Initial Drupal 11 with DDEV setup

This commit is contained in:
gluebox
2025-10-08 11:39:17 -04:00
commit 89ef74b305
25344 changed files with 2599172 additions and 0 deletions

View File

@ -0,0 +1,139 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Selector\Node;
use Peast\Selector\Matches;
use Peast\Syntax\Utils;
use Peast\Traverser;
/**
* Selector combinator class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class Combinator
{
/**
* Operator
*
* @var string|null
*/
protected $operator;
/**
* Selector parts
*
* @var Part\Part[]
*/
protected $parts = array();
/**
* Sets the operator
*
* @param string $operator Operator
* @return $this
*/
public function setOperator($operator)
{
$this->operator = $operator;
return $this;
}
/**
* Adds a new selector part
*
* @param Part\Part $part Part
* @return $this
*/
public function addPart(Part\Part $part)
{
$this->parts[] = $part;
return $this;
}
/**
* Executes the current group on the given matches
*
* @param Matches $matches Matches
*/
public function exec(Matches $matches)
{
$parts = $this->parts;
//Sort the parts by priority to execute faster checks first
usort($parts, function ($p1, $p2) {
$pr1 = $p1->getPriority();
$pr2 = $p2->getPriority();
if ($pr1 === $pr2) {
return 0;
} elseif ($pr1 < $pr2) {
return -1;
} else {
return 1;
}
});
$filter = function ($node, $parent) use ($parts) {
foreach ($parts as $part) {
if (!$part->check($node, $parent)) {
return false;
}
}
return true;
};
switch ($this->operator) {
case " ":
case ">":
$children = $this->operator === ">";
$matches->map(function ($curNode) use ($filter, $children) {
$ret = array();
$curNode->traverse(
function ($node, $parent) use ($filter, $children, &$ret) {
if ($filter($node, $parent)) {
$ret[] = array($node, $parent);
}
if ($children) {
return Traverser::DONT_TRAVERSE_CHILD_NODES;
}
},
array(
"skipStartingNode" => true,
"passParentNode" => true
)
);
return $ret;
});
break;
case "~":
case "+":
$adjacent = $this->operator === "+";
$matches->map(function ($node, $parent) use ($filter, $adjacent) {
$ret = array();
$evaluate = false;
$props = $parent ? Utils::getExpandedNodeProperties($parent) : array();
foreach ($props as $propNode) {
if ($evaluate) {
if ($propNode && $filter($propNode, $parent)) {
$ret[] = array($propNode, $parent);
}
if ($adjacent) {
break;
}
} elseif ($propNode === $node) {
$evaluate = true;
}
}
return $ret;
});
break;
default:
$matches->filter($filter);
break;
}
}
}

View File

@ -0,0 +1,52 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Selector\Node;
use Peast\Selector\Matches;
/**
* Selector group class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class Group
{
/**
* Selector combinators
*
* @var Combinator[]
*/
protected $combinators = array();
/**
* Adds a combinator
*
* @param Combinator $combinators Combinator
*
* @return $this
*/
public function addCombinator(Combinator $combinators)
{
$this->combinators[] = $combinators;
return $this;
}
/**
* Executes the current group on the given matches
*
* @param Matches $matches Matches
*/
public function exec(Matches $matches)
{
foreach ($this->combinators as $combinator) {
$combinator->exec($matches);
}
}
}

View File

@ -0,0 +1,228 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Selector\Node\Part;
use Peast\Syntax\Node\Node;
use Peast\Syntax\Utils;
/**
* Selector part attribute class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class Attribute extends Part
{
/**
* Priority
*
* @var int
*/
protected $priority = 4;
/**
* Attribute names
*
* @var array
*/
protected $names = array();
/**
* Attribute match operator
*
* @var array
*/
protected $operator = null;
/**
* Attribute value
*
* @var mixed
*/
protected $value = null;
/**
* Case insensitive flag
*
* @var bool
*/
protected $caseInsensitive = false;
/**
* Regex flag
*
* @var bool
*/
protected $regex = false;
/**
* Adds a name
*
* @param string $name Name
*
* @return $this
*/
public function addName($name)
{
$this->names[] = $name;
return $this;
}
/**
* Sets the operator
*
* @param string $operator Operator
*
* @return $this
*/
public function setOperator($operator)
{
$this->operator = $operator;
return $this;
}
/**
* Sets the value
*
* @param mixed $value Value
*
* @return $this
*/
public function setValue($value)
{
$this->value = $value;
return $this;
}
/**
* Sets the case insensitive flag
*
* @param bool $caseInsensitive Case insensitive flag
*
* @return $this
*/
public function setCaseInsensitive($caseInsensitive)
{
$this->caseInsensitive = $caseInsensitive;
return $this;
}
/**
* Sets the regex flag
*
* @param bool $regex Regex flag
*
* @return $this
*/
public function setRegex($regex)
{
$this->regex = $regex;
return $this;
}
/**
* Returns true if the selector part matches the given node,
* false otherwise
*
* @param Node $node Node
* @param Node $parent Parent node
*
* @return bool
*/
public function check(Node $node, $parent = null)
{
$attr = $node;
foreach ($this->names as $name) {
$attrFound = false;
if ($attr instanceof Node) {
$props = Utils::getNodeProperties($attr);
foreach ($props as $prop) {
if ($prop["name"] === $name) {
$attrFound = true;
$attr = $attr->{$prop["getter"]}();
break;
}
}
}
if (!$attrFound) {
return false;
}
}
$bothStrings = is_string($attr) && is_string($this->value);
switch ($this->operator) {
case "=":
if ($bothStrings) {
if ($this->regex) {
return preg_match($this->value, $attr);
}
return $this->compareStr(
$this->value, $attr, $this->caseInsensitive, true, true
);
}
if (is_int($attr) && is_float($this->value)) {
return (float) $attr === $this->value;
}
return $attr === $this->value;
case "<":
if (is_float($this->value) && !is_float($attr) && !is_int($attr) && !is_string($attr)) {
return false;
}
return $attr < $this->value;
case ">":
if (is_float($this->value) && !is_float($attr) && !is_int($attr) && !is_string($attr)) {
return false;
}
return $attr > $this->value;
case "<=":
if (is_float($this->value) && !is_float($attr) && !is_int($attr) && !is_string($attr)) {
return false;
}
return $attr <= $this->value;
case ">=":
if (is_float($this->value) && !is_float($attr) && !is_int($attr) && !is_string($attr)) {
return false;
}
return $attr >= $this->value;
case "^=":
case "$=":
case "*=":
return $this->compareStr(
$this->value, $attr, $this->caseInsensitive,
$this->operator === "^=",
$this->operator === "$="
);
default:
return true;
}
}
/**
* Compares two strings
*
* @param string $v1 Search value
* @param string $v2 Compare value
* @param bool $caseInsensitive True if the search must be case insensitive
* @param bool $matchStart True if the search must be executed from the
* beginning of the string
* @param bool $matchEnd True if the search must be executed from the
* end of the string
*
* @return bool
*/
protected function compareStr($v1, $v2, $caseInsensitive, $matchStart, $matchEnd)
{
$regex = "#" .
($matchStart ? "^" : "") .
preg_quote($v1) .
($matchEnd ? "$" : "") .
"#u" .
($caseInsensitive ? "i" : "");
return (bool) preg_match($regex, $v2);
}
}

View File

@ -0,0 +1,47 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Selector\Node\Part;
use Peast\Syntax\Node\Node;
/**
* Selector part base class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*
* @abstract
*/
abstract class Part
{
/**
* Priority
*
* @var int
*/
protected $priority = 5;
public function getPriority()
{
return $this->priority;
}
/**
* Returns true if the selector part matches the given node,
* false otherwise
*
* @param Node $node Node
* @param Node $parent Parent node
*
* @return bool
*
* @abstract
*/
abstract public function check(Node $node, $parent = null);
}

View File

@ -0,0 +1,40 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Selector\Node\Part;
/**
* Selector pseudo part base class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*
* @abstract
*/
abstract class Pseudo extends Part
{
/**
* Selector name
*
* @var string
*/
protected $name;
/**
* Sets the name
*
* @param string $name Name
*
* @return $this
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
}

View File

@ -0,0 +1,108 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Selector\Node\Part;
use Peast\Syntax\Node\Node;
use Peast\Syntax\Utils;
/**
* Selector part index pseudo class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class PseudoIndex extends Pseudo
{
/**
* Priority
*
* @var int
*/
protected $priority = 2;
/**
* Step
*
* @var int
*/
protected $step = 0;
/**
* Offset
*
* @var int
*/
protected $offset = 0;
/**
* Sets the step
*
* @param int $step Step
*
* @return $this
*/
public function setStep($step)
{
$this->step = $step;
return $this;
}
/**
* Sets the offset
*
* @param int $offset Offset
*
* @return $this
*/
public function setOffset($offset)
{
$this->offset = $offset;
return $this;
}
/**
* Returns true if the selector part matches the given node,
* false otherwise
*
* @param Node $node Node
* @param Node $parent Parent node
*
* @return bool
*/
public function check(Node $node, $parent = null)
{
$props = Utils::getExpandedNodeProperties($parent);
$count = count($props);
$reverse = $this->name === "nth-last-child";
if ($reverse) {
$start = $count - 1 - ($this->offset - 1);
$step = $this->step * -1;
if ($step > 0) {
$reverse = false;
}
} else {
$start = $this->offset - 1;
$step = $this->step;
if ($step < 0) {
$reverse = true;
}
}
//Step 0 will cause an infinite loop, so it must be set to the
//number of props so that it will execute only one iteration
if (!$step) {
$step = $reverse ? -$count : $count;
}
for ($i = $start; ($reverse && $i >= 0) || (!$reverse && $i < $count); $i += $step) {
if (isset($props[$i]) && $props[$i] === $node) {
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,66 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Selector\Node\Part;
use Peast\Selector\Matches;
use Peast\Selector\Node\Selector;
use Peast\Syntax\Node\Node;
/**
* Selector part selector pseudo class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class PseudoSelector extends Pseudo
{
/**
* Priority
*
* @var int
*/
protected $priority = 1;
/**
* Selector
*
* @var Selector
*/
protected $selector;
/**
* Sets the selector
*
* @param Selector $selector Selector
*
* @return $this
*/
public function setSelector(Selector $selector)
{
$this->selector = $selector;
return $this;
}
/**
* Returns true if the selector part matches the given node,
* false otherwise
*
* @param Node $node Node
* @param Node $parent Parent node
*
* @return bool
*/
public function check(Node $node, $parent = null)
{
$match = new Matches();
$match->addMatch($node, $parent);
$res = $this->selector->exec($match)->count();
return $this->name === "not" ? $res === 0 : $res !== 0;
}
}

View File

@ -0,0 +1,62 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Selector\Node\Part;
use Peast\Syntax\Node\Node;
use Peast\Syntax\Node\Pattern;
use Peast\Syntax\Node\Statement;
use Peast\Syntax\Node\Expression;
use Peast\Syntax\Node\Declaration;
use Peast\Syntax\Utils;
/**
* Selector part simple pseudo class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class PseudoSimple extends Pseudo
{
/**
* Priority
*
* @var int
*/
protected $priority = 3;
/**
* Returns true if the selector part matches the given node,
* false otherwise
*
* @param Node $node Node
* @param Node $parent Parent node
*
* @return bool
*/
public function check(Node $node, $parent = null)
{
switch ($this->name) {
case "pattern":
return $node instanceof Pattern;
case "statement":
return $node instanceof Statement;
case "expression":
return $node instanceof Expression;
case "declaration":
return $node instanceof Declaration;
case "last-child":
case "first-child":
$first = $this->name === "first-child";
$props = Utils::getExpandedNodeProperties($parent);
return count($props) > 0 && (
$first ? $props[0] === $node : array_pop($props) === $node
);
}
}
}

View File

@ -0,0 +1,54 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Selector\Node\Part;
use Peast\Syntax\Node\Node;
/**
* Selector part type class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class Type extends Part
{
/**
* Selector type
*
* @var string
*/
protected $type;
/**
* Sets the selector type
*
* @param string $type Type
*
* @return $this
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* Returns true if the selector part matches the given node,
* false otherwise
*
* @param Node $node Node
* @param Node $parent Parent node
*
* @return bool
*/
public function check(Node $node, $parent = null)
{
return $node->getType() === $this->type;
}
}

View File

@ -0,0 +1,61 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Selector\Node;
use Peast\Selector\Matches;
/**
* Selector class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class Selector
{
/**
* Selector groups
*
* @var Group[]
*/
protected $groups = array();
/**
* Adds a new group
*
* @param Group $group Group
*
* @return $this
*/
public function addGroup(Group $group)
{
$this->groups[] = $group;
return $this;
}
/**
* Executes the current selector on the given matches
*
* @param Matches $matches Matches
*
* @return Matches
*/
public function exec(Matches $matches)
{
$retMatches = array();
foreach ($this->groups as $group) {
$clonedMatches = $matches->createClone();
$group->exec($clonedMatches);
$retMatches[] = $clonedMatches;
}
if (count($retMatches) > 1) {
$retMatches[0]->merge(array_slice($retMatches, 1));
}
return $retMatches[0];
}
}