| Conditions | 38 |
| Paths | 992 |
| Total Lines | 157 |
| Code Lines | 77 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 1 | ||
| Bugs | 0 | Features | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
| 1 | <?php |
||
| 406 | protected function variable(string $key): mixed |
||
| 407 | { |
||
| 408 | // Support numeric and variable array indicies |
||
| 409 | $matches = []; |
||
| 410 | if (preg_match('|\[[0-9]+\]|', $key)) { |
||
| 411 | $key = (string) preg_replace('|\[([0-9]+)\]|', ".$1", $key); |
||
| 412 | } elseif (preg_match('|\[[0-9a-z._]+\]|', $key, $matches)) { |
||
| 413 | $index = $this->get(str_replace(['[', ']'], '', $matches[0])); |
||
| 414 | if (strlen((string) $index) > 0) { |
||
| 415 | $key = (string) preg_replace('|\[([0-9a-z._]+)\]|', ".$index", $key); |
||
| 416 | } |
||
| 417 | } |
||
| 418 | |||
| 419 | $parts = explode(Token::VARIABLE_ATTR_SEPARATOR, $key); |
||
| 420 | if ($parts !== false) { |
||
| 421 | $object = $this->fetch((string) array_shift($parts)); |
||
| 422 | while (count($parts) > 0) { |
||
| 423 | // since we still have a part to consider |
||
| 424 | // and since we can't dig deeper into plain values |
||
| 425 | // it can be thought as if it has a property with a null value |
||
| 426 | if ( |
||
| 427 | is_object($object) === false |
||
| 428 | && is_array($object) === false |
||
| 429 | && is_string($object) === false |
||
| 430 | ) { |
||
| 431 | return null; |
||
| 432 | } |
||
| 433 | |||
| 434 | // first try to cast an object to an array or value |
||
| 435 | if (is_object($object)) { |
||
| 436 | if (method_exists($object, 'toObject')) { |
||
| 437 | $object = $object->toObject(); |
||
| 438 | } elseif (method_exists($object, 'toArray')) { |
||
| 439 | $object = $object->toArray(); |
||
| 440 | } |
||
| 441 | } |
||
| 442 | |||
| 443 | if (is_null($object)) { |
||
| 444 | return null; |
||
| 445 | } |
||
| 446 | |||
| 447 | if ($object instanceof Drop) { |
||
| 448 | $object->setContext($this); |
||
| 449 | } |
||
| 450 | |||
| 451 | $nextPartName = (string) array_shift($parts); |
||
| 452 | if (is_string($object)) { |
||
| 453 | if ($nextPartName === 'size') { |
||
| 454 | return strlen($object); |
||
| 455 | } |
||
| 456 | |||
| 457 | return null; |
||
| 458 | } |
||
| 459 | |||
| 460 | if (is_array($object)) { |
||
| 461 | if ( |
||
| 462 | $nextPartName === 'first' |
||
| 463 | && count($parts) === 0 |
||
| 464 | && !array_key_exists('first', $object) |
||
| 465 | ) { |
||
| 466 | return ArrayFilter::first($object); |
||
| 467 | } |
||
| 468 | |||
| 469 | if ( |
||
| 470 | $nextPartName === 'last' |
||
| 471 | && count($parts) === 0 |
||
| 472 | && !array_key_exists('last', $object) |
||
| 473 | ) { |
||
| 474 | return ArrayFilter::last($object); |
||
| 475 | } |
||
| 476 | |||
| 477 | if ( |
||
| 478 | $nextPartName === 'size' |
||
| 479 | && count($parts) === 0 |
||
| 480 | && !array_key_exists('size', $object) |
||
| 481 | ) { |
||
| 482 | return count($object); |
||
| 483 | } |
||
| 484 | |||
| 485 | // no key - no value |
||
| 486 | if (!array_key_exists($nextPartName, $object)) { |
||
| 487 | return null; |
||
| 488 | } |
||
| 489 | |||
| 490 | $object = $object[$nextPartName]; |
||
| 491 | continue; |
||
| 492 | } |
||
| 493 | |||
| 494 | if (is_object($object) === false) { |
||
| 495 | // we got plain value, yet asked to resolve a part |
||
| 496 | // think plain values have a null part with any name |
||
| 497 | return null; |
||
| 498 | } |
||
| 499 | |||
| 500 | if ($object instanceof Countable) { |
||
| 501 | if ( |
||
| 502 | $nextPartName === 'size' |
||
| 503 | && count($parts) === 0 |
||
| 504 | ) { |
||
| 505 | return count($object); |
||
| 506 | } |
||
| 507 | } |
||
| 508 | |||
| 509 | if ($object instanceof Drop) { |
||
| 510 | if ($object->hasKey($nextPartName) === false) { |
||
| 511 | return null; |
||
| 512 | } |
||
| 513 | |||
| 514 | $object = $object->invokeDrop($nextPartName); |
||
| 515 | continue; |
||
| 516 | } |
||
| 517 | |||
| 518 | // if it's just a regular object, attempt to access a public method |
||
| 519 | $objectCallable = [$object, $nextPartName]; |
||
| 520 | if (is_callable($objectCallable)) { |
||
| 521 | $object = call_user_func($objectCallable); |
||
| 522 | continue; |
||
| 523 | } |
||
| 524 | |||
| 525 | // if a magic accessor method present... |
||
| 526 | if (method_exists($object, '__get')) { |
||
| 527 | $object = $object->{$nextPartName}; |
||
| 528 | continue; |
||
| 529 | } |
||
| 530 | |||
| 531 | // Inexistent property is a null, PHP-speak |
||
| 532 | if (property_exists($object, $nextPartName) === false) { |
||
| 533 | return null; |
||
| 534 | } |
||
| 535 | |||
| 536 | // then try a property (independent of accessibility) |
||
| 537 | $object = $object->{$nextPartName}; |
||
| 538 | continue; |
||
| 539 | // we'll try casting this object in the next iteration |
||
| 540 | } |
||
| 541 | |||
| 542 | // lastly, try to get an embedded value of an object |
||
| 543 | // value could be of any type, not just string, so we have to do this |
||
| 544 | // conversion here, not later in AbstractBlock::renderAll |
||
| 545 | if (is_object($object) && method_exists($object, 'toObject')) { |
||
| 546 | $object = $object->toObject(); |
||
| 547 | } |
||
| 548 | |||
| 549 | /* |
||
| 550 | * Before here were checks for object types and object to string conversion. |
||
| 551 | * |
||
| 552 | * Now we just return what we have: |
||
| 553 | * - Traversable objects are taken care of inside filters |
||
| 554 | * - Object-to-string conversion is handled at the last moment |
||
| 555 | * in AbstractCondition::stringValue, and in AbstractBlock::renderAll |
||
| 556 | * |
||
| 557 | * This way complex objects could be passed between templates and to filters |
||
| 558 | */ |
||
| 559 | return $object; |
||
| 560 | } |
||
| 561 | |||
| 562 | return null; |
||
| 563 | } |
||
| 565 |