Skip to content

Commit

Permalink
Strings, Arrays, Json, Image: $flags replaced with parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Oct 26, 2021
1 parent 694130e commit fd0a5c0
Show file tree
Hide file tree
Showing 11 changed files with 150 additions and 32 deletions.
3 changes: 2 additions & 1 deletion src/Utils/Arrays.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,9 @@ public static function renameKey(array &$array, string|int $oldKey, string|int $
* @param string[] $array
* @return string[]
*/
public static function grep(array $array, string $pattern, int $flags = 0): array
public static function grep(array $array, string $pattern, bool|int $invert = false): array
{
$flags = $invert ? PREG_GREP_INVERT : 0;
return Strings::pcre('preg_grep', [$pattern, $array, $flags]);
}

Expand Down
29 changes: 18 additions & 11 deletions src/Utils/Image.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class Image
{
use Nette\SmartObject;

/** {@link resize()} only shrinks images */
/** @deprecated */
public const SHRINK_ONLY = 0b0001;

/** {@link resize()} will ignore aspect ratio */
Expand Down Expand Up @@ -303,14 +303,19 @@ public function getImageResource(): \GdImage

/**
* Scales an image. Width and height accept pixels or percent.
* @param self::FIT|self::FILL|self::STRETCH|self::EXACT $mode
*/
public function resize(int|string|null $width, int|string|null $height, int $flags = self::FIT): static
{
if ($flags & self::EXACT) {
public function resize(
int|string|null $width,
int|string|null $height,
int $mode = self::FIT,
bool $shrinkOnly = false,
): static {
if ($mode & self::EXACT) {
return $this->resize($width, $height, self::FILL)->crop('50%', '50%', $width, $height);
}

[$newWidth, $newHeight] = static::calculateSize($this->getWidth(), $this->getHeight(), $width, $height, $flags);
[$newWidth, $newHeight] = static::calculateSize($this->getWidth(), $this->getHeight(), $width, $height, $mode, $shrinkOnly);

if ($newWidth !== $this->getWidth() || $newHeight !== $this->getHeight()) { // resize
$newImage = static::fromBlank($newWidth, $newHeight, self::rgb(0, 0, 0, 127))->getImageResource();
Expand Down Expand Up @@ -338,13 +343,15 @@ public function resize(int|string|null $width, int|string|null $height, int $fla

/**
* Calculates dimensions of resized image. Width and height accept pixels or percent.
* @param self::FIT|self::FILL|self::STRETCH $mode
*/
public static function calculateSize(
int $srcWidth,
int $srcHeight,
$newWidth,
$newHeight,
int $flags = self::FIT,
int $mode = self::FIT,
bool $shrinkOnly = false,
): array {
if ($newWidth === null) {
} elseif (self::isPercent($newWidth)) {
Expand All @@ -357,17 +364,17 @@ public static function calculateSize(
if ($newHeight === null) {
} elseif (self::isPercent($newHeight)) {
$newHeight = (int) round($srcHeight / 100 * abs($newHeight));
$flags |= empty($percents) ? 0 : self::STRETCH;
$mode |= empty($percents) ? 0 : self::STRETCH;
} else {
$newHeight = abs($newHeight);
}

if ($flags & self::STRETCH) { // non-proportional
if ($mode & self::STRETCH) { // non-proportional
if (!$newWidth || !$newHeight) {
throw new Nette\InvalidArgumentException('For stretching must be both width and height specified.');
}

if ($flags & self::SHRINK_ONLY) {
if ($mode & self::SHRINK_ONLY || $shrinkOnly) {
$newWidth = (int) round($srcWidth * min(1, $newWidth / $srcWidth));
$newHeight = (int) round($srcHeight * min(1, $newHeight / $srcHeight));
}
Expand All @@ -386,11 +393,11 @@ public static function calculateSize(
$scale[] = $newHeight / $srcHeight;
}

if ($flags & self::FILL) {
if ($mode & self::FILL) {
$scale = [max($scale)];
}

if ($flags & self::SHRINK_ONLY) {
if ($mode & self::SHRINK_ONLY || $shrinkOnly) {
$scale[] = 1;
}

Expand Down
29 changes: 19 additions & 10 deletions src/Utils/Json.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,33 @@ final class Json
{
use Nette\StaticClass;

/** @deprecated */
public const FORCE_ARRAY = 0b0001;

/** @deprecated */
public const PRETTY = 0b0010;

/** @deprecated */
public const ESCAPE_UNICODE = 0b0100;


/**
* Converts value to JSON format. The flag can be Json::PRETTY, which formats JSON for easier reading and clarity,
* and Json::ESCAPE_UNICODE for ASCII output.
* Converts value to JSON format. Parameter $flags is deprecated. Use $pretty for easier reading and clarity,
* and $escapeUnicode for ASCII output.
* @throws JsonException
*/
public static function encode(mixed $value, int $flags = 0): string
{
$flags = ($flags & self::ESCAPE_UNICODE ? 0 : JSON_UNESCAPED_UNICODE)
public static function encode(
mixed $value,
bool|int $pretty = false,
bool $escapeUnicode = false,
): string {
if (is_int($pretty)) { // back compatibility
$escapeUnicode = $pretty & self::ESCAPE_UNICODE;
$pretty &= self::PRETTY;
}
$flags = ($escapeUnicode ? 0 : JSON_UNESCAPED_UNICODE)
| JSON_UNESCAPED_SLASHES
| ($flags & self::PRETTY ? JSON_PRETTY_PRINT : 0)
| ($pretty ? JSON_PRETTY_PRINT : 0)
| (defined('JSON_PRESERVE_ZERO_FRACTION') ? JSON_PRESERVE_ZERO_FRACTION : 0); // since PHP 5.6.6 & PECL JSON-C 1.3.7

$json = json_encode($value, $flags);
Expand All @@ -47,13 +57,12 @@ public static function encode(mixed $value, int $flags = 0): string


/**
* Parses JSON to PHP value. The flag can be Json::FORCE_ARRAY, which forces an array instead of an object as the return value.
* Parses JSON to PHP value. Parameter $forceArray forces an array instead of an object as the return value.
* @throws JsonException
*/
public static function decode(string $json, int $flags = 0): mixed
public static function decode(string $json, bool|int $forceArray = false): mixed
{
$forceArray = (bool) ($flags & self::FORCE_ARRAY);
$value = json_decode($json, $forceArray, 512, JSON_BIGINT_AS_STRING);
$value = json_decode($json, (bool) $forceArray, 512, JSON_BIGINT_AS_STRING);
if ($error = json_last_error()) {
throw new JsonException(json_last_error_msg(), $error);
}
Expand Down
42 changes: 32 additions & 10 deletions src/Utils/Strings.php
Original file line number Diff line number Diff line change
Expand Up @@ -468,20 +468,33 @@ private static function pos(string $haystack, string $needle, int $nth = 1): ?in

/**
* Splits a string into array by the regular expression. Parenthesized expression in the delimiter are captured.
* Parameter $flags can be any combination of PREG_SPLIT_NO_EMPTY and PREG_OFFSET_CAPTURE flags.
*/
public static function split(string $subject, string $pattern, int $flags = 0): array
{
public static function split(
string $subject,
string $pattern,
bool|int $captureOffset = false,
bool $skipEmpty = false,
): array {
$flags = is_int($captureOffset) // back compatibility
? $captureOffset
: ($captureOffset ? PREG_SPLIT_OFFSET_CAPTURE : 0) | ($skipEmpty ? PREG_SPLIT_NO_EMPTY : 0);
return self::pcre('preg_split', [$pattern, $subject, -1, $flags | PREG_SPLIT_DELIM_CAPTURE]);
}


/**
* Checks if given string matches a regular expression pattern and returns an array with first found match and each subpattern.
* Parameter $flags can be any combination of PREG_OFFSET_CAPTURE and PREG_UNMATCHED_AS_NULL flags.
*/
public static function match(string $subject, string $pattern, int $flags = 0, int $offset = 0): ?array
{
public static function match(
string $subject,
string $pattern,
bool|int $captureOffset = false,
int $offset = 0,
bool $unmatchedAsNull = false,
): ?array {
$flags = is_int($captureOffset) // back compatibility
? $captureOffset
: ($captureOffset ? PREG_OFFSET_CAPTURE : 0) | ($unmatchedAsNull ? PREG_UNMATCHED_AS_NULL : 0);
if ($offset > strlen($subject)) {
return null;
}
Expand All @@ -492,11 +505,20 @@ public static function match(string $subject, string $pattern, int $flags = 0, i


/**
* Finds all occurrences matching regular expression pattern and returns a two-dimensional array. Result is array of matches (ie uses by default PREG_SET_ORDER).
* Parameter $flags can be any combination of PREG_OFFSET_CAPTURE, PREG_UNMATCHED_AS_NULL and PREG_PATTERN_ORDER flags.
* Finds all occurrences matching regular expression pattern and returns a two-dimensional array.
* Result is array of matches (ie uses by default PREG_SET_ORDER).
*/
public static function matchAll(string $subject, string $pattern, int $flags = 0, int $offset = 0): array
{
public static function matchAll(
string $subject,
string $pattern,
bool|int $captureOffset = false,
int $offset = 0,
bool $unmatchedAsNull = false,
bool $patternOrder = false,
): array {
$flags = is_int($captureOffset) // back compatibility
? $captureOffset
: ($captureOffset ? PREG_OFFSET_CAPTURE : 0) | ($unmatchedAsNull ? PREG_UNMATCHED_AS_NULL : 0) | ($patternOrder ? PREG_PATTERN_ORDER : 0);
if ($offset > strlen($subject)) {
return [];
}
Expand Down
5 changes: 5 additions & 0 deletions tests/Utils/Arrays.grep().phpt
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@ Assert::same([
0 => 'a',
2 => 'c',
], Arrays::grep(['a', '1', 'c'], '#\d#', PREG_GREP_INVERT));

Assert::same([
0 => 'a',
2 => 'c',
], Arrays::grep(['a', '1', 'c'], '#\d#', invert: true));
40 changes: 40 additions & 0 deletions tests/Utils/Image.resize.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ test('resizing Y shrink', function () use ($main) {
});


test('resizing Y shrink', function () use ($main) {
$image = clone $main;
$image->resize(null, 150, shrinkOnly: true);
Assert::same(176, $image->width);
Assert::same(104, $image->height);
});


test('resizing X Y shrink', function () use ($main) {
$image = clone $main;
$image->resize(300, 150, Image::SHRINK_ONLY);
Expand All @@ -60,6 +68,14 @@ test('resizing X Y shrink', function () use ($main) {
});


test('resizing X Y shrink', function () use ($main) {
$image = clone $main;
$image->resize(300, 150, shrinkOnly: true);
Assert::same(176, $image->width);
Assert::same(104, $image->height);
});


test('resizing X Y', function () use ($main) {
$image = clone $main;
$image->resize(300, 150);
Expand All @@ -84,6 +100,14 @@ test('resizing X Y shrink stretch', function () use ($main) {
});


test('resizing X Y shrink stretch', function () use ($main) {
$image = clone $main;
$image->resize(300, 100, Image::STRETCH, shrinkOnly: true);
Assert::same(176, $image->width);
Assert::same(100, $image->height);
});


test('resizing X%', function () use ($main) {
$image = clone $main;
$image->resize('110%', null);
Expand Down Expand Up @@ -116,6 +140,14 @@ test('flipping Y shrink', function () use ($main) {
});


test('flipping Y shrink', function () use ($main) {
$image = clone $main;
$image->resize(null, -150, shrinkOnly: true);
Assert::same(176, $image->width);
Assert::same(104, $image->height);
});


test('flipping X Y shrink', function () use ($main) {
$image = clone $main;
$image->resize(-300, -150, Image::SHRINK_ONLY);
Expand All @@ -124,6 +156,14 @@ test('flipping X Y shrink', function () use ($main) {
});


test('flipping X Y shrink', function () use ($main) {
$image = clone $main;
$image->resize(-300, -150, shrinkOnly: true);
Assert::same(176, $image->width);
Assert::same(104, $image->height);
});


test('exact resize', function () use ($main) {
$image = clone $main;
$image->resize(300, 150, Image::EXACT);
Expand Down
1 change: 1 addition & 0 deletions tests/Utils/Json.decode().phpt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Assert::null(Json::decode(' null'));

Assert::equal((object) ['a' => 1], Json::decode('{"a":1}'));
Assert::same(['a' => 1], Json::decode('{"a":1}', Json::FORCE_ARRAY));
Assert::same(['a' => 1], Json::decode('{"a":1}', forceArray: true));


Assert::exception(function () {
Expand Down
2 changes: 2 additions & 0 deletions tests/Utils/Json.encode().phpt
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ Assert::same('"\u2028\u2029"', Json::encode("\u{2028}\u{2029}"));
// ESCAPE_UNICODE
Assert::same('"/I\u00f1t\u00ebrn\u00e2ti\u00f4n\u00e0liz\u00e6ti\u00f8n"', Json::encode("/I\u{F1}t\u{EB}rn\u{E2}ti\u{F4}n\u{E0}liz\u{E6}ti\u{F8}n", Json::ESCAPE_UNICODE));
Assert::same('"\u2028\u2029"', Json::encode("\u{2028}\u{2029}", Json::ESCAPE_UNICODE));
Assert::same('"\u2028\u2029"', Json::encode("\u{2028}\u{2029}", escapeUnicode: true));


// JSON_PRETTY_PRINT
Assert::same("[\n 1,\n 2,\n 3\n]", Json::encode([1, 2, 3], Json::PRETTY));
Assert::same("[\n 1,\n 2,\n 3\n]", Json::encode([1, 2, 3], pretty: true));


Assert::exception(function () {
Expand Down
1 change: 1 addition & 0 deletions tests/Utils/Strings.match().phpt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Assert::same(['hell', 'l'], Strings::match('hello world!', '#([e-l])+#'));
Assert::same(['hell'], Strings::match('hello world!', '#[e-l]+#'));

Assert::same([['hell', 0]], Strings::match('hello world!', '#[e-l]+#', PREG_OFFSET_CAPTURE));
Assert::same([['hell', 0]], Strings::match('hello world!', '#[e-l]+#', captureOffset: true));

Assert::same(['ll'], Strings::match('hello world!', '#[e-l]+#', 0, 2));

Expand Down
14 changes: 14 additions & 0 deletions tests/Utils/Strings.matchAll().phpt
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,28 @@ Assert::same([
[['k', 14], ['k', 14], ['', 15]],
], Strings::matchAll('žluťoučký kůň!', '#([a-z])([a-z]*)#u', PREG_OFFSET_CAPTURE));

Assert::same([
[['lu', 2], ['l', 2], ['u', 3]],
[['ou', 6], ['o', 6], ['u', 7]],
[['k', 10], ['k', 10], ['', 11]],
[['k', 14], ['k', 14], ['', 15]],
], Strings::matchAll('žluťoučký kůň!', '#([a-z])([a-z]*)#u', captureOffset: true));

Assert::same([
[['lu', 2], ['ou', 6], ['k', 10], ['k', 14]],
[['l', 2], ['o', 6], ['k', 10], ['k', 14]],
[['u', 3], ['u', 7], ['', 11], ['', 15]],
], Strings::matchAll('žluťoučký kůň!', '#([a-z])([a-z]*)#u', PREG_OFFSET_CAPTURE | PREG_PATTERN_ORDER));

Assert::same([
[['lu', 2], ['ou', 6], ['k', 10], ['k', 14]],
[['l', 2], ['o', 6], ['k', 10], ['k', 14]],
[['u', 3], ['u', 7], ['', 11], ['', 15]],
], Strings::matchAll('žluťoučký kůň!', '#([a-z])([a-z]*)#u', captureOffset: true, patternOrder: true));

Assert::same([['l'], ['k'], ['k']], Strings::matchAll('žluťoučký kůň', '#[e-l]+#u', 0, 2));

Assert::same([['ll', 'l']], Strings::matchAll('hello world!', '#[e-l]+#', PREG_PATTERN_ORDER, 2));
Assert::same([['ll', 'l']], Strings::matchAll('hello world!', '#[e-l]+#', patternOrder: true, offset: 2));

Assert::same([], Strings::matchAll('hello world!', '', 0, 50));
16 changes: 16 additions & 0 deletions tests/Utils/Strings.split().phpt
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,26 @@ Assert::same([
'c',
], Strings::split('a, b, c', '#(,)\s*#', PREG_SPLIT_NO_EMPTY));

Assert::same([
'a',
',',
'b',
',',
'c',
], Strings::split('a, b, c', '#(,)\s*#', skipEmpty: true));

Assert::same([
['a', 0],
[',', 1],
['b', 3],
[',', 4],
['c', 6],
], Strings::split('a, b, c', '#(,)\s*#', PREG_SPLIT_OFFSET_CAPTURE));

Assert::same([
['a', 0],
[',', 1],
['b', 3],
[',', 4],
['c', 6],
], Strings::split('a, b, c', '#(,)\s*#', captureOffset: true));

0 comments on commit fd0a5c0

Please sign in to comment.