Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Please also have a look at our

### Changed

- Remove `thecodingmachine/safe` dependency (#1482)
- Clean up extra whitespace in CSS selector (#1398)
- The array keys passed to `DeclarationBlock::setSelectors()` are no longer
preserved (#1407)
Expand Down
2 changes: 1 addition & 1 deletion bin/quickdump.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

use Sabberworm\CSS\Parser;

use function Safe\file_get_contents;
use function Sabberworm\CSS\Safe\file_get_contents;

/**
* This script is used for generating the examples in the README.
Expand Down
6 changes: 4 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@
"homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser",
"require": {
"php": "^7.2.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0",
"ext-iconv": "*",
"thecodingmachine/safe": "^1.3 || ^2.5 || ^3.3"
"ext-iconv": "*"
},
"require-dev": {
"php-parallel-lint/php-parallel-lint": "1.4.0",
Expand All @@ -44,6 +43,9 @@
"ext-mbstring": "for parsing UTF-8 CSS"
},
"autoload": {
"files": [
"src/Safe/safe_functions.php"
],
"psr-4": {
"Sabberworm\\CSS\\": "src/"
}
Expand Down
3 changes: 3 additions & 0 deletions config/phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ parameters:
- %currentWorkingDirectory%/src/
- %currentWorkingDirectory%/tests/

excludePaths:
- %currentWorkingDirectory%/src/Safe/safe_functions.php

type_perfect:
no_mixed_property: true
no_mixed_caller: true
Expand Down
2 changes: 1 addition & 1 deletion src/CSSList/CSSList.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
use Sabberworm\CSS\Value\URL;
use Sabberworm\CSS\Value\Value;

use function Safe\preg_match;
use function Sabberworm\CSS\Safe\preg_match;

/**
* This is the most generic container available. It can contain `DeclarationBlock`s (rule sets with a selector),
Expand Down
6 changes: 3 additions & 3 deletions src/Parsing/ParserState.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
use Sabberworm\CSS\Comment\Comment;
use Sabberworm\CSS\Settings;

use function Safe\iconv;
use function Safe\preg_match;
use function Safe\preg_split;
use function Sabberworm\CSS\Safe\iconv;
use function Sabberworm\CSS\Safe\preg_match;
use function Sabberworm\CSS\Safe\preg_split;

/**
* @internal since 8.7.0
Expand Down
4 changes: 2 additions & 2 deletions src/Property/Selector.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
use Sabberworm\CSS\Property\Selector\SpecificityCalculator;
use Sabberworm\CSS\Renderable;

use function Safe\preg_match;
use function Safe\preg_replace;
use function Sabberworm\CSS\Safe\preg_match;
use function Sabberworm\CSS\Safe\preg_replace;

/**
* Class representing a single CSS selector. Selectors have to be split by the comma prior to being passed into this
Expand Down
2 changes: 1 addition & 1 deletion src/Property/Selector/SpecificityCalculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Sabberworm\CSS\Property\Selector;

use function Safe\preg_match_all;
use function Sabberworm\CSS\Safe\preg_match_all;

/**
* Utility class to calculate the specificity of a CSS selector.
Expand Down
2 changes: 1 addition & 1 deletion src/Rule/Rule.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use Sabberworm\CSS\Value\RuleValueList;
use Sabberworm\CSS\Value\Value;

use function Safe\preg_match;
use function Sabberworm\CSS\Safe\preg_match;

/**
* `Rule`s just have a string key (the rule) and a 'Value'.
Expand Down
15 changes: 15 additions & 0 deletions src/Safe/Exceptions/DirException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Sabberworm\CSS\Safe\Exceptions;

class DirException extends \ErrorException implements SafeExceptionInterface
{
public static function createFromPhpError(): self
{
$error = \error_get_last();

return new self($error['message'] ?? 'An error occurred', 0, $error['type'] ?? 1);
}
}
15 changes: 15 additions & 0 deletions src/Safe/Exceptions/FilesystemException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Sabberworm\CSS\Safe\Exceptions;

class FilesystemException extends \ErrorException implements SafeExceptionInterface
{
public static function createFromPhpError(): self
{
$error = \error_get_last();

return new self($error['message'] ?? 'An error occurred', 0, $error['type'] ?? 1);
}
}
15 changes: 15 additions & 0 deletions src/Safe/Exceptions/IconvException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Sabberworm\CSS\Safe\Exceptions;

class IconvException extends \ErrorException implements SafeExceptionInterface
{
public static function createFromPhpError(): self
{
$error = \error_get_last();

return new self($error['message'] ?? 'An error occurred', 0, $error['type'] ?? 1);
}
}
23 changes: 23 additions & 0 deletions src/Safe/Exceptions/PcreException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Sabberworm\CSS\Safe\Exceptions;

class PcreException extends \Exception implements SafeExceptionInterface
{
public static function createFromPhpError(): self
{
$errorMap = [
PREG_INTERNAL_ERROR => 'PREG_INTERNAL_ERROR: Internal error',
PREG_BACKTRACK_LIMIT_ERROR => 'PREG_BACKTRACK_LIMIT_ERROR: Backtrack limit reached',
PREG_RECURSION_LIMIT_ERROR => 'PREG_RECURSION_LIMIT_ERROR: Recursion limit reached',
PREG_BAD_UTF8_ERROR => 'PREG_BAD_UTF8_ERROR: Invalid UTF8 character',
PREG_BAD_UTF8_OFFSET_ERROR => 'PREG_BAD_UTF8_OFFSET_ERROR',
PREG_JIT_STACKLIMIT_ERROR => 'PREG_JIT_STACKLIMIT_ERROR',
];
$errMsg = $errorMap[\preg_last_error()] ?? 'Unknown PCRE error: ' . \preg_last_error();

return new self($errMsg, \preg_last_error());
}
}
9 changes: 9 additions & 0 deletions src/Safe/Exceptions/SafeExceptionInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace Sabberworm\CSS\Safe\Exceptions;

interface SafeExceptionInterface extends \Throwable
{
}
194 changes: 194 additions & 0 deletions src/Safe/safe_functions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
<?php

declare(strict_types=1);

/**
* These functions have been absorbed from "thecodingmachine/safe" to avoid a dependency.
*
* See: https://github.com/thecodingmachine/safe
*/

namespace Sabberworm\CSS\Safe;

use Sabberworm\CSS\Safe\Exceptions\DirException;
use Sabberworm\CSS\Safe\Exceptions\FilesystemException;
use Sabberworm\CSS\Safe\Exceptions\IconvException;
use Sabberworm\CSS\Safe\Exceptions\PcreException;

use const PREG_NO_ERROR;

/**
* Searches subject for a match to the regular expression given in pattern.
*
* @param string $pattern The pattern to search for, as a string.
* @param string $subject The input string.
* @param null|string[] $matches If matches is provided, then it is filled with the results of search.
* @param int $flags Can be a combination of flags.
* @param int $offset Offset from which to start the search (in bytes).
*
* @return 0|1 Returns 1 if the pattern matches given subject, 0 if it does not.
*
* @throws PcreException
*/
function preg_match(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): int
{
\error_clear_last();
$safeResult = \preg_match($pattern, $subject, $matches, $flags, $offset);
if ($safeResult === false) {
throw PcreException::createFromPhpError();
}

return $safeResult;
}

/**
* Searches subject for all matches to the regular expression given in pattern
* and puts them in matches in the order specified by flags.
*
* @param string $pattern The pattern to search for, as a string.
* @param string $subject The input string.
* @param array|null $matches Array of all matches in multi-dimensional array ordered according to flags.
* @param int $flags Can be a combination of flags.
* @param int $offset Offset from which to start the search (in bytes).
*
* @return 0|positive-int Returns the number of full pattern matches (which might be zero).
*
* @throws PcreException
*/
function preg_match_all(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): int
{
\error_clear_last();
$safeResult = \preg_match_all($pattern, $subject, $matches, $flags, $offset);
if ($safeResult === false) {
throw PcreException::createFromPhpError();
}

return $safeResult;
}

/**
* Split the given string by a regular expression.
*
* @param string $pattern The pattern to search for, as a string.
* @param string $subject The input string.
* @param int|null $limit If specified, then only substrings up to limit are returned.
* @param int $flags Can be any combination of flags.
*
* @return list<string> Returns an array containing substrings of subject split along boundaries matched by pattern.
*
* @throws PcreException
*/
function preg_split(string $pattern, string $subject, ?int $limit = -1, int $flags = 0): array
{
\error_clear_last();
$safeResult = \preg_split($pattern, $subject, $limit, $flags);
if ($safeResult === false) {
throw PcreException::createFromPhpError();
}

return $safeResult;
}

/**
* Searches subject for matches to pattern and replaces them with replacement.
*
* @param string[]|string $pattern The pattern to search for.
* @param string[]|string $replacement The string or an array with strings to replace.
* @param string|array|string[] $subject The string or an array with strings to search and replace.
* @param int $limit The maximum possible replacements for each pattern. Defaults to -1 (no limit).
* @param int $count If specified, this variable will be filled with the number of replacements done.
* @param-out int $count
*
* @return string|array|string[] Returns an array if the subject parameter is an array, or a string otherwise.
*
* @throws PcreException
*/
function preg_replace($pattern, $replacement, $subject, int $limit = -1, ?int &$count = null)
{
\error_clear_last();
$result = \preg_replace($pattern, $replacement, $subject, $limit, $count);
if (\preg_last_error() !== PREG_NO_ERROR || $result === null) {
throw PcreException::createFromPhpError();
}

return $result;
}

/**
* Performs a character set conversion on the string from from_encoding to to_encoding.
*
* @param string $from_encoding The input charset.
* @param string $to_encoding The output charset.
* @param string $string The string to be converted.
*
* @return string Returns the converted string.
*
* @throws IconvException
*/
function iconv(string $from_encoding, string $to_encoding, string $string): string
{
\error_clear_last();
$safeResult = \iconv($from_encoding, $to_encoding, $string);
if ($safeResult === false) {
throw IconvException::createFromPhpError();
}

return $safeResult;
}

/**
* This function is similar to file, except that file_get_contents returns the file in a string.
*
* @param string $filename Name of the file to read.
* @param bool $use_include_path Whether to search in the include path.
* @param resource|null $context A valid context resource created with stream_context_create.
* @param int $offset The offset where the reading starts on the original stream.
* @param 0|positive-int $length Maximum length of data read.
*
* @return string The function returns the read data.
*
* @throws FilesystemException
*/
function file_get_contents(string $filename, bool $use_include_path = false, $context = null, int $offset = 0, ?int $length = null): string
{
\error_clear_last();
if ($length !== null) {
$safeResult = \file_get_contents($filename, $use_include_path, $context, $offset, $length);
} elseif ($offset !== 0) {
$safeResult = \file_get_contents($filename, $use_include_path, $context, $offset);
} elseif ($context !== null) {
$safeResult = \file_get_contents($filename, $use_include_path, $context);
} else {
$safeResult = \file_get_contents($filename, $use_include_path);
}
if ($safeResult === false) {
throw FilesystemException::createFromPhpError();
}

return $safeResult;
}

/**
* Opens up a directory handle to be used in subsequent closedir, readdir, and rewinddir calls.
*
* @param string $directory The directory path that is to be opened.
* @param resource|null $context For a description of the context parameter, refer to the streams section.
*
* @return resource Returns a directory handle resource on success.
*
* @throws DirException
*/
function opendir(string $directory, $context = null)
{
\error_clear_last();
if ($context !== null) {
$safeResult = \opendir($directory, $context);
} else {
$safeResult = \opendir($directory);
}
if ($safeResult === false) {
throw DirException::createFromPhpError();
}

return $safeResult;
}
2 changes: 1 addition & 1 deletion src/Value/CSSString.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use Sabberworm\CSS\Parsing\UnexpectedTokenException;
use Sabberworm\CSS\ShortClassNameProvider;

use function Safe\preg_match;
use function Sabberworm\CSS\Safe\preg_match;

/**
* This class is a wrapper for quoted strings to distinguish them from keywords.
Expand Down
2 changes: 1 addition & 1 deletion src/Value/CalcFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use Sabberworm\CSS\Parsing\UnexpectedEOFException;
use Sabberworm\CSS\Parsing\UnexpectedTokenException;

use function Safe\preg_match;
use function Sabberworm\CSS\Safe\preg_match;

class CalcFunction extends CSSFunction
{
Expand Down
Loading
Loading