[ Index ]

PHP Cross Reference of phpBB-3.3.11-deutsch

title

Body

[close]

/vendor/guzzlehttp/guzzle/src/ -> UriTemplate.php (source)

   1  <?php
   2  namespace GuzzleHttp;
   3  
   4  /**
   5   * Expands URI templates. Userland implementation of PECL uri_template.
   6   *
   7   * @link http://tools.ietf.org/html/rfc6570
   8   */
   9  class UriTemplate
  10  {
  11      /** @var string URI template */
  12      private $template;
  13  
  14      /** @var array Variables to use in the template expansion */
  15      private $variables;
  16  
  17      /** @var array Hash for quick operator lookups */
  18      private static $operatorHash = [
  19          ''  => ['prefix' => '',  'joiner' => ',', 'query' => false],
  20          '+' => ['prefix' => '',  'joiner' => ',', 'query' => false],
  21          '#' => ['prefix' => '#', 'joiner' => ',', 'query' => false],
  22          '.' => ['prefix' => '.', 'joiner' => '.', 'query' => false],
  23          '/' => ['prefix' => '/', 'joiner' => '/', 'query' => false],
  24          ';' => ['prefix' => ';', 'joiner' => ';', 'query' => true],
  25          '?' => ['prefix' => '?', 'joiner' => '&', 'query' => true],
  26          '&' => ['prefix' => '&', 'joiner' => '&', 'query' => true]
  27      ];
  28  
  29      /** @var array Delimiters */
  30      private static $delims = [':', '/', '?', '#', '[', ']', '@', '!', '$',
  31          '&', '\'', '(', ')', '*', '+', ',', ';', '='];
  32  
  33      /** @var array Percent encoded delimiters */
  34      private static $delimsPct = ['%3A', '%2F', '%3F', '%23', '%5B', '%5D',
  35          '%40', '%21', '%24', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C',
  36          '%3B', '%3D'];
  37  
  38      public function expand($template, array $variables)
  39      {
  40          if (false === strpos($template, '{')) {
  41              return $template;
  42          }
  43  
  44          $this->template = $template;
  45          $this->variables = $variables;
  46  
  47          return preg_replace_callback(
  48              '/\{([^\}]+)\}/',
  49              [$this, 'expandMatch'],
  50              $this->template
  51          );
  52      }
  53  
  54      /**
  55       * Parse an expression into parts
  56       *
  57       * @param string $expression Expression to parse
  58       *
  59       * @return array Returns an associative array of parts
  60       */
  61      private function parseExpression($expression)
  62      {
  63          $result = [];
  64  
  65          if (isset(self::$operatorHash[$expression[0]])) {
  66              $result['operator'] = $expression[0];
  67              $expression = substr($expression, 1);
  68          } else {
  69              $result['operator'] = '';
  70          }
  71  
  72          foreach (explode(',', $expression) as $value) {
  73              $value = trim($value);
  74              $varspec = [];
  75              if ($colonPos = strpos($value, ':')) {
  76                  $varspec['value'] = substr($value, 0, $colonPos);
  77                  $varspec['modifier'] = ':';
  78                  $varspec['position'] = (int) substr($value, $colonPos + 1);
  79              } elseif (substr($value, -1) === '*') {
  80                  $varspec['modifier'] = '*';
  81                  $varspec['value'] = substr($value, 0, -1);
  82              } else {
  83                  $varspec['value'] = (string) $value;
  84                  $varspec['modifier'] = '';
  85              }
  86              $result['values'][] = $varspec;
  87          }
  88  
  89          return $result;
  90      }
  91  
  92      /**
  93       * Process an expansion
  94       *
  95       * @param array $matches Matches met in the preg_replace_callback
  96       *
  97       * @return string Returns the replacement string
  98       */
  99      private function expandMatch(array $matches)
 100      {
 101          static $rfc1738to3986 = ['+' => '%20', '%7e' => '~'];
 102  
 103          $replacements = [];
 104          $parsed = self::parseExpression($matches[1]);
 105          $prefix = self::$operatorHash[$parsed['operator']]['prefix'];
 106          $joiner = self::$operatorHash[$parsed['operator']]['joiner'];
 107          $useQuery = self::$operatorHash[$parsed['operator']]['query'];
 108  
 109          foreach ($parsed['values'] as $value) {
 110              if (!isset($this->variables[$value['value']])) {
 111                  continue;
 112              }
 113  
 114              $variable = $this->variables[$value['value']];
 115              $actuallyUseQuery = $useQuery;
 116              $expanded = '';
 117  
 118              if (is_array($variable)) {
 119                  $isAssoc = $this->isAssoc($variable);
 120                  $kvp = [];
 121                  foreach ($variable as $key => $var) {
 122                      if ($isAssoc) {
 123                          $key = rawurlencode($key);
 124                          $isNestedArray = is_array($var);
 125                      } else {
 126                          $isNestedArray = false;
 127                      }
 128  
 129                      if (!$isNestedArray) {
 130                          $var = rawurlencode($var);
 131                          if ($parsed['operator'] === '+' ||
 132                              $parsed['operator'] === '#'
 133                          ) {
 134                              $var = $this->decodeReserved($var);
 135                          }
 136                      }
 137  
 138                      if ($value['modifier'] === '*') {
 139                          if ($isAssoc) {
 140                              if ($isNestedArray) {
 141                                  // Nested arrays must allow for deeply nested
 142                                  // structures.
 143                                  $var = strtr(
 144                                      http_build_query([$key => $var]),
 145                                      $rfc1738to3986
 146                                  );
 147                              } else {
 148                                  $var = $key . '=' . $var;
 149                              }
 150                          } elseif ($key > 0 && $actuallyUseQuery) {
 151                              $var = $value['value'] . '=' . $var;
 152                          }
 153                      }
 154  
 155                      $kvp[$key] = $var;
 156                  }
 157  
 158                  if (empty($variable)) {
 159                      $actuallyUseQuery = false;
 160                  } elseif ($value['modifier'] === '*') {
 161                      $expanded = implode($joiner, $kvp);
 162                      if ($isAssoc) {
 163                          // Don't prepend the value name when using the explode
 164                          // modifier with an associative array.
 165                          $actuallyUseQuery = false;
 166                      }
 167                  } else {
 168                      if ($isAssoc) {
 169                          // When an associative array is encountered and the
 170                          // explode modifier is not set, then the result must be
 171                          // a comma separated list of keys followed by their
 172                          // respective values.
 173                          foreach ($kvp as $k => &$v) {
 174                              $v = $k . ',' . $v;
 175                          }
 176                      }
 177                      $expanded = implode(',', $kvp);
 178                  }
 179              } else {
 180                  if ($value['modifier'] === ':') {
 181                      $variable = substr($variable, 0, $value['position']);
 182                  }
 183                  $expanded = rawurlencode($variable);
 184                  if ($parsed['operator'] === '+' || $parsed['operator'] === '#') {
 185                      $expanded = $this->decodeReserved($expanded);
 186                  }
 187              }
 188  
 189              if ($actuallyUseQuery) {
 190                  if (!$expanded && $joiner !== '&') {
 191                      $expanded = $value['value'];
 192                  } else {
 193                      $expanded = $value['value'] . '=' . $expanded;
 194                  }
 195              }
 196  
 197              $replacements[] = $expanded;
 198          }
 199  
 200          $ret = implode($joiner, $replacements);
 201          if ($ret && $prefix) {
 202              return $prefix . $ret;
 203          }
 204  
 205          return $ret;
 206      }
 207  
 208      /**
 209       * Determines if an array is associative.
 210       *
 211       * This makes the assumption that input arrays are sequences or hashes.
 212       * This assumption is a tradeoff for accuracy in favor of speed, but it
 213       * should work in almost every case where input is supplied for a URI
 214       * template.
 215       *
 216       * @param array $array Array to check
 217       *
 218       * @return bool
 219       */
 220      private function isAssoc(array $array)
 221      {
 222          return $array && array_keys($array)[0] !== 0;
 223      }
 224  
 225      /**
 226       * Removes percent encoding on reserved characters (used with + and #
 227       * modifiers).
 228       *
 229       * @param string $string String to fix
 230       *
 231       * @return string
 232       */
 233      private function decodeReserved($string)
 234      {
 235          return str_replace(self::$delimsPct, self::$delims, $string);
 236      }
 237  }


Generated: Sat Nov 4 14:26:03 2023 Cross-referenced by PHPXref 0.7.1