This commit is contained in:
emmymayo
2025-02-05 23:15:46 +01:00
commit 7269c99357
16995 changed files with 3389680 additions and 0 deletions
@@ -0,0 +1,180 @@
<?php
namespace MailPoetVendor\Doctrine\Common\Collections;
if (!defined('ABSPATH')) exit;
use Closure;
use ReturnTypeWillChange;
use Traversable;
abstract class AbstractLazyCollection implements Collection
{
protected $collection;
protected $initialized = \false;
#[\ReturnTypeWillChange]
public function count()
{
$this->initialize();
return $this->collection->count();
}
public function add($element)
{
$this->initialize();
return $this->collection->add($element);
}
public function clear()
{
$this->initialize();
$this->collection->clear();
}
public function contains($element)
{
$this->initialize();
return $this->collection->contains($element);
}
public function isEmpty()
{
$this->initialize();
return $this->collection->isEmpty();
}
public function remove($key)
{
$this->initialize();
return $this->collection->remove($key);
}
public function removeElement($element)
{
$this->initialize();
return $this->collection->removeElement($element);
}
public function containsKey($key)
{
$this->initialize();
return $this->collection->containsKey($key);
}
public function get($key)
{
$this->initialize();
return $this->collection->get($key);
}
public function getKeys()
{
$this->initialize();
return $this->collection->getKeys();
}
public function getValues()
{
$this->initialize();
return $this->collection->getValues();
}
public function set($key, $value)
{
$this->initialize();
$this->collection->set($key, $value);
}
public function toArray()
{
$this->initialize();
return $this->collection->toArray();
}
public function first()
{
$this->initialize();
return $this->collection->first();
}
public function last()
{
$this->initialize();
return $this->collection->last();
}
public function key()
{
$this->initialize();
return $this->collection->key();
}
public function current()
{
$this->initialize();
return $this->collection->current();
}
public function next()
{
$this->initialize();
return $this->collection->next();
}
public function exists(Closure $p)
{
$this->initialize();
return $this->collection->exists($p);
}
public function filter(Closure $p)
{
$this->initialize();
return $this->collection->filter($p);
}
public function forAll(Closure $p)
{
$this->initialize();
return $this->collection->forAll($p);
}
public function map(Closure $func)
{
$this->initialize();
return $this->collection->map($func);
}
public function partition(Closure $p)
{
$this->initialize();
return $this->collection->partition($p);
}
public function indexOf($element)
{
$this->initialize();
return $this->collection->indexOf($element);
}
public function slice($offset, $length = null)
{
$this->initialize();
return $this->collection->slice($offset, $length);
}
#[\ReturnTypeWillChange]
public function getIterator()
{
$this->initialize();
return $this->collection->getIterator();
}
#[\ReturnTypeWillChange]
public function offsetExists($offset)
{
$this->initialize();
return $this->collection->offsetExists($offset);
}
#[\ReturnTypeWillChange]
public function offsetGet($offset)
{
$this->initialize();
return $this->collection->offsetGet($offset);
}
#[\ReturnTypeWillChange]
public function offsetSet($offset, $value)
{
$this->initialize();
$this->collection->offsetSet($offset, $value);
}
#[\ReturnTypeWillChange]
public function offsetUnset($offset)
{
$this->initialize();
$this->collection->offsetUnset($offset);
}
public function isInitialized()
{
return $this->initialized;
}
protected function initialize()
{
if ($this->initialized) {
return;
}
$this->doInitialize();
$this->initialized = \true;
}
protected abstract function doInitialize();
}
@@ -0,0 +1,225 @@
<?php
namespace MailPoetVendor\Doctrine\Common\Collections;
if (!defined('ABSPATH')) exit;
use ArrayIterator;
use Closure;
use MailPoetVendor\Doctrine\Common\Collections\Expr\ClosureExpressionVisitor;
use ReturnTypeWillChange;
use Traversable;
use function array_filter;
use function array_key_exists;
use function array_keys;
use function array_map;
use function array_reverse;
use function array_search;
use function array_slice;
use function array_values;
use function count;
use function current;
use function end;
use function in_array;
use function key;
use function next;
use function reset;
use function spl_object_hash;
use function uasort;
use const ARRAY_FILTER_USE_BOTH;
class ArrayCollection implements Collection, Selectable
{
private $elements;
public function __construct(array $elements = [])
{
$this->elements = $elements;
}
public function toArray()
{
return $this->elements;
}
public function first()
{
return reset($this->elements);
}
protected function createFrom(array $elements)
{
return new static($elements);
}
public function last()
{
return end($this->elements);
}
public function key()
{
return key($this->elements);
}
public function next()
{
return next($this->elements);
}
public function current()
{
return current($this->elements);
}
public function remove($key)
{
if (!isset($this->elements[$key]) && !array_key_exists($key, $this->elements)) {
return null;
}
$removed = $this->elements[$key];
unset($this->elements[$key]);
return $removed;
}
public function removeElement($element)
{
$key = array_search($element, $this->elements, \true);
if ($key === \false) {
return \false;
}
unset($this->elements[$key]);
return \true;
}
#[\ReturnTypeWillChange]
public function offsetExists($offset)
{
return $this->containsKey($offset);
}
#[\ReturnTypeWillChange]
public function offsetGet($offset)
{
return $this->get($offset);
}
#[\ReturnTypeWillChange]
public function offsetSet($offset, $value)
{
if (!isset($offset)) {
$this->add($value);
return;
}
$this->set($offset, $value);
}
#[\ReturnTypeWillChange]
public function offsetUnset($offset)
{
$this->remove($offset);
}
public function containsKey($key)
{
return isset($this->elements[$key]) || array_key_exists($key, $this->elements);
}
public function contains($element)
{
return in_array($element, $this->elements, \true);
}
public function exists(Closure $p)
{
foreach ($this->elements as $key => $element) {
if ($p($key, $element)) {
return \true;
}
}
return \false;
}
public function indexOf($element)
{
return array_search($element, $this->elements, \true);
}
public function get($key)
{
return $this->elements[$key] ?? null;
}
public function getKeys()
{
return array_keys($this->elements);
}
public function getValues()
{
return array_values($this->elements);
}
#[\ReturnTypeWillChange]
public function count()
{
return count($this->elements);
}
public function set($key, $value)
{
$this->elements[$key] = $value;
}
public function add($element)
{
$this->elements[] = $element;
return \true;
}
public function isEmpty()
{
return empty($this->elements);
}
#[\ReturnTypeWillChange]
public function getIterator()
{
return new ArrayIterator($this->elements);
}
public function map(Closure $func)
{
return $this->createFrom(array_map($func, $this->elements));
}
public function filter(Closure $p)
{
return $this->createFrom(array_filter($this->elements, $p, ARRAY_FILTER_USE_BOTH));
}
public function forAll(Closure $p)
{
foreach ($this->elements as $key => $element) {
if (!$p($key, $element)) {
return \false;
}
}
return \true;
}
public function partition(Closure $p)
{
$matches = $noMatches = [];
foreach ($this->elements as $key => $element) {
if ($p($key, $element)) {
$matches[$key] = $element;
} else {
$noMatches[$key] = $element;
}
}
return [$this->createFrom($matches), $this->createFrom($noMatches)];
}
public function __toString()
{
return self::class . '@' . spl_object_hash($this);
}
public function clear()
{
$this->elements = [];
}
public function slice($offset, $length = null)
{
return array_slice($this->elements, $offset, $length, \true);
}
public function matching(Criteria $criteria)
{
$expr = $criteria->getWhereExpression();
$filtered = $this->elements;
if ($expr) {
$visitor = new ClosureExpressionVisitor();
$filter = $visitor->dispatch($expr);
$filtered = array_filter($filtered, $filter);
}
$orderings = $criteria->getOrderings();
if ($orderings) {
$next = null;
foreach (array_reverse($orderings) as $field => $ordering) {
$next = ClosureExpressionVisitor::sortByField($field, $ordering === Criteria::DESC ? -1 : 1, $next);
}
uasort($filtered, $next);
}
$offset = $criteria->getFirstResult();
$length = $criteria->getMaxResults();
if ($offset || $length) {
$filtered = array_slice($filtered, (int) $offset, $length);
}
return $this->createFrom($filtered);
}
}
@@ -0,0 +1,34 @@
<?php
namespace MailPoetVendor\Doctrine\Common\Collections;
if (!defined('ABSPATH')) exit;
use ArrayAccess;
use Closure;
use Countable;
use IteratorAggregate;
interface Collection extends Countable, IteratorAggregate, ArrayAccess
{
public function add($element);
public function clear();
public function contains($element);
public function isEmpty();
public function remove($key);
public function removeElement($element);
public function containsKey($key);
public function get($key);
public function getKeys();
public function getValues();
public function set($key, $value);
public function toArray();
public function first();
public function last();
public function key();
public function current();
public function next();
public function exists(Closure $p);
public function filter(Closure $p);
public function forAll(Closure $p);
public function map(Closure $func);
public function partition(Closure $p);
public function indexOf($element);
public function slice($offset, $length = null);
}
@@ -0,0 +1,92 @@
<?php
namespace MailPoetVendor\Doctrine\Common\Collections;
if (!defined('ABSPATH')) exit;
use MailPoetVendor\Doctrine\Common\Collections\Expr\CompositeExpression;
use MailPoetVendor\Doctrine\Common\Collections\Expr\Expression;
use function array_map;
use function strtoupper;
class Criteria
{
public const ASC = 'ASC';
public const DESC = 'DESC';
private static $expressionBuilder;
private $expression;
private $orderings = [];
private $firstResult;
private $maxResults;
public static function create()
{
return new static();
}
public static function expr()
{
if (self::$expressionBuilder === null) {
self::$expressionBuilder = new ExpressionBuilder();
}
return self::$expressionBuilder;
}
public function __construct(?Expression $expression = null, ?array $orderings = null, $firstResult = null, $maxResults = null)
{
$this->expression = $expression;
$this->setFirstResult($firstResult);
$this->setMaxResults($maxResults);
if ($orderings === null) {
return;
}
$this->orderBy($orderings);
}
public function where(Expression $expression)
{
$this->expression = $expression;
return $this;
}
public function andWhere(Expression $expression)
{
if ($this->expression === null) {
return $this->where($expression);
}
$this->expression = new CompositeExpression(CompositeExpression::TYPE_AND, [$this->expression, $expression]);
return $this;
}
public function orWhere(Expression $expression)
{
if ($this->expression === null) {
return $this->where($expression);
}
$this->expression = new CompositeExpression(CompositeExpression::TYPE_OR, [$this->expression, $expression]);
return $this;
}
public function getWhereExpression()
{
return $this->expression;
}
public function getOrderings()
{
return $this->orderings;
}
public function orderBy(array $orderings)
{
$this->orderings = array_map(static function (string $ordering) : string {
return strtoupper($ordering) === Criteria::ASC ? Criteria::ASC : Criteria::DESC;
}, $orderings);
return $this;
}
public function getFirstResult()
{
return $this->firstResult;
}
public function setFirstResult($firstResult)
{
$this->firstResult = $firstResult;
return $this;
}
public function getMaxResults()
{
return $this->maxResults;
}
public function setMaxResults($maxResults)
{
$this->maxResults = $maxResults;
return $this;
}
}
@@ -0,0 +1,179 @@
<?php
namespace MailPoetVendor\Doctrine\Common\Collections\Expr;
if (!defined('ABSPATH')) exit;
use ArrayAccess;
use Closure;
use RuntimeException;
use function in_array;
use function is_array;
use function is_scalar;
use function iterator_to_array;
use function method_exists;
use function preg_match;
use function preg_replace_callback;
use function strlen;
use function strpos;
use function strtoupper;
use function substr;
class ClosureExpressionVisitor extends ExpressionVisitor
{
public static function getObjectFieldValue($object, $field)
{
if (is_array($object)) {
return $object[$field];
}
$accessors = ['get', 'is'];
foreach ($accessors as $accessor) {
$accessor .= $field;
if (method_exists($object, $accessor)) {
return $object->{$accessor}();
}
}
if (preg_match('/^is[A-Z]+/', $field) === 1 && method_exists($object, $field)) {
return $object->{$field}();
}
// __call should be triggered for get.
$accessor = $accessors[0] . $field;
if (method_exists($object, '__call')) {
return $object->{$accessor}();
}
if ($object instanceof ArrayAccess) {
return $object[$field];
}
if (isset($object->{$field})) {
return $object->{$field};
}
// camelcase field name to support different variable naming conventions
$ccField = preg_replace_callback('/_(.?)/', static function ($matches) {
return strtoupper($matches[1]);
}, $field);
foreach ($accessors as $accessor) {
$accessor .= $ccField;
if (method_exists($object, $accessor)) {
return $object->{$accessor}();
}
}
return $object->{$field};
}
public static function sortByField($name, $orientation = 1, ?Closure $next = null)
{
if (!$next) {
$next = static function () : int {
return 0;
};
}
return static function ($a, $b) use($name, $next, $orientation) : int {
$aValue = ClosureExpressionVisitor::getObjectFieldValue($a, $name);
$bValue = ClosureExpressionVisitor::getObjectFieldValue($b, $name);
if ($aValue === $bValue) {
return $next($a, $b);
}
return ($aValue > $bValue ? 1 : -1) * $orientation;
};
}
public function walkComparison(Comparison $comparison)
{
$field = $comparison->getField();
$value = $comparison->getValue()->getValue();
// shortcut for walkValue()
switch ($comparison->getOperator()) {
case Comparison::EQ:
return static function ($object) use($field, $value) : bool {
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) === $value;
};
case Comparison::NEQ:
return static function ($object) use($field, $value) : bool {
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) !== $value;
};
case Comparison::LT:
return static function ($object) use($field, $value) : bool {
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) < $value;
};
case Comparison::LTE:
return static function ($object) use($field, $value) : bool {
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) <= $value;
};
case Comparison::GT:
return static function ($object) use($field, $value) : bool {
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) > $value;
};
case Comparison::GTE:
return static function ($object) use($field, $value) : bool {
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) >= $value;
};
case Comparison::IN:
return static function ($object) use($field, $value) : bool {
$fieldValue = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
return in_array($fieldValue, $value, is_scalar($fieldValue));
};
case Comparison::NIN:
return static function ($object) use($field, $value) : bool {
$fieldValue = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
return !in_array($fieldValue, $value, is_scalar($fieldValue));
};
case Comparison::CONTAINS:
return static function ($object) use($field, $value) {
return strpos(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value) !== \false;
};
case Comparison::MEMBER_OF:
return static function ($object) use($field, $value) : bool {
$fieldValues = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
if (!is_array($fieldValues)) {
$fieldValues = iterator_to_array($fieldValues);
}
return in_array($value, $fieldValues, \true);
};
case Comparison::STARTS_WITH:
return static function ($object) use($field, $value) : bool {
return strpos(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value) === 0;
};
case Comparison::ENDS_WITH:
return static function ($object) use($field, $value) : bool {
return $value === substr(ClosureExpressionVisitor::getObjectFieldValue($object, $field), -strlen($value));
};
default:
throw new RuntimeException('Unknown comparison operator: ' . $comparison->getOperator());
}
}
public function walkValue(Value $value)
{
return $value->getValue();
}
public function walkCompositeExpression(CompositeExpression $expr)
{
$expressionList = [];
foreach ($expr->getExpressionList() as $child) {
$expressionList[] = $this->dispatch($child);
}
switch ($expr->getType()) {
case CompositeExpression::TYPE_AND:
return $this->andExpressions($expressionList);
case CompositeExpression::TYPE_OR:
return $this->orExpressions($expressionList);
default:
throw new RuntimeException('Unknown composite ' . $expr->getType());
}
}
private function andExpressions(array $expressions) : callable
{
return static function ($object) use($expressions) : bool {
foreach ($expressions as $expression) {
if (!$expression($object)) {
return \false;
}
}
return \true;
};
}
private function orExpressions(array $expressions) : callable
{
return static function ($object) use($expressions) : bool {
foreach ($expressions as $expression) {
if ($expression($object)) {
return \true;
}
}
return \false;
};
}
}
@@ -0,0 +1,48 @@
<?php
namespace MailPoetVendor\Doctrine\Common\Collections\Expr;
if (!defined('ABSPATH')) exit;
class Comparison implements Expression
{
public const EQ = '=';
public const NEQ = '<>';
public const LT = '<';
public const LTE = '<=';
public const GT = '>';
public const GTE = '>=';
public const IS = '=';
// no difference with EQ
public const IN = 'IN';
public const NIN = 'NIN';
public const CONTAINS = 'CONTAINS';
public const MEMBER_OF = 'MEMBER_OF';
public const STARTS_WITH = 'STARTS_WITH';
public const ENDS_WITH = 'ENDS_WITH';
private $field;
private $op;
private $value;
public function __construct($field, $operator, $value)
{
if (!$value instanceof Value) {
$value = new Value($value);
}
$this->field = $field;
$this->op = $operator;
$this->value = $value;
}
public function getField()
{
return $this->field;
}
public function getValue()
{
return $this->value;
}
public function getOperator()
{
return $this->op;
}
public function visit(ExpressionVisitor $visitor)
{
return $visitor->walkComparison($this);
}
}
@@ -0,0 +1,36 @@
<?php
namespace MailPoetVendor\Doctrine\Common\Collections\Expr;
if (!defined('ABSPATH')) exit;
use RuntimeException;
class CompositeExpression implements Expression
{
public const TYPE_AND = 'AND';
public const TYPE_OR = 'OR';
private $type;
private $expressions = [];
public function __construct($type, array $expressions)
{
$this->type = $type;
foreach ($expressions as $expr) {
if ($expr instanceof Value) {
throw new RuntimeException('Values are not supported expressions as children of and/or expressions.');
}
if (!$expr instanceof Expression) {
throw new RuntimeException('No expression given to CompositeExpression.');
}
$this->expressions[] = $expr;
}
}
public function getExpressionList()
{
return $this->expressions;
}
public function getType()
{
return $this->type;
}
public function visit(ExpressionVisitor $visitor)
{
return $visitor->walkCompositeExpression($this);
}
}
@@ -0,0 +1,7 @@
<?php
namespace MailPoetVendor\Doctrine\Common\Collections\Expr;
if (!defined('ABSPATH')) exit;
interface Expression
{
public function visit(ExpressionVisitor $visitor);
}
@@ -0,0 +1,24 @@
<?php
namespace MailPoetVendor\Doctrine\Common\Collections\Expr;
if (!defined('ABSPATH')) exit;
use RuntimeException;
use function get_class;
abstract class ExpressionVisitor
{
public abstract function walkComparison(Comparison $comparison);
public abstract function walkValue(Value $value);
public abstract function walkCompositeExpression(CompositeExpression $expr);
public function dispatch(Expression $expr)
{
switch (\true) {
case $expr instanceof Comparison:
return $this->walkComparison($expr);
case $expr instanceof Value:
return $this->walkValue($expr);
case $expr instanceof CompositeExpression:
return $this->walkCompositeExpression($expr);
default:
throw new RuntimeException('Unknown Expression ' . get_class($expr));
}
}
}
@@ -0,0 +1,19 @@
<?php
namespace MailPoetVendor\Doctrine\Common\Collections\Expr;
if (!defined('ABSPATH')) exit;
class Value implements Expression
{
private $value;
public function __construct($value)
{
$this->value = $value;
}
public function getValue()
{
return $this->value;
}
public function visit(ExpressionVisitor $visitor)
{
return $visitor->walkValue($this);
}
}
@@ -0,0 +1,70 @@
<?php
namespace MailPoetVendor\Doctrine\Common\Collections;
if (!defined('ABSPATH')) exit;
use MailPoetVendor\Doctrine\Common\Collections\Expr\Comparison;
use MailPoetVendor\Doctrine\Common\Collections\Expr\CompositeExpression;
use MailPoetVendor\Doctrine\Common\Collections\Expr\Value;
use function func_get_args;
class ExpressionBuilder
{
public function andX($x = null)
{
return new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args());
}
public function orX($x = null)
{
return new CompositeExpression(CompositeExpression::TYPE_OR, func_get_args());
}
public function eq($field, $value)
{
return new Comparison($field, Comparison::EQ, new Value($value));
}
public function gt($field, $value)
{
return new Comparison($field, Comparison::GT, new Value($value));
}
public function lt($field, $value)
{
return new Comparison($field, Comparison::LT, new Value($value));
}
public function gte($field, $value)
{
return new Comparison($field, Comparison::GTE, new Value($value));
}
public function lte($field, $value)
{
return new Comparison($field, Comparison::LTE, new Value($value));
}
public function neq($field, $value)
{
return new Comparison($field, Comparison::NEQ, new Value($value));
}
public function isNull($field)
{
return new Comparison($field, Comparison::EQ, new Value(null));
}
public function in($field, array $values)
{
return new Comparison($field, Comparison::IN, new Value($values));
}
public function notIn($field, array $values)
{
return new Comparison($field, Comparison::NIN, new Value($values));
}
public function contains($field, $value)
{
return new Comparison($field, Comparison::CONTAINS, new Value($value));
}
public function memberOf($field, $value)
{
return new Comparison($field, Comparison::MEMBER_OF, new Value($value));
}
public function startsWith($field, $value)
{
return new Comparison($field, Comparison::STARTS_WITH, new Value($value));
}
public function endsWith($field, $value)
{
return new Comparison($field, Comparison::ENDS_WITH, new Value($value));
}
}
@@ -0,0 +1,7 @@
<?php
namespace MailPoetVendor\Doctrine\Common\Collections;
if (!defined('ABSPATH')) exit;
interface Selectable
{
public function matching(Criteria $criteria);
}