1<?php 2/** 3 * 4 * This file is part of Aura for PHP. 5 * 6 * @license http://opensource.org/licenses/bsd-license.php BSD 7 * 8 */ 9namespace Aura\Router; 10 11/** 12 * 13 * An individual route with a name, path, attributes, defaults, etc. 14 * 15 * @package Aura.Router 16 * 17 * @property-read string $name The route name. 18 * 19 * @property-read string $path The route path. 20 * 21 * @property-read string $namePrefix 22 * 23 * @property-read string $pathPrefix 24 * 25 * @property-read string $host 26 * 27 * @property-read array $defaults Default values for attributes. 28 * 29 * @property-read array $attributes Attribute values added by the rules. 30 * 31 * @property-read array $tokens Placeholder token names and regexes. 32 * 33 * @property-read string $wildcard The name of the wildcard token. 34 * 35 * @property-read array $accept 36 * 37 * @property-read mixed $auth The auth value. 38 * 39 * @property-read array $extras 40 * 41 * @property-read bool $secure 42 * 43 * @property-read array $allows 44 * 45 * @property-read bool $isRoutable 46 * 47 * @property-read callable $special 48 * 49 * @property-read string $failedRule 50 * 51 * @property-read mixed $handler 52 * 53 */ 54class Route 55{ 56 /** 57 * 58 * Accepts these content types. 59 * 60 * @var array 61 * 62 */ 63 protected $accepts = []; 64 65 /** 66 * 67 * Allows these HTTP methods. 68 * 69 * @var array 70 * 71 */ 72 protected $allows = []; 73 74 /** 75 * 76 * Attribute values added by the rules. 77 * 78 * @var array 79 * 80 */ 81 protected $attributes = []; 82 83 /** 84 * 85 * Authentication/authorization values. 86 * 87 * @var mixed 88 * 89 */ 90 protected $auth; 91 92 /** 93 * 94 * Default attribute values. 95 * 96 * @var array 97 * 98 */ 99 protected $defaults = []; 100 101 /** 102 * 103 * Extra key-value pairs to attach to the route; intended for use by 104 * custom matching rules. 105 * 106 * @var array 107 * 108 */ 109 protected $extras = []; 110 111 /** 112 * 113 * The rule that failed, if any, during matching. 114 * 115 * @var string 116 * 117 */ 118 protected $failedRule; 119 120 /** 121 * 122 * The action, controller, callable, closure, etc. this route points to. 123 * 124 * @var mixed 125 * 126 */ 127 protected $handler; 128 129 /** 130 * 131 * The host string this route responds to. 132 * 133 * @var string 134 * 135 */ 136 protected $host; 137 138 /** 139 * 140 * The name for this route. 141 * 142 * @var string 143 * 144 */ 145 protected $name; 146 147 /** 148 * 149 * Prefix the route name with this string. 150 * 151 * @var string 152 * 153 */ 154 protected $namePrefix; 155 156 /** 157 * 158 * The path for this route. 159 * 160 * @var string 161 * 162 */ 163 protected $path; 164 165 /** 166 * 167 * Prefix the route path with this string. 168 * 169 * @var string 170 * 171 */ 172 protected $pathPrefix; 173 174 /** 175 * 176 * Should this route be used for matching? 177 * 178 * @var bool 179 * 180 */ 181 protected $isRoutable = true; 182 183 /** 184 * 185 * Should this route respond on a secure protocol? 186 * 187 * @var bool 188 * 189 */ 190 protected $secure = null; 191 192 /** 193 * 194 * A callable to use for special matching logic on this individual Route. 195 * 196 * @var callable 197 * 198 */ 199 protected $special; 200 201 /** 202 * 203 * Placeholder token names and regexes. 204 * 205 * @var array 206 * 207 */ 208 protected $tokens = []; 209 210 /** 211 * 212 * Wildcard token name, if any. 213 * 214 * @var string 215 * 216 */ 217 protected $wildcard = null; 218 219 /** 220 * 221 * When cloning the Route, reset the `$attributes` to an empty array, and 222 * clear the `$failedRule`. 223 * 224 */ 225 public function __clone() 226 { 227 // $this is the cloned instance, not the original 228 $this->attributes = $this->defaults; 229 $this->failedRule = null; 230 } 231 232 /** 233 * 234 * Magic read-only for all properties. 235 * 236 * @param string $key The property to read from. 237 * 238 * @return mixed 239 * 240 */ 241 public function __get($key) 242 { 243 return $this->$key; 244 } 245 246 /** 247 * 248 * Merges with the existing content types. 249 * 250 * @param string|array $accepts The content types. 251 * 252 * @return $this 253 * 254 */ 255 public function accepts($accepts) 256 { 257 $this->accepts = array_merge($this->accepts, (array) $accepts); 258 return $this; 259 } 260 261 /** 262 * 263 * Merges with the existing allowed methods. 264 * 265 * @param string|array $allows The allowed HTTP methods. 266 * 267 * @return $this 268 * 269 */ 270 public function allows($allows) 271 { 272 $this->allows = array_merge($this->allows, (array) $allows); 273 return $this; 274 } 275 276 /** 277 * 278 * Merges with the existing attributes. 279 * 280 * @param array $attributes The attributes to add. 281 * 282 * @return $this 283 * 284 */ 285 public function attributes(array $attributes) 286 { 287 $this->attributes = array_merge($this->attributes, $attributes); 288 return $this; 289 } 290 291 /** 292 * 293 * Sets the auth value. 294 * 295 * @param mixed $auth The auth value to set. 296 * 297 * @return $this 298 * 299 */ 300 public function auth($auth) 301 { 302 $this->auth = $auth; 303 return $this; 304 } 305 306 /** 307 * 308 * Merges with the existing default values for attributes. 309 * 310 * @param array $defaults Default values for attributes. 311 * 312 * @return $this 313 * 314 */ 315 public function defaults(array $defaults) 316 { 317 $this->defaults = array_merge($this->defaults, $defaults); 318 return $this; 319 } 320 321 /** 322 * 323 * Merges with the existing extra key-value pairs; this merge is recursive, 324 * so the values can be arbitrarily deep. 325 * 326 * @param array $extras The extra key-value pairs. 327 * 328 * @return $this 329 * 330 */ 331 public function extras(array $extras) 332 { 333 $this->extras = array_merge_recursive($this->extras, $extras); 334 return $this; 335 } 336 337 /** 338 * 339 * Sets the failed rule. 340 * 341 * @param mixed $failedRule The failed rule. 342 * 343 * @return $this 344 * 345 */ 346 public function failedRule($failedRule) 347 { 348 $this->failedRule = $failedRule; 349 return $this; 350 } 351 352 /** 353 * 354 * The route leads to this handler. 355 * 356 * @param mixed $handler The handler for this route; if null, uses the 357 * route name. 358 * 359 * @return $this 360 * 361 */ 362 public function handler($handler) 363 { 364 if ($handler === null) { 365 $handler = $this->name; 366 } 367 $this->handler = $handler; 368 return $this; 369 } 370 371 /** 372 * 373 * Sets the host. 374 * 375 * @param mixed $host The host. 376 * 377 * @return $this 378 * 379 */ 380 public function host($host) 381 { 382 $this->host = $host; 383 return $this; 384 } 385 386 /** 387 * 388 * Sets whether or not this route should be used for matching. 389 * 390 * @param bool $isRoutable If true, this route can be matched; if not, it 391 * can be used only to generate a path. 392 * 393 * @return $this 394 * 395 */ 396 public function isRoutable($isRoutable = true) 397 { 398 $this->isRoutable = (bool) $isRoutable; 399 return $this; 400 } 401 402 /** 403 * 404 * Sets the route name; immutable once set. 405 * 406 * @param string $name The route name. 407 * 408 * @return $this 409 * 410 * @throws Exception\ImmutableProperty when the name has already been set. 411 * 412 */ 413 public function name($name) 414 { 415 if ($this->name !== null) { 416 $message = __CLASS__ . '::$name is immutable once set'; 417 throw new Exception\ImmutableProperty($message); 418 } 419 $this->name = $this->namePrefix . $name; 420 return $this; 421 } 422 423 /** 424 * 425 * Appends to the existing name prefix; immutable once $name is set. 426 * 427 * @param string $namePrefix The name prefix to append. 428 * 429 * @return $this 430 * 431 * @throws Exception\ImmutableProperty when the name has already been set. 432 * 433 */ 434 public function namePrefix($namePrefix) 435 { 436 if ($this->name !== null) { 437 $message = __CLASS__ . '::$namePrefix is immutable once $name is set'; 438 throw new Exception\ImmutableProperty($message); 439 } 440 $this->namePrefix = $namePrefix; 441 return $this; 442 } 443 444 /** 445 * 446 * Sets the route path; immutable once set. 447 * 448 * @param string $path The route path. 449 * 450 * @return $this 451 * 452 * @throws Exception\ImmutableProperty when the name has already been set. 453 * 454 */ 455 public function path($path) 456 { 457 if ($this->path !== null) { 458 $message = __CLASS__ . '::$path is immutable once set'; 459 throw new Exception\ImmutableProperty($message); 460 } 461 $this->path = $this->pathPrefix . $path; 462 return $this; 463 } 464 465 /** 466 * 467 * Appends to the existing path prefix; immutable once $path is set. 468 * 469 * @param string $pathPrefix The path prefix to append. 470 * 471 * @return $this 472 * 473 * @throws Exception\ImmutableProperty when the path has already been set. 474 * 475 */ 476 public function pathPrefix($pathPrefix) 477 { 478 if ($this->path !== null) { 479 $message = __CLASS__ . '::$pathPrefix is immutable once $path is set'; 480 throw new Exception\ImmutableProperty($message); 481 } 482 $this->pathPrefix = $pathPrefix; 483 return $this; 484 } 485 486 /** 487 * 488 * Sets whether or not the route must be secure. 489 * 490 * @param bool|null $secure If true, the server must indicate an HTTPS request; 491 * if false, it must *not* be HTTPS; if null, it doesn't matter. 492 * 493 * @return $this 494 * 495 */ 496 public function secure($secure = true) 497 { 498 $this->secure = ($secure === null) ? null : (bool) $secure; 499 return $this; 500 } 501 502 /** 503 * 504 * A callable to use for special matching logic on this individual Route. 505 * 506 * @param callable|null $special A callable to invoke for special matching 507 * logic on this individiual route. The callable should have the signature 508 * `function ($request, $route) : bool`. (Use null or another empty value 509 * to indicate there is no special matching logic.) 510 * 511 * @return $this 512 * 513 */ 514 public function special($special) 515 { 516 $this->special = $special; 517 return $this; 518 } 519 520 /** 521 * 522 * Merges with the existing tokens. 523 * 524 * @param array $tokens The tokens. 525 * 526 * @return $this 527 * 528 */ 529 public function tokens(array $tokens) 530 { 531 $this->tokens = array_merge($this->tokens, $tokens); 532 return $this; 533 } 534 535 /** 536 * 537 * Sets the name of the wildcard token, if any. 538 * 539 * @param string $wildcard The name of the wildcard token, if any. 540 * 541 * @return $this 542 * 543 */ 544 public function wildcard($wildcard) 545 { 546 $this->wildcard = $wildcard; 547 return $this; 548 } 549} 550