From 4ce65d59ca91871cfd126497158200a818720bce Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 13 Apr 2024 13:30:08 +0200 Subject: Adding upstream version 0.13.1. Signed-off-by: Daniel Baumann --- vendor/ipl/stdlib/src/BaseFilter.php | 45 ++ vendor/ipl/stdlib/src/Contract/Filterable.php | 63 +++ vendor/ipl/stdlib/src/Contract/Paginatable.php | 56 ++ .../stdlib/src/Contract/PaginationInterface.php | 8 + vendor/ipl/stdlib/src/Contract/PluginLoader.php | 21 + vendor/ipl/stdlib/src/Contract/Translator.php | 65 +++ vendor/ipl/stdlib/src/Contract/Validator.php | 22 + .../ipl/stdlib/src/Contract/ValidatorInterface.php | 8 + vendor/ipl/stdlib/src/Data.php | 89 ++++ vendor/ipl/stdlib/src/EventEmitter.php | 9 + vendor/ipl/stdlib/src/Events.php | 57 ++ vendor/ipl/stdlib/src/Filter.php | 584 +++++++++++++++++++++ vendor/ipl/stdlib/src/Filter/All.php | 7 + vendor/ipl/stdlib/src/Filter/Any.php | 7 + vendor/ipl/stdlib/src/Filter/Chain.php | 179 +++++++ vendor/ipl/stdlib/src/Filter/Condition.php | 84 +++ vendor/ipl/stdlib/src/Filter/Equal.php | 31 ++ vendor/ipl/stdlib/src/Filter/GreaterThan.php | 7 + .../ipl/stdlib/src/Filter/GreaterThanOrEqual.php | 7 + vendor/ipl/stdlib/src/Filter/LessThan.php | 7 + vendor/ipl/stdlib/src/Filter/LessThanOrEqual.php | 7 + vendor/ipl/stdlib/src/Filter/Like.php | 31 ++ vendor/ipl/stdlib/src/Filter/MetaData.php | 20 + vendor/ipl/stdlib/src/Filter/MetaDataProvider.php | 15 + vendor/ipl/stdlib/src/Filter/None.php | 7 + vendor/ipl/stdlib/src/Filter/Rule.php | 7 + vendor/ipl/stdlib/src/Filter/Unequal.php | 31 ++ vendor/ipl/stdlib/src/Filter/Unlike.php | 31 ++ vendor/ipl/stdlib/src/Filters.php | 58 ++ .../stdlib/src/Loader/AutoloadingPluginLoader.php | 52 ++ vendor/ipl/stdlib/src/MessageContainer.php | 9 + vendor/ipl/stdlib/src/Messages.php | 92 ++++ vendor/ipl/stdlib/src/Plugins.php | 95 ++++ vendor/ipl/stdlib/src/PriorityQueue.php | 42 ++ vendor/ipl/stdlib/src/Properties.php | 205 ++++++++ vendor/ipl/stdlib/src/Seq.php | 111 ++++ vendor/ipl/stdlib/src/Str.php | 93 ++++ vendor/ipl/stdlib/src/functions.php | 128 +++++ vendor/ipl/stdlib/src/functions_include.php | 6 + 39 files changed, 2396 insertions(+) create mode 100644 vendor/ipl/stdlib/src/BaseFilter.php create mode 100644 vendor/ipl/stdlib/src/Contract/Filterable.php create mode 100644 vendor/ipl/stdlib/src/Contract/Paginatable.php create mode 100644 vendor/ipl/stdlib/src/Contract/PaginationInterface.php create mode 100644 vendor/ipl/stdlib/src/Contract/PluginLoader.php create mode 100644 vendor/ipl/stdlib/src/Contract/Translator.php create mode 100644 vendor/ipl/stdlib/src/Contract/Validator.php create mode 100644 vendor/ipl/stdlib/src/Contract/ValidatorInterface.php create mode 100644 vendor/ipl/stdlib/src/Data.php create mode 100644 vendor/ipl/stdlib/src/EventEmitter.php create mode 100644 vendor/ipl/stdlib/src/Events.php create mode 100644 vendor/ipl/stdlib/src/Filter.php create mode 100644 vendor/ipl/stdlib/src/Filter/All.php create mode 100644 vendor/ipl/stdlib/src/Filter/Any.php create mode 100644 vendor/ipl/stdlib/src/Filter/Chain.php create mode 100644 vendor/ipl/stdlib/src/Filter/Condition.php create mode 100644 vendor/ipl/stdlib/src/Filter/Equal.php create mode 100644 vendor/ipl/stdlib/src/Filter/GreaterThan.php create mode 100644 vendor/ipl/stdlib/src/Filter/GreaterThanOrEqual.php create mode 100644 vendor/ipl/stdlib/src/Filter/LessThan.php create mode 100644 vendor/ipl/stdlib/src/Filter/LessThanOrEqual.php create mode 100644 vendor/ipl/stdlib/src/Filter/Like.php create mode 100644 vendor/ipl/stdlib/src/Filter/MetaData.php create mode 100644 vendor/ipl/stdlib/src/Filter/MetaDataProvider.php create mode 100644 vendor/ipl/stdlib/src/Filter/None.php create mode 100644 vendor/ipl/stdlib/src/Filter/Rule.php create mode 100644 vendor/ipl/stdlib/src/Filter/Unequal.php create mode 100644 vendor/ipl/stdlib/src/Filter/Unlike.php create mode 100644 vendor/ipl/stdlib/src/Filters.php create mode 100644 vendor/ipl/stdlib/src/Loader/AutoloadingPluginLoader.php create mode 100644 vendor/ipl/stdlib/src/MessageContainer.php create mode 100644 vendor/ipl/stdlib/src/Messages.php create mode 100644 vendor/ipl/stdlib/src/Plugins.php create mode 100644 vendor/ipl/stdlib/src/PriorityQueue.php create mode 100644 vendor/ipl/stdlib/src/Properties.php create mode 100644 vendor/ipl/stdlib/src/Seq.php create mode 100644 vendor/ipl/stdlib/src/Str.php create mode 100644 vendor/ipl/stdlib/src/functions.php create mode 100644 vendor/ipl/stdlib/src/functions_include.php (limited to 'vendor/ipl/stdlib/src') diff --git a/vendor/ipl/stdlib/src/BaseFilter.php b/vendor/ipl/stdlib/src/BaseFilter.php new file mode 100644 index 0000000..267decb --- /dev/null +++ b/vendor/ipl/stdlib/src/BaseFilter.php @@ -0,0 +1,45 @@ +baseFilter !== null; + } + + /** + * Get the base filter + * + * @return ?Rule + */ + public function getBaseFilter() + { + return $this->baseFilter; + } + + /** + * Set the base filter + * + * @param Rule $baseFilter + * + * @return $this + */ + public function setBaseFilter(Rule $baseFilter = null): self + { + $this->baseFilter = $baseFilter; + + return $this; + } +} diff --git a/vendor/ipl/stdlib/src/Contract/Filterable.php b/vendor/ipl/stdlib/src/Contract/Filterable.php new file mode 100644 index 0000000..2a6316a --- /dev/null +++ b/vendor/ipl/stdlib/src/Contract/Filterable.php @@ -0,0 +1,63 @@ + + */ + public function getMessages(); +} diff --git a/vendor/ipl/stdlib/src/Contract/ValidatorInterface.php b/vendor/ipl/stdlib/src/Contract/ValidatorInterface.php new file mode 100644 index 0000000..36cf55e --- /dev/null +++ b/vendor/ipl/stdlib/src/Contract/ValidatorInterface.php @@ -0,0 +1,8 @@ + */ + protected $data = []; + + /** + * Check whether there's any data + * + * @return bool + */ + public function isEmpty() + { + return empty($this->data); + } + + /** + * Check whether the given data exists + * + * @param string $name The name of the data + * + * @return bool + */ + public function has($name) + { + return array_key_exists($name, $this->data); + } + + /** + * Get the value of the given data + * + * @param string $name The name of the data + * @param mixed $default The value to return if there's no such data + * + * @return mixed + */ + public function get($name, $default = null) + { + if ($this->has($name)) { + return $this->data[$name]; + } + + return $default; + } + + /** + * Set the value of the given data + * + * @param string $name The name of the data + * @param mixed $value + * + * @return $this + */ + public function set($name, $value) + { + $this->data[$name] = $value; + + return $this; + } + + /** + * Merge the given data + * + * @param Data $with + * + * @return $this + */ + public function merge(self $with) + { + $this->data = array_merge($this->data, $with->data); + + return $this; + } + + /** + * Clear all data + * + * @return $this + */ + public function clear() + { + $this->data = []; + + return $this; + } +} diff --git a/vendor/ipl/stdlib/src/EventEmitter.php b/vendor/ipl/stdlib/src/EventEmitter.php new file mode 100644 index 0000000..6d189ee --- /dev/null +++ b/vendor/ipl/stdlib/src/EventEmitter.php @@ -0,0 +1,9 @@ +eventsEmittedOnce[$event])) { + $this->eventsEmittedOnce[$event] = true; + $this->emit($event, $arguments); + } + } + + /** + * @param string $event + * @param callable $listener + * @return $this + */ + public function on($event, callable $listener) + { + $this->assertValidEvent($event); + $this->evenementUnvalidatedOn($event, $listener); + + return $this; + } + + protected function assertValidEvent($event) + { + if (! $this->isValidEvent($event)) { + throw new InvalidArgumentException("$event is not a valid event"); + } + } + + /** + * @param string $event + * @return bool + */ + public function isValidEvent($event) + { + return true; + } +} diff --git a/vendor/ipl/stdlib/src/Filter.php b/vendor/ipl/stdlib/src/Filter.php new file mode 100644 index 0000000..9523f1f --- /dev/null +++ b/vendor/ipl/stdlib/src/Filter.php @@ -0,0 +1,584 @@ +|object $row + * + * @return bool + */ + public static function match(Rule $rule, $row) + { + if (! is_object($row)) { + if (is_array($row)) { + $row = (object) $row; + } else { + throw new InvalidArgumentException(sprintf( + 'Object or array expected, got %s instead', + get_php_type($row) + )); + } + } + + return (new self())->performMatch($rule, $row); + } + + /** + * Create a rule that matches if **all** of the given rules do + * + * @param Rule ...$rules + * + * @return Chain + */ + public static function all(Rule ...$rules) + { + return new All(...$rules); + } + + /** + * Return whether the given rules all match the given item + * + * @param All $rules + * @param object $row + * + * @return bool + */ + protected function matchAll(All $rules, $row) + { + foreach ($rules as $rule) { + if (! $this->performMatch($rule, $row)) { + return false; + } + } + + return true; + } + + /** + * Create a rule that matches if **any** of the given rules do + * + * @param Rule ...$rules + * + * @return Chain + */ + public static function any(Rule ...$rules) + { + return new Any(...$rules); + } + + /** + * Return whether any of the given rules match the given item + * + * @param Any $rules + * @param object $row + * + * @return bool + */ + protected function matchAny(Any $rules, $row) + { + foreach ($rules as $rule) { + if ($this->performMatch($rule, $row)) { + return true; + } + } + + return false; + } + + /** + * Create a rule that matches if **none** of the given rules do + * + * @param Rule ...$rules + * + * @return Chain + */ + public static function none(Rule ...$rules) + { + return new None(...$rules); + } + + /** + * Return whether none of the given rules match the given item + * + * @param None $rules + * @param object $row + * + * @return bool + */ + protected function matchNone(None $rules, $row) + { + foreach ($rules as $rule) { + if ($this->performMatch($rule, $row)) { + return false; + } + } + + return true; + } + + /** + * Create a rule that matches rows with a column that **equals** the given value + * + * @param string $column + * @param array|bool|float|int|string $value + * + * @return Condition + */ + public static function equal($column, $value) + { + return new Equal($column, $value); + } + + /** + * Return whether the given rule's value equals the given item's value + * + * @param Equal|Unequal $rule + * @param object $row + * + * @return bool + */ + protected function matchEqual($rule, $row) + { + if (! $rule instanceof Equal && ! $rule instanceof Unequal) { + throw new InvalidArgumentException(sprintf( + 'Rule must be of type %s or %s, got %s instead', + Equal::class, + Unequal::class, + get_php_type($rule) + )); + } + + $rowValue = $this->extractValue($rule->getColumn(), $row); + $value = $rule->getValue(); + $this->normalizeTypes($rowValue, $value); + + if (! is_array($rowValue)) { + $rowValue = [$rowValue]; + } + + foreach ($rowValue as $rowVal) { + if ($this->performEqualityMatch($value, $rowVal, $rule->ignoresCase())) { + return true; + } + } + + return false; + } + + /** + * Create a rule that matches rows with a column that is **similar** to the given value + * + * Performs a wildcard search if the value contains asterisks. + * + * @param string $column + * @param string|string[] $value + * + * @return Condition + */ + public static function like($column, $value) + { + return new Like($column, $value); + } + + /** + * Return whether the given rule's value is similar to the given item's value + * + * @param Like|Unlike $rule + * @param object $row + * + * @return bool + */ + protected function matchSimilar($rule, $row) + { + if (! $rule instanceof Like && ! $rule instanceof Unlike) { + throw new InvalidArgumentException(sprintf( + 'Rule must be of type %s or %s, got %s instead', + Like::class, + Unlike::class, + get_php_type($rule) + )); + } + + $rowValue = $this->extractValue($rule->getColumn(), $row); + $value = $rule->getValue(); + $this->normalizeTypes($rowValue, $value); + + if (! is_array($rowValue)) { + $rowValue = [$rowValue]; + } + + foreach ($rowValue as $rowVal) { + if ($this->performSimilarityMatch($value, $rowVal, $rule->ignoresCase())) { + return true; + } + } + + return false; + } + + /** + * Apply equality matching rules on the given row value + * + * @param mixed $value + * @param mixed $rowValue + * @param bool $ignoreCase + * + * @return bool + */ + protected function performEqualityMatch($value, $rowValue, $ignoreCase = false) + { + if ($ignoreCase && is_string($rowValue)) { + $rowValue = strtolower($rowValue); + $value = is_array($value) + ? array_map(function ($val) { + return strtolower((string) $val); + }, $value) + : strtolower((string) $value); + } + + if (is_array($value)) { + return in_array($rowValue, $value, true); + } elseif (! is_string($value)) { + if (is_string($rowValue)) { + $value = (string) $value; + } + } + + return $rowValue === $value; + } + + /** + * Apply similarity matching rules on the given row value + * + * @param string|string[] $value + * @param string $rowValue + * @param bool $ignoreCase + * + * @return bool + */ + protected function performSimilarityMatch($value, $rowValue, $ignoreCase = false) + { + if ($ignoreCase) { + $rowValue = strtolower($rowValue); + $value = is_array($value) + ? array_map('strtolower', $value) + : strtolower($value); + } + + if (is_array($value)) { + return in_array($rowValue, $value, true); + } + + $wildcardSubSegments = preg_split('~\*~', $value); + if (! $wildcardSubSegments) { + $wildcardSubSegments = []; + } + + if (count($wildcardSubSegments) === 1) { + return $rowValue === $value; + } + + $parts = []; + foreach ($wildcardSubSegments as $part) { + $parts[] = preg_quote($part, '~'); + } + + $pattern = '~^' . join('.*', $parts) . '$~'; + + return (bool) preg_match($pattern, $rowValue); + } + + /** + * Create a rule that matches rows with a column that is **unequal** with the given value + * + * @param string $column + * @param array|bool|float|int|string $value + * + * @return Condition + */ + public static function unequal($column, $value) + { + return new Unequal($column, $value); + } + + /** + * Return whether the given rule's value does not equal the given item's value + * + * @param Unequal $rule + * @param object $row + * + * @return bool + */ + protected function matchUnequal(Unequal $rule, $row) + { + return ! $this->matchEqual($rule, $row); + } + + /** + * Create a rule that matches rows with a column that is **unlike** with the given value + * + * Performs a wildcard search if the value contains asterisks. + * + * @param string $column + * @param string|string[] $value + * + * @return Condition + */ + public static function unlike($column, $value) + { + return new Unlike($column, $value); + } + + /** + * Return whether the given rule's value is unlike the given item's value + * + * @param Unlike $rule + * @param object $row + * + * @return bool + */ + protected function matchUnlike(Unlike $rule, $row) + { + return ! $this->matchSimilar($rule, $row); + } + + /** + * Create a rule that matches rows with a column that is **greater** than the given value + * + * @param string $column + * @param float|int|string $value + * + * @return Condition + */ + public static function greaterThan($column, $value) + { + return new GreaterThan($column, $value); + } + + /** + * Return whether the given rule's value is greater than the given item's value + * + * @param GreaterThan $rule + * @param object $row + * + * @return bool + */ + protected function matchGreaterThan(GreaterThan $rule, $row) + { + return $this->extractValue($rule->getColumn(), $row) > $rule->getValue(); + } + + /** + * Create a rule that matches rows with a column that is **less** than the given value + * + * @param string $column + * @param float|int|string $value + * + * @return Condition + */ + public static function lessThan($column, $value) + { + return new LessThan($column, $value); + } + + /** + * Return whether the given rule's value is less than the given item's value + * + * @param LessThan $rule + * @param object $row + * + * @return bool + */ + protected function matchLessThan(LessThan $rule, $row) + { + $rowValue = $this->extractValue($rule->getColumn(), $row); + if ($rowValue === null) { + return false; + } + + return $rowValue < $rule->getValue(); + } + + /** + * Create a rule that matches rows with a column that is **greater** than or **equal** to the given value + * + * @param string $column + * @param float|int|string $value + * + * @return Condition + */ + public static function greaterThanOrEqual($column, $value) + { + return new GreaterThanOrEqual($column, $value); + } + + /** + * Return whether the given rule's value is greater than or equals the given item's value + * + * @param GreaterThanOrEqual $rule + * @param object $row + * + * @return bool + */ + protected function matchGreaterThanOrEqual(GreaterThanOrEqual $rule, $row) + { + return $this->extractValue($rule->getColumn(), $row) >= $rule->getValue(); + } + + /** + * Create a rule that matches rows with a column that is **less** than or **equal** to the given value + * + * @param string $column + * @param float|int|string $value + * + * @return Condition + */ + public static function lessThanOrEqual($column, $value) + { + return new LessThanOrEqual($column, $value); + } + + /** + * Return whether the given rule's value is less than or equals the given item's value + * + * @param LessThanOrEqual $rule + * @param object $row + * + * @return bool + */ + protected function matchLessThanOrEqual(LessThanOrEqual $rule, $row) + { + $rowValue = $this->extractValue($rule->getColumn(), $row); + if ($rowValue === null) { + return false; + } + + return $rowValue <= $rule->getValue(); + } + + /** + * Perform the appropriate match for the given rule on the given item + * + * @param Rule $rule + * @param object $row + * + * @return bool + */ + protected function performMatch(Rule $rule, $row) + { + switch (true) { + case $rule instanceof All: + return $this->matchAll($rule, $row); + case $rule instanceof Any: + return $this->matchAny($rule, $row); + case $rule instanceof Like: + return $this->matchSimilar($rule, $row); + case $rule instanceof Equal: + return $this->matchEqual($rule, $row); + case $rule instanceof GreaterThan: + return $this->matchGreaterThan($rule, $row); + case $rule instanceof GreaterThanOrEqual: + return $this->matchGreaterThanOrEqual($rule, $row); + case $rule instanceof LessThan: + return $this->matchLessThan($rule, $row); + case $rule instanceof LessThanOrEqual: + return $this->matchLessThanOrEqual($rule, $row); + case $rule instanceof None: + return $this->matchNone($rule, $row); + case $rule instanceof Unequal: + return $this->matchUnequal($rule, $row); + case $rule instanceof Unlike: + return $this->matchUnlike($rule, $row); + default: + throw new InvalidArgumentException(sprintf( + 'Unable to match filter. Rule type %s is unknown', + get_class($rule) + )); + } + } + + /** + * Return a value from the given row suitable to work with + * + * @param string $column + * @param object $row + * + * @return mixed + */ + protected function extractValue($column, $row) + { + try { + return $row->{$column}; + } catch (Exception $_) { + return null; + } + } + + /** + * Normalize type of $value to the one of $rowValue + * + * For details on how this works please see the corresponding test + * {@see \ipl\Tests\Stdlib\FilterTest::testConditionsAreValueTypeAgnostic} + * + * @param mixed $rowValue + * @param mixed $value + * + * @return void + */ + protected function normalizeTypes($rowValue, &$value) + { + if ($rowValue === null || $value === null) { + return; + } + + if (is_array($rowValue)) { + if (empty($rowValue)) { + return; + } + + $rowValue = array_shift($rowValue); + } + + if (is_array($value)) { + if (is_bool($rowValue) && ! empty($value) && is_string(array_values($value)[0])) { + return; + } + + $rowValueType = gettype($rowValue); + foreach ($value as &$val) { + settype($val, $rowValueType); + } + } elseif (! is_bool($rowValue) || ! is_string($value)) { + settype($value, gettype($rowValue)); + } + } +} diff --git a/vendor/ipl/stdlib/src/Filter/All.php b/vendor/ipl/stdlib/src/Filter/All.php new file mode 100644 index 0000000..67b47b6 --- /dev/null +++ b/vendor/ipl/stdlib/src/Filter/All.php @@ -0,0 +1,7 @@ + */ + protected $rules = []; + + /** + * Create a new Chain + * + * @param Rule ...$rules + */ + public function __construct(Rule ...$rules) + { + foreach ($rules as $rule) { + $this->add($rule); + } + } + + /** + * Clone this chain's meta data and rules + */ + public function __clone() + { + if ($this->metaData !== null) { + $this->metaData = clone $this->metaData; + } + + foreach ($this->rules as $i => $rule) { + $this->rules[$i] = clone $rule; + } + } + + /** + * Get an iterator this chain's rules + * + * @return ArrayIterator + */ + public function getIterator(): Traversable + { + return new ArrayIterator($this->rules); + } + + /** + * Add a rule to this chain + * + * @param Rule $rule + * + * @return $this + */ + public function add(Rule $rule) + { + $this->rules[] = $rule; + + return $this; + } + + /** + * Prepend a rule to an existing rule in this chain + * + * @param Rule $rule + * @param Rule $before + * + * @throws OutOfBoundsException In case no existing rule is found + * @return $this + */ + public function insertBefore(Rule $rule, Rule $before) + { + $ruleAt = array_search($before, $this->rules, true); + if ($ruleAt === false) { + throw new OutOfBoundsException('Reference rule not found'); + } + + array_splice($this->rules, $ruleAt, 0, [$rule]); + + return $this; + } + + /** + * Append a rule to an existing rule in this chain + * + * @param Rule $rule + * @param Rule $after + * + * @throws OutOfBoundsException In case no existing rule is found + * @return $this + */ + public function insertAfter(Rule $rule, Rule $after) + { + $ruleAt = array_search($after, $this->rules, true); + if ($ruleAt === false) { + throw new OutOfBoundsException('Reference rule not found'); + } + + array_splice($this->rules, $ruleAt + 1, 0, [$rule]); + + return $this; + } + + /** + * Get whether this chain contains the given rule + * + * @param Rule $rule + * + * @return bool + */ + public function has(Rule $rule) + { + return array_search($rule, $this->rules, true) !== false; + } + + /** + * Replace a rule with another one in this chain + * + * @param Rule $rule + * @param Rule $replacement + * + * @throws OutOfBoundsException In case no existing rule is found + * @return $this + */ + public function replace(Rule $rule, Rule $replacement) + { + $ruleAt = array_search($rule, $this->rules, true); + if ($ruleAt === false) { + throw new OutOfBoundsException('Rule to replace not found'); + } + + array_splice($this->rules, $ruleAt, 1, [$replacement]); + + return $this; + } + + /** + * Remove a rule from this chain + * + * @param Rule $rule + * + * @return $this + */ + public function remove(Rule $rule) + { + $ruleAt = array_search($rule, $this->rules, true); + if ($ruleAt !== false) { + array_splice($this->rules, $ruleAt, 1, []); + } + + return $this; + } + + /** + * Get whether this chain has any rules + * + * @return bool + */ + public function isEmpty() + { + return empty($this->rules); + } + + /** + * Count this chain's rules + * + * @return int + */ + public function count(): int + { + return count($this->rules); + } +} diff --git a/vendor/ipl/stdlib/src/Filter/Condition.php b/vendor/ipl/stdlib/src/Filter/Condition.php new file mode 100644 index 0000000..cc35610 --- /dev/null +++ b/vendor/ipl/stdlib/src/Filter/Condition.php @@ -0,0 +1,84 @@ +setColumn($column) + ->setValue($value); + } + + /** + * Clone this condition's meta data + */ + public function __clone() + { + if ($this->metaData !== null) { + $this->metaData = clone $this->metaData; + } + } + + /** + * Set this condition's column + * + * @param string $column + * + * @return $this + */ + public function setColumn($column) + { + $this->column = $column; + + return $this; + } + + /** + * Get this condition's column + * + * @return string + */ + public function getColumn() + { + return $this->column; + } + + /** + * Set this condition's value + * + * @param mixed $value + * + * @return $this + */ + public function setValue($value) + { + $this->value = $value; + + return $this; + } + + /** + * Get this condition's value + * + * @return mixed + */ + public function getValue() + { + return $this->value; + } +} diff --git a/vendor/ipl/stdlib/src/Filter/Equal.php b/vendor/ipl/stdlib/src/Filter/Equal.php new file mode 100644 index 0000000..71da490 --- /dev/null +++ b/vendor/ipl/stdlib/src/Filter/Equal.php @@ -0,0 +1,31 @@ +ignoreCase = true; + + return $this; + } + + /** + * Return whether this rule ignores case + * + * @return bool + */ + public function ignoresCase() + { + return $this->ignoreCase; + } +} diff --git a/vendor/ipl/stdlib/src/Filter/GreaterThan.php b/vendor/ipl/stdlib/src/Filter/GreaterThan.php new file mode 100644 index 0000000..fd8190c --- /dev/null +++ b/vendor/ipl/stdlib/src/Filter/GreaterThan.php @@ -0,0 +1,7 @@ +ignoreCase = true; + + return $this; + } + + /** + * Return whether this rule ignores case + * + * @return bool + */ + public function ignoresCase() + { + return $this->ignoreCase; + } +} diff --git a/vendor/ipl/stdlib/src/Filter/MetaData.php b/vendor/ipl/stdlib/src/Filter/MetaData.php new file mode 100644 index 0000000..6fe2523 --- /dev/null +++ b/vendor/ipl/stdlib/src/Filter/MetaData.php @@ -0,0 +1,20 @@ +metaData === null) { + $this->metaData = new Data(); + } + + return $this->metaData; + } +} diff --git a/vendor/ipl/stdlib/src/Filter/MetaDataProvider.php b/vendor/ipl/stdlib/src/Filter/MetaDataProvider.php new file mode 100644 index 0000000..ef9557e --- /dev/null +++ b/vendor/ipl/stdlib/src/Filter/MetaDataProvider.php @@ -0,0 +1,15 @@ +ignoreCase = true; + + return $this; + } + + /** + * Return whether this rule ignores case + * + * @return bool + */ + public function ignoresCase() + { + return $this->ignoreCase; + } +} diff --git a/vendor/ipl/stdlib/src/Filter/Unlike.php b/vendor/ipl/stdlib/src/Filter/Unlike.php new file mode 100644 index 0000000..16b9fb3 --- /dev/null +++ b/vendor/ipl/stdlib/src/Filter/Unlike.php @@ -0,0 +1,31 @@ +ignoreCase = true; + + return $this; + } + + /** + * Return whether this rule ignores case + * + * @return bool + */ + public function ignoresCase() + { + return $this->ignoreCase; + } +} diff --git a/vendor/ipl/stdlib/src/Filters.php b/vendor/ipl/stdlib/src/Filters.php new file mode 100644 index 0000000..defff43 --- /dev/null +++ b/vendor/ipl/stdlib/src/Filters.php @@ -0,0 +1,58 @@ +filter ?: Filter::all(); + } + + public function filter(Filter\Rule $filter) + { + $currentFilter = $this->getFilter(); + if ($currentFilter instanceof Filter\All) { + $this->filter = $currentFilter->add($filter); + } else { + $this->filter = Filter::all($filter); + if (! $currentFilter->isEmpty()) { + $this->filter->insertBefore($currentFilter, $filter); + } + } + + return $this; + } + + public function orFilter(Filter\Rule $filter) + { + $currentFilter = $this->getFilter(); + if ($currentFilter instanceof Filter\Any) { + $this->filter = $currentFilter->add($filter); + } else { + $this->filter = Filter::any($filter); + if (! $currentFilter->isEmpty()) { + $this->filter->insertBefore($currentFilter, $filter); + } + } + + return $this; + } + + public function notFilter(Filter\Rule $filter) + { + $this->filter(Filter::none($filter)); + + return $this; + } + + public function orNotFilter(Filter\Rule $filter) + { + $this->orFilter(Filter::none($filter)); + + return $this; + } +} diff --git a/vendor/ipl/stdlib/src/Loader/AutoloadingPluginLoader.php b/vendor/ipl/stdlib/src/Loader/AutoloadingPluginLoader.php new file mode 100644 index 0000000..ba195c6 --- /dev/null +++ b/vendor/ipl/stdlib/src/Loader/AutoloadingPluginLoader.php @@ -0,0 +1,52 @@ +namespace = $namespace; + $this->postfix = $postfix; + } + + /** + * Get the FQN of a plugin + * + * @param string $name Name of the plugin + * + * @return string + */ + protected function getFqn($name) + { + return $this->namespace . '\\' . ucfirst($name) . $this->postfix; + } + + public function load($name) + { + $class = $this->getFqn($name); + + if (! class_exists($class)) { + return false; + } + + return $class; + } +} diff --git a/vendor/ipl/stdlib/src/MessageContainer.php b/vendor/ipl/stdlib/src/MessageContainer.php new file mode 100644 index 0000000..3b383b1 --- /dev/null +++ b/vendor/ipl/stdlib/src/MessageContainer.php @@ -0,0 +1,9 @@ +messages); + } + + /** + * Get all messages + * + * @return array + */ + public function getMessages() + { + return $this->messages; + } + + /** + * Set the given messages overriding existing ones + * + * @param string[] $messages + * + * @return $this + */ + public function setMessages(array $messages) + { + $this->clearMessages(); + + foreach ($messages as $message) { + $this->addMessage($message); + } + + return $this; + } + + /** + * Add a single message + * + * @param string $message + * @param mixed ...$args Optional args for sprintf-style messages + * + * @return $this + */ + public function addMessage($message, ...$args) + { + if (empty($args)) { + $this->messages[] = $message; + } else { + $this->messages[] = vsprintf($message, $args); + } + + return $this; + } + + /** + * Add the given messages + * + * @param array $messages + * + * @return $this + */ + public function addMessages(array $messages) + { + $this->messages = array_merge($this->messages, $messages); + + return $this; + } + + /** + * Drop any existing message + * + * @return $this + */ + public function clearMessages() + { + $this->messages = []; + + return $this; + } +} diff --git a/vendor/ipl/stdlib/src/Plugins.php b/vendor/ipl/stdlib/src/Plugins.php new file mode 100644 index 0000000..a5dbb77 --- /dev/null +++ b/vendor/ipl/stdlib/src/Plugins.php @@ -0,0 +1,95 @@ +pluginLoaders[$type]); + } + + /** + * Add a plugin loader for the given type + * + * @param string $type + * @param PluginLoader|string $loaderOrNamespace + * @param string $postfix + * + * @return $this + */ + public function addPluginLoader($type, $loaderOrNamespace, $postfix = '') + { + $loader = static::wantPluginLoader($loaderOrNamespace, $postfix); + + if (! isset($this->pluginLoaders[$type])) { + $this->pluginLoaders[$type] = []; + } + + array_unshift($this->pluginLoaders[$type], $loader); + + return $this; + } + + /** + * Load the class file of the given plugin + * + * @param string $type + * @param string $name + * + * @return string|false + */ + public function loadPlugin($type, $name) + { + if ($this->hasPluginLoader($type)) { + /** @var PluginLoader $loader */ + foreach ($this->pluginLoaders[$type] as $loader) { + $class = $loader->load($name); + if ($class) { + return $class; + } + } + } + + return false; + } + + protected function addDefaultPluginLoader($type, $loaderOrNamespace, $postfix) + { + $this->pluginLoaders[$type][] = static::wantPluginLoader($loaderOrNamespace, $postfix); + + return $this; + } +} diff --git a/vendor/ipl/stdlib/src/PriorityQueue.php b/vendor/ipl/stdlib/src/PriorityQueue.php new file mode 100644 index 0000000..9047af4 --- /dev/null +++ b/vendor/ipl/stdlib/src/PriorityQueue.php @@ -0,0 +1,42 @@ +serial--]); + } + + /** + * Yield all items as priority-value pairs + * + * @return Generator + */ + public function yieldAll() + { + // Clone queue because the SplPriorityQueue acts as a heap and thus items are removed upon iteration + $queue = clone $this; + + $queue->setExtractFlags(static::EXTR_BOTH); + + foreach ($queue as $item) { + yield $item['priority'][0] => $item['data']; + } + } +} diff --git a/vendor/ipl/stdlib/src/Properties.php b/vendor/ipl/stdlib/src/Properties.php new file mode 100644 index 0000000..5726af3 --- /dev/null +++ b/vendor/ipl/stdlib/src/Properties.php @@ -0,0 +1,205 @@ +properties); + } + + /** + * Get whether a property with the given key exists + * + * @param string $key + * + * @return bool + */ + public function hasProperty($key) + { + return array_key_exists($key, $this->properties); + } + + /** + * Set the given properties + * + * @param array $properties + * + * @return $this + */ + public function setProperties(array $properties) + { + foreach ($properties as $key => $value) { + $this->setProperty($key, $value); + } + + return $this; + } + + /** + * Get the property by the given key + * + * @param string $key + * + * @return mixed + * + * @throws OutOfBoundsException If the property by the given key does not exist + */ + protected function getProperty($key) + { + if (array_key_exists($key, $this->properties)) { + return $this->properties[$key]; + } + + throw new OutOfBoundsException("Can't access property '$key'. Property does not exist"); + } + + /** + * Set a property with the given key and value + * + * @param string $key + * @param mixed $value + * + * @return $this + */ + protected function setProperty($key, $value) + { + $this->properties[$key] = $value; + + return $this; + } + + /** + * Iterate over all existing properties + * + * @return Traversable + */ + public function getIterator(): Traversable + { + foreach ($this->properties as $key => $value) { + yield $key => $value; + } + } + + /** + * Check whether an offset exists + * + * @param mixed $offset + * + * @return bool + */ + public function offsetExists($offset): bool + { + return isset($this->properties[$offset]); + } + + /** + * Get the value for an offset + * + * @param mixed $offset + * + * @return mixed + */ + #[\ReturnTypeWillChange] + public function offsetGet($offset) + { + return $this->getProperty($offset); + } + + /** + * Set the value for an offset + * + * @param mixed $offset + * @param mixed $value + */ + public function offsetSet($offset, $value): void + { + $this->setProperty($offset, $value); + } + + /** + * Unset the value for an offset + * + * @param mixed $offset + */ + public function offsetUnset($offset): void + { + unset($this->properties[$offset]); + } + + /** + * Get the value of a non-public property + * + * This is a PHP magic method which is implicitly called upon access to non-public properties, + * e.g. `$value = $object->property;`. + * Do not call this method directly. + * + * @param mixed $key + * + * @return mixed + */ + public function __get($key) + { + return $this->getProperty($key); + } + + /** + * Set the value of a non-public property + * + * This is a PHP magic method which is implicitly called upon access to non-public properties, + * e.g. `$object->property = $value;`. + * Do not call this method directly. + * + * @param string $key + * @param mixed $value + */ + public function __set($key, $value) + { + $this->setProperty($key, $value); + } + + /** + * Check whether a non-public property is defined and not null + * + * This is a PHP magic method which is implicitly called upon access to non-public properties, + * e.g. `isset($object->property);`. + * Do not call this method directly. + * + * @param string $key + * + * @return bool + */ + public function __isset($key) + { + return $this->offsetExists($key); + } + + /** + * Unset the value of a non-public property + * + * This is a PHP magic method which is implicitly called upon access to non-public properties, + * e.g. `unset($object->property);`. This method does nothing if the property does not exist. + * Do not call this method directly. + * + * @param string $key + */ + public function __unset($key) + { + $this->offsetUnset($key); + } +} diff --git a/vendor/ipl/stdlib/src/Seq.php b/vendor/ipl/stdlib/src/Seq.php new file mode 100644 index 0000000..02a3bd0 --- /dev/null +++ b/vendor/ipl/stdlib/src/Seq.php @@ -0,0 +1,111 @@ +|iterable $traversable + * @param mixed $needle Might also be a closure + * @param bool $caseSensitive Whether strings should be compared case-sensitive + * + * @return bool + */ + public static function contains($traversable, $needle, $caseSensitive = true) + { + return self::find($traversable, $needle, $caseSensitive)[0] !== null; + } + + /** + * Search in the traversable for the given needle and return its key and value + * + * @param array|iterable $traversable + * @param mixed $needle Might also be a closure + * @param bool $caseSensitive Whether strings should be compared case-sensitive + * + * @return array An array with two entries, the first is the key, then the value. + * Both are null if nothing is found. + */ + public static function find($traversable, $needle, $caseSensitive = true) + { + $usesCallback = $needle instanceof Closure; + if (! $usesCallback && $caseSensitive && is_array($traversable)) { + return [array_search($needle, $traversable, true), $needle]; + } + + if (! $caseSensitive && is_string($needle) && ! $usesCallback) { + $needle = strtolower($needle); + } + + foreach ($traversable as $key => $item) { + $originalItem = $item; + if (! $caseSensitive && is_string($item)) { + $item = strtolower($item); + } + + if ($usesCallback && $needle($item)) { + return [$key, $originalItem]; + } elseif ($item === $needle) { + return [$key, $originalItem]; + } + } + + return [null, null]; + } + + /** + * Search in the traversable for the given needle and return its key + * + * @param array|iterable $traversable + * @param mixed $needle Might also be a closure + * @param bool $caseSensitive Whether strings should be compared case-sensitive + * + * @return mixed|null Null if nothing is found + */ + public static function findKey($traversable, $needle, $caseSensitive = true) + { + return self::find($traversable, $needle, $caseSensitive)[0]; + } + + /** + * Search in the traversable for the given needle and return its value + * + * @param array|iterable $traversable + * @param mixed $needle Might also be a closure + * @param bool $caseSensitive Whether strings should be compared case-sensitive + * + * @return mixed|null Null if nothing is found + */ + public static function findValue($traversable, $needle, $caseSensitive = true) + { + $usesCallback = $needle instanceof Closure; + if (! $usesCallback && $caseSensitive && is_array($traversable)) { + return isset($traversable[$needle]) ? $traversable[$needle] : null; + } + + if (! $caseSensitive && is_string($needle) && ! $usesCallback) { + $needle = strtolower($needle); + } + + foreach ($traversable as $key => $item) { + if (! $caseSensitive && is_string($key)) { + $key = strtolower($key); + } + + if ($usesCallback && $needle($key)) { + return $item; + } elseif ($key === $needle) { + return $item; + } + } + + return null; + } +} diff --git a/vendor/ipl/stdlib/src/Str.php b/vendor/ipl/stdlib/src/Str.php new file mode 100644 index 0000000..9cf1cae --- /dev/null +++ b/vendor/ipl/stdlib/src/Str.php @@ -0,0 +1,93 @@ + + */ + public static function symmetricSplit(?string $subject, string $delimiter, int $limit, $default = null) + { + if ($subject === null) { + return array_pad([], $limit, $default); + } + + return array_pad(explode($delimiter, $subject, $limit), $limit, $default); + } + + /** + * Split string into an array and trim spaces + * + * @param ?string $subject + * @param string $delimiter + * @param ?int $limit + * + * @return array + */ + public static function trimSplit(?string $subject, string $delimiter = ',', int $limit = null) + { + if ($subject === null) { + return []; + } + + if ($limit !== null) { + $exploded = explode($delimiter, $subject, $limit); + } else { + $exploded = explode($delimiter, $subject); + } + + return array_map('trim', $exploded); + } +} diff --git a/vendor/ipl/stdlib/src/functions.php b/vendor/ipl/stdlib/src/functions.php new file mode 100644 index 0000000..e7f9be0 --- /dev/null +++ b/vendor/ipl/stdlib/src/functions.php @@ -0,0 +1,128 @@ +|object|Traversable $subject + * + * @return array + * + * @throws InvalidArgumentException If subject type is invalid + */ +function arrayval($subject) +{ + if (is_array($subject)) { + return $subject; + } + + if ($subject instanceof stdClass) { + return (array) $subject; + } + + if ($subject instanceof Traversable) { + // Works for generators too + return iterator_to_array($subject); + } + + throw new InvalidArgumentException(sprintf( + 'arrayval expects arrays, objects or instances of Traversable. Got %s instead.', + get_php_type($subject) + )); +} + +/** + * Get the first key of an iterable + * + * @param iterable $iterable + * + * @return mixed The first key of the iterable if it is not empty, null otherwise + */ +function iterable_key_first($iterable) +{ + foreach ($iterable as $key => $_) { + return $key; + } + + return null; +} + +/** + * Get the first value of an iterable + * + * @param iterable $iterable + * + * @return ?mixed + */ +function iterable_value_first($iterable) +{ + foreach ($iterable as $_ => $value) { + return $value; + } + + return null; +} + +/** + * Yield sets of items from a sorted traversable grouped by a specific criterion gathered from a callback + * + * The traversable must be sorted by the criterion. The callback must return at least the criterion, + * but can also return value and key in addition. + * + * @param Traversable $traversable + * @param callable(mixed $value, mixed $key): array{0: mixed, 1?: mixed, 2?: mixed} $groupBy + * + * @return Generator + */ +function yield_groups(Traversable $traversable, callable $groupBy): Generator +{ + $iterator = new IteratorIterator($traversable); + $iterator->rewind(); + + if (! $iterator->valid()) { + return; + } + + list($criterion, $v, $k) = array_pad((array) $groupBy($iterator->current(), $iterator->key()), 3, null); + $group = [$k ?? $iterator->key() => $v ?? $iterator->current()]; + + $iterator->next(); + for (; $iterator->valid(); $iterator->next()) { + list($c, $v, $k) = array_pad((array) $groupBy($iterator->current(), $iterator->key()), 3, null); + if ($c !== $criterion) { + yield $criterion => $group; + + $group = []; + $criterion = $c; + } + + $group[$k ?? $iterator->key()] = $v ?? $iterator->current(); + } + + yield $criterion => $group; +} diff --git a/vendor/ipl/stdlib/src/functions_include.php b/vendor/ipl/stdlib/src/functions_include.php new file mode 100644 index 0000000..9a2dc6f --- /dev/null +++ b/vendor/ipl/stdlib/src/functions_include.php @@ -0,0 +1,6 @@ +