refactor: Cleanup git state - commit all staged changes
Major refactoring cleanup: - Add new controller architecture (class-controller-*.php) - Add new settings-v2 UI (views/settings-v2/) - Add new CSS architecture (agentic-sidebar.css, tokens) - Add esbuild build pipeline (scripts/build.js, package.json) - Add composer dependencies (vendor/) - Add frontend src directory (assets/js/src/index.jsx) - Add documentation files - Remove old/obsolete files (class-settings.php, old CSS) This commits all pending changes from previous refactoring efforts.
This commit is contained in:
85
vendor/league/csv/src/Query/Constraint/Column.php
vendored
Normal file
85
vendor/league/csv/src/Query/Constraint/Column.php
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* League.Csv (https://csv.thephpleague.com)
|
||||
*
|
||||
* (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\Csv\Query\Constraint;
|
||||
|
||||
use CallbackFilterIterator;
|
||||
use Closure;
|
||||
use Iterator;
|
||||
use League\Csv\MapIterator;
|
||||
use League\Csv\Query;
|
||||
use ReflectionException;
|
||||
|
||||
/**
|
||||
* Enable filtering a record based on the value of a one of its cell.
|
||||
*
|
||||
* When used with PHP's array_filter with the ARRAY_FILTER_USE_BOTH flag
|
||||
* the record offset WILL NOT BE taken into account
|
||||
*/
|
||||
final class Column implements Query\Predicate
|
||||
{
|
||||
/**
|
||||
* @throws Query\QueryException
|
||||
*/
|
||||
private function __construct(
|
||||
public readonly string|int $column,
|
||||
public readonly Comparison|Closure $operator,
|
||||
public readonly mixed $value,
|
||||
) {
|
||||
if (!$this->operator instanceof Closure) {
|
||||
$this->operator->accept($this->value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Query\QueryException
|
||||
*/
|
||||
public static function filterOn(
|
||||
string|int $column,
|
||||
Comparison|Closure|callable|string $operator,
|
||||
mixed $value = null,
|
||||
): self {
|
||||
if ($operator instanceof Closure) {
|
||||
return new self($column, $operator, null);
|
||||
}
|
||||
|
||||
if (is_callable($operator)) {
|
||||
return new self($column, $operator(...), $value);
|
||||
}
|
||||
|
||||
return new self(
|
||||
$column,
|
||||
is_string($operator) ? Comparison::fromOperator($operator) : $operator,
|
||||
$value
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ReflectionException
|
||||
* @throws Query\QueryException
|
||||
*/
|
||||
public function __invoke(mixed $value, int|string $key): bool
|
||||
{
|
||||
$subject = Query\Row::from($value)->value($this->column);
|
||||
if ($this->operator instanceof Closure) {
|
||||
return ($this->operator)($subject);
|
||||
}
|
||||
|
||||
return $this->operator->compare($subject, $this->value);
|
||||
}
|
||||
|
||||
public function filter(iterable $value): Iterator
|
||||
{
|
||||
return new CallbackFilterIterator(MapIterator::toIterator($value), $this);
|
||||
}
|
||||
}
|
||||
157
vendor/league/csv/src/Query/Constraint/Comparison.php
vendored
Normal file
157
vendor/league/csv/src/Query/Constraint/Comparison.php
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* League.Csv (https://csv.thephpleague.com)
|
||||
*
|
||||
* (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\Csv\Query\Constraint;
|
||||
|
||||
use League\Csv\Query\QueryException;
|
||||
|
||||
use function array_is_list;
|
||||
use function count;
|
||||
use function in_array;
|
||||
use function is_array;
|
||||
use function is_scalar;
|
||||
use function is_string;
|
||||
use function str_contains;
|
||||
use function str_ends_with;
|
||||
use function str_starts_with;
|
||||
use function strtoupper;
|
||||
use function trim;
|
||||
|
||||
enum Comparison: string
|
||||
{
|
||||
case Equals = '=';
|
||||
case NotEquals = '!=';
|
||||
case GreaterThan = '>';
|
||||
case GreaterThanOrEqual = '>=';
|
||||
case LesserThan = '<';
|
||||
case LesserThanOrEqual = '<=';
|
||||
case Between = 'BETWEEN';
|
||||
case NotBetween = 'NBETWEEN';
|
||||
case Regexp = 'REGEXP';
|
||||
case NotRegexp = 'NREGEXP';
|
||||
case In = 'IN';
|
||||
case NotIn = 'NIN';
|
||||
case Contains = 'CONTAINS';
|
||||
case NotContain = 'NCONTAIN';
|
||||
case StartsWith = 'STARTS_WITH';
|
||||
case EndsWith = 'ENDS_WITH';
|
||||
|
||||
public static function tryFromOperator(string $operator): ?self
|
||||
{
|
||||
$operator = strtoupper(trim($operator));
|
||||
|
||||
return match ($operator) {
|
||||
'<>', 'NEQ', 'IS NOT', 'NOT EQUAL' => self::NotEquals,
|
||||
'EQ', 'IS', 'EQUAL', 'EQUALS' => self::Equals,
|
||||
'GT', 'GREATER THAN' => self::GreaterThan,
|
||||
'GTE', 'GREATER THAN OR EQUAL' => self::GreaterThanOrEqual,
|
||||
'LT', 'LESSER THAN' => self::LesserThan,
|
||||
'LTE', 'LESSER THAN OR EQUAL' => self::LesserThanOrEqual,
|
||||
'NOT_REGEXP', 'NOT REGEXP' => self::NotRegexp,
|
||||
'NOT_CONTAIN', 'NOT CONTAIN', 'DOES_NOT_CONTAIN', 'DOES NOT CONTAIN' => self::NotContain,
|
||||
'NOT_IN', 'NOT IN' => self::NotIn,
|
||||
'NOT_BETWEEN', 'NOT BETWEEN' => self::Between,
|
||||
'STARTS WITH', 'START WITH' => self::StartsWith,
|
||||
'ENDS WITH', 'END WITH' => self::EndsWith,
|
||||
default => self::tryFrom($operator),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws QueryException
|
||||
*/
|
||||
public static function fromOperator(string $operator): self
|
||||
{
|
||||
return self::tryFromOperator($operator) ?? throw QueryException::dueToUnknownOperator($operator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Values comparison.
|
||||
*
|
||||
* The method return true if the values satisfy the comparison operator, otherwise false is returned.
|
||||
*
|
||||
* @throws QueryException
|
||||
*/
|
||||
public function compare(mixed $subject, mixed $reference): bool
|
||||
{
|
||||
$this->accept($reference);
|
||||
|
||||
return match ($this) {
|
||||
self::Equals => self::isSingleValue($subject) ? $subject === $reference : $subject == $reference,
|
||||
self::NotEquals => self::isSingleValue($subject) ? $subject !== $reference : $subject != $reference,
|
||||
self::GreaterThan => $subject > $reference,
|
||||
self::GreaterThanOrEqual => $subject >= $reference,
|
||||
self::LesserThan => $subject < $reference,
|
||||
self::LesserThanOrEqual => $subject <= $reference,
|
||||
self::Between => $subject >= $reference[0] && $subject <= $reference[1], /* @phpstan-ignore-line */
|
||||
self::NotBetween => $subject < $reference[0] || $subject > $reference[1], /* @phpstan-ignore-line */
|
||||
self::In => in_array($subject, $reference, self::isSingleValue($subject)), /* @phpstan-ignore-line */
|
||||
self::NotIn => !in_array($subject, $reference, self::isSingleValue($subject)), /* @phpstan-ignore-line */
|
||||
self::Regexp => is_string($subject) && 1 === preg_match($reference, $subject), /* @phpstan-ignore-line */
|
||||
self::NotRegexp => is_string($subject) && 1 !== preg_match($reference, $subject), /* @phpstan-ignore-line */
|
||||
self::Contains => is_string($subject) && str_contains($subject, $reference), /* @phpstan-ignore-line */
|
||||
self::NotContain => is_string($subject) && !str_contains($subject, $reference), /* @phpstan-ignore-line */
|
||||
self::StartsWith => is_string($subject) && str_starts_with($subject, $reference), /* @phpstan-ignore-line */
|
||||
self::EndsWith => is_string($subject) && str_ends_with($subject, $reference), /* @phpstan-ignore-line */
|
||||
};
|
||||
}
|
||||
|
||||
private static function isSingleValue(mixed $value): bool
|
||||
{
|
||||
return is_scalar($value) || null === $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert if the reference value can be used with the Enum operator.
|
||||
*
|
||||
* @throws QueryException
|
||||
*/
|
||||
public function accept(mixed $reference): void
|
||||
{
|
||||
match ($this) {
|
||||
self::Between,
|
||||
self::NotBetween => match (true) {
|
||||
!is_array($reference),
|
||||
!array_is_list($reference),
|
||||
2 !== count($reference) => throw new QueryException('The value used for comparison with the `'.$this->name.'` operator must be an list containing 2 values, the minimum and maximum values.'),
|
||||
default => true,
|
||||
},
|
||||
self::In,
|
||||
self::NotIn => match (true) {
|
||||
!is_array($reference) => throw new QueryException('The value used for comparison with the `'.$this->name.'` operator must be an array.'),
|
||||
default => true,
|
||||
},
|
||||
self::Regexp,
|
||||
self::NotRegexp => match (true) {
|
||||
!is_string($reference),
|
||||
'' === $reference,
|
||||
false === @preg_match($reference, '') => throw new QueryException('The value used for comparison with the `'.$this->name.'` operator must be a valid regular expression pattern string.'),
|
||||
default => true,
|
||||
},
|
||||
self::Contains,
|
||||
self::NotContain,
|
||||
self::StartsWith,
|
||||
self::EndsWith => match (true) {
|
||||
!is_string($reference),
|
||||
'' === $reference => throw new QueryException('The value used for comparison with the `'.$this->name.'` operator must be a non empty string.'),
|
||||
default => true,
|
||||
},
|
||||
self::Equals,
|
||||
self::NotEquals,
|
||||
self::GreaterThanOrEqual,
|
||||
self::GreaterThan,
|
||||
self::LesserThanOrEqual,
|
||||
self::LesserThan => true,
|
||||
};
|
||||
}
|
||||
}
|
||||
168
vendor/league/csv/src/Query/Constraint/Criteria.php
vendored
Normal file
168
vendor/league/csv/src/Query/Constraint/Criteria.php
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* League.Csv (https://csv.thephpleague.com)
|
||||
*
|
||||
* (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\Csv\Query\Constraint;
|
||||
|
||||
use CallbackFilterIterator;
|
||||
use Closure;
|
||||
use Iterator;
|
||||
use League\Csv\MapIterator;
|
||||
use League\Csv\Query\Predicate;
|
||||
use League\Csv\Query\PredicateCombinator;
|
||||
|
||||
use function array_reduce;
|
||||
|
||||
/**
|
||||
* @phpstan-import-type Condition from PredicateCombinator
|
||||
* @phpstan-import-type ConditionExtended from PredicateCombinator
|
||||
*/
|
||||
final class Criteria implements PredicateCombinator
|
||||
{
|
||||
/**
|
||||
* @param Condition $predicate
|
||||
*/
|
||||
private function __construct(private readonly Predicate|Closure $predicate)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance with predicates join using the logical AND operator.
|
||||
*
|
||||
* @param ConditionExtended ...$predicates
|
||||
*/
|
||||
public static function all(Predicate|Closure|callable ...$predicates): self
|
||||
{
|
||||
return new self(function (mixed $value, int|string $key) use ($predicates): bool {
|
||||
foreach ($predicates as $predicate) {
|
||||
if (!$predicate($value, $key)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance with predicates join using the logical NOT operator.
|
||||
*
|
||||
* @param ConditionExtended ...$predicates
|
||||
*/
|
||||
public static function none(Predicate|Closure|callable ...$predicates): self
|
||||
{
|
||||
return new self(function (mixed $value, int|string $key) use ($predicates): bool {
|
||||
foreach ($predicates as $predicate) {
|
||||
if ($predicate($value, $key)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance with predicates join using the logical OR operator.
|
||||
*
|
||||
* @param ConditionExtended ...$predicates
|
||||
*/
|
||||
public static function any(Predicate|Closure|callable ...$predicates): self
|
||||
{
|
||||
return new self(function (mixed $value, int|string $key) use ($predicates): bool {
|
||||
foreach ($predicates as $predicate) {
|
||||
if ($predicate($value, $key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance with predicates join using the logical XOR operator.
|
||||
*
|
||||
* @param ConditionExtended ...$predicates
|
||||
*/
|
||||
public static function xany(Predicate|Closure|callable ...$predicates): self
|
||||
{
|
||||
return new self(fn (mixed $value, int|string $key): bool => array_reduce(
|
||||
$predicates,
|
||||
fn (bool $bool, Predicate|Closure|callable $predicate) => $predicate($value, $key) xor $bool,
|
||||
false
|
||||
));
|
||||
}
|
||||
|
||||
public function __invoke(mixed $value, int|string $key): bool
|
||||
{
|
||||
return ($this->predicate)($value, $key);
|
||||
}
|
||||
|
||||
public function filter(iterable $value): Iterator
|
||||
{
|
||||
return new CallbackFilterIterator(MapIterator::toIterator($value), $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConditionExtended ...$predicates
|
||||
*/
|
||||
public function and(Predicate|Closure|callable ...$predicates): self
|
||||
{
|
||||
return self::all($this->predicate, ...$predicates);
|
||||
}
|
||||
|
||||
public function andNot(Predicate|Closure|callable ...$predicates): self
|
||||
{
|
||||
return self::all($this->predicate, self::none(...$predicates));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConditionExtended ...$predicates
|
||||
*/
|
||||
public function not(Predicate|Closure|callable ...$predicates): self
|
||||
{
|
||||
return self::none($this->predicate, ...$predicates);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConditionExtended ...$predicates
|
||||
*/
|
||||
public function or(Predicate|Closure|callable ...$predicates): self
|
||||
{
|
||||
return self::any($this->predicate, ...$predicates);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConditionExtended ...$predicates
|
||||
*/
|
||||
public function orNot(Predicate|Closure|callable ...$predicates): self
|
||||
{
|
||||
return self::any($this->predicate, self::none(...$predicates));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConditionExtended ...$predicates
|
||||
*/
|
||||
public function xor(Predicate|Closure|callable ...$predicates): self
|
||||
{
|
||||
return self::xany($this->predicate, ...$predicates);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConditionExtended ...$predicates
|
||||
*/
|
||||
public function xorNot(Predicate|Closure|callable ...$predicates): self
|
||||
{
|
||||
return self::xany($this->predicate, self::none(...$predicates));
|
||||
}
|
||||
}
|
||||
79
vendor/league/csv/src/Query/Constraint/Offset.php
vendored
Normal file
79
vendor/league/csv/src/Query/Constraint/Offset.php
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* League.Csv (https://csv.thephpleague.com)
|
||||
*
|
||||
* (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\Csv\Query\Constraint;
|
||||
|
||||
use CallbackFilterIterator;
|
||||
use Closure;
|
||||
use Iterator;
|
||||
use League\Csv\MapIterator;
|
||||
use League\Csv\Query;
|
||||
|
||||
/**
|
||||
* Enable filtering a record based on its offset.
|
||||
*
|
||||
* When used with PHP's array_filter with the ARRAY_FILTER_USE_BOTH flag
|
||||
* the record value WILL NOT BE taken into account
|
||||
*/
|
||||
final class Offset implements Query\Predicate
|
||||
{
|
||||
/**
|
||||
* @throws Query\QueryException
|
||||
*/
|
||||
private function __construct(
|
||||
public readonly Comparison|Closure $operator,
|
||||
public readonly mixed $value,
|
||||
) {
|
||||
if (!$this->operator instanceof Closure) {
|
||||
$this->operator->accept($this->value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Query\QueryException
|
||||
*/
|
||||
public static function filterOn(
|
||||
Comparison|Closure|callable|string $operator,
|
||||
mixed $value = null,
|
||||
): self {
|
||||
if ($operator instanceof Closure) {
|
||||
return new self($operator, null);
|
||||
}
|
||||
|
||||
if (is_callable($operator)) {
|
||||
return new self(Closure::fromCallable($operator), $value);
|
||||
}
|
||||
|
||||
return new self(
|
||||
is_string($operator) ? Comparison::fromOperator($operator) : $operator,
|
||||
$value
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Query\QueryException
|
||||
*/
|
||||
public function __invoke(mixed $value, int|string $key): bool
|
||||
{
|
||||
if ($this->operator instanceof Closure) {
|
||||
return ($this->operator)($key);
|
||||
}
|
||||
|
||||
return $this->operator->compare($key, $this->value);
|
||||
}
|
||||
|
||||
public function filter(iterable $value): Iterator
|
||||
{
|
||||
return new CallbackFilterIterator(MapIterator::toIterator($value), $this);
|
||||
}
|
||||
}
|
||||
99
vendor/league/csv/src/Query/Constraint/TwoColumns.php
vendored
Normal file
99
vendor/league/csv/src/Query/Constraint/TwoColumns.php
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* League.Csv (https://csv.thephpleague.com)
|
||||
*
|
||||
* (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\Csv\Query\Constraint;
|
||||
|
||||
use CallbackFilterIterator;
|
||||
use Closure;
|
||||
use Iterator;
|
||||
use League\Csv\MapIterator;
|
||||
use League\Csv\Query\Predicate;
|
||||
use League\Csv\Query\QueryException;
|
||||
use League\Csv\Query\Row;
|
||||
use ReflectionException;
|
||||
|
||||
use function array_filter;
|
||||
use function is_array;
|
||||
use function is_int;
|
||||
use function is_string;
|
||||
|
||||
use const ARRAY_FILTER_USE_BOTH;
|
||||
|
||||
/**
|
||||
* Enable filtering a record by comparing the values of two of its column.
|
||||
*
|
||||
* When used with PHP's array_filter with the ARRAY_FILTER_USE_BOTH flag
|
||||
* the record offset WILL NOT BE taken into account
|
||||
*/
|
||||
final class TwoColumns implements Predicate
|
||||
{
|
||||
/**
|
||||
* @throws QueryException
|
||||
*/
|
||||
private function __construct(
|
||||
public readonly string|int $first,
|
||||
public readonly Comparison|Closure $operator,
|
||||
public readonly array|string|int $second,
|
||||
) {
|
||||
!$this->operator instanceof Closure || !is_array($this->second) || throw new QueryException('The second column must be a string if the operator is a callback.');
|
||||
|
||||
if (is_array($this->second)) {
|
||||
$res = array_filter($this->second, fn (mixed $value): bool => !is_string($value) && !is_int($value));
|
||||
if ([] !== $res) {
|
||||
throw new QueryException('The second column must be a string, an integer or a list of strings and/or integer when the operator is not a callback.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws QueryException
|
||||
*/
|
||||
public static function filterOn(
|
||||
string|int $firstColumn,
|
||||
Comparison|Closure|callable|string $operator,
|
||||
array|string|int $secondColumn
|
||||
): self {
|
||||
if (is_string($operator)) {
|
||||
$operator = Comparison::fromOperator($operator);
|
||||
}
|
||||
|
||||
if (is_callable($operator)) {
|
||||
return new self($firstColumn, Closure::fromCallable($operator), $secondColumn);
|
||||
}
|
||||
|
||||
return new self($firstColumn, $operator, $secondColumn);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws QueryException
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function __invoke(mixed $value, int|string $key): bool
|
||||
{
|
||||
$val = match (true) {
|
||||
is_array($this->second) => array_values(Row::from($value)->select(...$this->second)),
|
||||
default => Row::from($value)->value($this->second),
|
||||
};
|
||||
|
||||
if ($this->operator instanceof Closure) {
|
||||
return ($this->operator)(Row::from($value)->value($this->first), $val);
|
||||
}
|
||||
|
||||
return Column::filterOn($this->first, $this->operator, $val)($value, $key);
|
||||
}
|
||||
|
||||
public function filter(iterable $value): Iterator
|
||||
{
|
||||
return new CallbackFilterIterator(MapIterator::toIterator($value), $this);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user