Hoa central
Cli.php
Go to the documentation of this file.
1 <?php
2 
37 namespace Hoa\Router;
38 
39 use Hoa\Core;
40 
49 class Cli extends Generic implements Core\Parameter\Parameterizable
50 {
56  protected $_parameters = null;
57 
63  protected static $_methods = [
64  'get'
65  ];
66 
67 
68 
74  public function __construct(Array $parameters = [])
75  {
76  $this->_parameters = new Core\Parameter(
77  $this,
78  [],
79  [
80  'rules.public' => [],
81  'rules.private' => []
82  ]
83  );
84  $this->_parameters->setParameters($parameters);
85 
86  foreach ($this->_parameters->getParameter('rules.public') as $id => $rule) {
87  @list($methods, $pattern, $call, $able, $variables)
88  = $rule;
89 
90  if (null === $variables) {
91  $variables = [];
92  }
93 
94  $this->addRule($id, $methods, $pattern, $call, $able, $variables);
95  }
96 
97  foreach ($this->_parameters->getParameter('rules.private') as $id => $rule) {
98  @list($methods, $pattern, $call, $able, $variables)
99  = $rule;
100 
101  if (null === $variables) {
102  $variables = [];
103  }
104 
105  $this->addPrivateRule(
106  $id, $methods, $pattern, $call, $able, $variables
107  );
108  }
109 
110  return;
111  }
112 
118  public function getParameters()
119  {
120  return $this->_parameters;
121  }
122 
137  protected function _addRule(
138  $visibility,
139  $id,
140  Array $methods,
141  $pattern,
142  $call, $able,
143  Array $variables
144  ) {
145  if (true === $this->ruleExists($id)) {
146  throw new Exception(
147  'Cannot add rule %s because it already exists.',
148  0,
149  $id
150  );
151  }
152 
153  array_walk($methods, function (&$method) {
154 
155  $method = strtolower($method);
156  });
157  $diff = array_diff($methods, self::$_methods);
158 
159  if (!empty($diff)) {
160  throw new Exception(
161  (1 == count($diff)
162  ? 'Method %s is'
163  : 'Methods %s are') .
164  ' invalid for the rule %s (valid methods are: %s).',
165  1,
166  [
167  implode(', ', $diff),
168  $id,
169  implode(', ', self::$_methods)
170  ]
171  );
172  }
173 
174  $this->_rules[$id] = [
175  Router::RULE_VISIBILITY => $visibility,
176  Router::RULE_ID => $id,
177  Router::RULE_METHODS => $methods,
178  Router::RULE_PATTERN => $pattern,
179  Router::RULE_CALL => $call,
180  Router::RULE_ABLE => $able,
181  Router::RULE_VARIABLES => $variables
182  ];
183 
184  return $this;
185  }
186 
195  public function route($uri = null)
196  {
197  if (null === $uri) {
198  $uri = static::getURI();
199  }
200 
201  $method = $this->getMethod();
202  $rules = array_filter(
203  $this->getRules(),
204  function ($rule) use (&$method) {
206  return false;
207  }
208 
209  if (false === in_array($method, $rule[Router::RULE_METHODS])) {
210  return false;
211  }
212 
213  return true;
214  }
215  );
216 
217  $gotcha = false;
218 
219  foreach ($rules as $rule) {
220  $pattern = $rule[Router::RULE_PATTERN];
221 
222  if (0 !== preg_match('#^' . $pattern . '$#i', $uri, $muri)) {
223  $gotcha = true;
224 
225  break;
226  }
227  }
228 
229  if (false === $gotcha) {
230  throw new Exception\NotFound(
231  'Cannot found an appropriated rule to route %s.',
232  2,
233  $uri
234  );
235  }
236 
237  array_shift($muri);
238  $rule[Router::RULE_VARIABLES]['_method'] = 'get';
239  $rule[Router::RULE_VARIABLES]['_call'] = &$rule[Router::RULE_CALL];
240  $rule[Router::RULE_VARIABLES]['_able'] = &$rule[Router::RULE_ABLE];
241 
242  $caseless = 0 === preg_match(
243  '#\(\?\-[imsxUXJ]+\)#',
244  $rule[Router::RULE_PATTERN]
245  );
246 
247  foreach ($muri as $key => $value) {
248  if (!is_string($key)) {
249  continue;
250  }
251 
252  if (true === $caseless) {
253  $key = mb_strtolower($key);
254  }
255 
256  if (isset($rule[Router::RULE_VARIABLES][$key]) && empty($value)) {
257  continue;
258  }
259 
260  $rule[Router::RULE_VARIABLES][$key] = $value;
261  }
262 
263  $this->_rule = $rule;
264 
265  return $this;
266  }
267 
275  public function unroute($id, Array $variables = [])
276  {
277  $rule = $this->getRule($id);
278  $pattern = $rule[Router::RULE_PATTERN];
279  $variables = array_merge($rule[Router::RULE_VARIABLES], $variables);
280  $out = preg_replace_callback(
281  '#\(\?<([^>]+)>[^\)]*\)[\?\*\+]{0,2}#',
282  function (Array $matches) use (&$variables) {
283  $m = strtolower($matches[1]);
284 
285  if (!isset($variables[$m])) {
286  return '';
287  }
288 
289  return $variables[$m];
290  },
291  preg_replace('#\(\?\-?[imsxUXJ]+\)#', '', $pattern)
292  );
293 
294  return str_replace(
295  [
296  '\.', '\\\\', '\+', '\*', '\?', '\[', '\]', '\^', '\$', '\(',
297  '\)', '\{', '\}', '\=', '\!', '<', '>', '\|', '\:', '\-'
298  ],
299  [
300  '.', '\\', '+', '*', '?', '[', ']', '^', '$', '(',
301  ')', '{', '}', '=', '!', '<', '>', '|', ':', '-'
302  ],
303  $out
304  );
305  }
306 
312  public function getMethod()
313  {
314  return 'get';
315  }
316 
322  public function isAsynchronous()
323  {
324  return false;
325  }
326 
332  public static function getURI()
333  {
334  if (!isset($_SERVER['argv'])) {
335  return null;
336  }
337 
338  $out = null;
339  $_argv = $_SERVER['argv'];
340  array_shift($_argv);
341 
342  foreach ($_argv as $arg) {
343  if ('-' === $arg[0] && false !== strpos($arg, '=')) {
344  if (false !== strpos($arg, '"')) {
345  $arg = str_replace(
346  '=',
347  '="',
348  str_replace('"', '\\"', $arg)
349  ) . '"';
350  } elseif (false !== strpos($arg, '\'')) {
351  $arg = str_replace(
352  '=',
353  '=\'',
354  str_replace('\'', '\\\'', $arg)
355  ) . '\'';
356  } elseif (false !== strpos($arg, ' ')) {
357  $arg = str_replace('=', '="', $arg) . '"';
358  }
359  } elseif (false !== strpos($arg, ' ')) {
360  $arg = '"' . str_replace('"', '\\"', $arg) . '"';
361  } elseif (false !== strpos($arg, '"')) {
362  $arg = '"' . str_replace('"', '\\"', $arg) . '"';
363  } elseif (false !== strpos($arg, '\'')) {
364  $arg = '"' . $arg . '"';
365  }
366 
367  $out .= ' ' . $arg;
368  }
369 
370  return ltrim($out);
371  }
372 }
const RULE_METHODS
Definition: Router.php:84
const VISIBILITY_PUBLIC
Definition: Router.php:56
const RULE_VARIABLES
Definition: Router.php:112
addRule($id, Array $methods, $pattern, $call=null, $able=null, Array $variables=[])
Definition: Generic.php:108
const RULE_VISIBILITY
Definition: Router.php:70
static getURI()
Definition: Cli.php:332
isAsynchronous()
Definition: Cli.php:322
const RULE_PATTERN
Definition: Router.php:91
unroute($id, Array $variables=[])
Definition: Cli.php:275
__construct(Array $parameters=[])
Definition: Cli.php:74
getParameters()
Definition: Cli.php:118
static $_methods
Definition: Cli.php:63
const RULE_CALL
Definition: Router.php:98
route($uri=null)
Definition: Cli.php:195
_addRule($visibility, $id, Array $methods, $pattern, $call, $able, Array $variables)
Definition: Cli.php:137
addPrivateRule($id, Array $methods, $pattern, $call=null, $able=null, Array $variables=[])
Definition: Generic.php:139