PluginProbe
Media Cloud Sync / 1.4.2
Media Cloud Sync v1.4.2
1.4.2 1.4.1 1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 All 36 releases
media-cloud-sync / includes / sdk / google / rize / uri-template / src / Rize / UriTemplate / Parser.php

Parser.php in Media Cloud Sync 1.4.2, at includes/sdk/google/rize/uri-template/src/Rize/UriTemplate/Parser.php

118 lines 4.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Dudlewebs\WPMCS\GCP\Rize\UriTemplate;
4
5 use Dudlewebs\WPMCS\GCP\Rize\UriTemplate\Node\Abstraction;
6 use Dudlewebs\WPMCS\GCP\Rize\UriTemplate\Node\Expression;
7 use Dudlewebs\WPMCS\GCP\Rize\UriTemplate\Node\Variable;
8 use Dudlewebs\WPMCS\GCP\Rize\UriTemplate\Operator\UnNamed;
9 class Parser
10 {
11 private const REGEX_VARNAME = '[A-z0-9.]|%[0-9a-fA-F]{2}';
12 /**
13 * Parses URI Template and returns nodes.
14 *
15 * @return Node\Abstraction[]
16 */
17 public function parse(string $template) : array
18 {
19 $parts = \preg_split('#(\\{[^}]+})#', $template, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
20 $nodes = [];
21 foreach ($parts as $part) {
22 $node = $this->createNode($part);
23 // if current node has dot separator that requires a forward lookup
24 // for the previous node iff previous node's operator is UnNamed
25 if ($node instanceof Expression && $node->getOperator()->id === '.') {
26 if (\count($nodes) > 0) {
27 $previousNode = $nodes[\count($nodes) - 1];
28 if ($previousNode instanceof Expression && $previousNode->getOperator() instanceof UnNamed) {
29 $previousNode->setForwardLookupSeparator($node->getOperator()->id);
30 }
31 }
32 }
33 $nodes[] = $node;
34 }
35 return $nodes;
36 }
37 protected function createNode(string $token) : Abstraction
38 {
39 // literal string
40 if ($token[0] !== '{') {
41 $node = $this->createLiteralNode($token);
42 } else {
43 // remove `{}` from expression and parse it
44 $node = $this->parseExpression(\substr($token, 1, -1));
45 }
46 return $node;
47 }
48 protected function parseExpression(string $expression) : Expression
49 {
50 $token = $expression;
51 $prefix = $token[0];
52 // not a valid operator?
53 if (!Operator\Abstraction::isValid($prefix)) {
54 // not valid chars?
55 if (!\preg_match('#' . self::REGEX_VARNAME . '#', $token)) {
56 throw new \InvalidArgumentException("Invalid operator [{$prefix}] found at {$token}");
57 }
58 // default operator
59 //
60 // PHP 8.5: using null as array offset is deprecated and we no longer rely on auto-casting null to ''.
61 $prefix = '';
62 }
63 // remove operator prefix if exists e.g. '?'
64 if ($prefix) {
65 $token = \substr($token, 1);
66 }
67 // parse variables
68 $vars = [];
69 foreach (\explode(',', $token) as $var) {
70 $vars[] = $this->parseVariable($var);
71 }
72 return $this->createExpressionNode($token, $this->createOperatorNode($prefix), $vars);
73 }
74 protected function parseVariable(string $var) : Variable
75 {
76 $var = \trim($var);
77 $val = null;
78 $modifier = null;
79 // check for prefix (:) / explode (*) / array (%) modifier
80 if (\str_contains($var, ':')) {
81 $modifier = ':';
82 [$varname, $val] = \explode(':', $var);
83 // error checking
84 if (!\is_numeric($val)) {
85 throw new \InvalidArgumentException("Value for `:` modifier must be numeric value [{$varname}:{$val}]");
86 }
87 }
88 switch ($last = \substr($var, -1)) {
89 case '*':
90 case '%':
91 // there can be only 1 modifier per var
92 if ($modifier) {
93 throw new \InvalidArgumentException("Multiple modifiers per variable are not allowed [{$var}]");
94 }
95 $modifier = $last;
96 $var = \substr($var, 0, -1);
97 break;
98 }
99 return $this->createVariableNode($var, ['modifier' => $modifier, 'value' => $val]);
100 }
101 protected function createVariableNode($token, $options = []) : Variable
102 {
103 return new Variable($token, $options);
104 }
105 protected function createExpressionNode($token, ?Operator\Abstraction $operator = null, array $vars = []) : Expression
106 {
107 return new Expression($token, $operator, $vars);
108 }
109 protected function createLiteralNode(string $token) : Node\Literal
110 {
111 return new Node\Literal($token);
112 }
113 protected function createOperatorNode($token) : Operator\Abstraction
114 {
115 return Operator\Abstraction::createById($token);
116 }
117 }
118