| Conditions | 41 | 
| Paths | 1120 | 
| Total Lines | 158 | 
| 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) | ||
| 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 (is_string($index) && strlen($index) > 0) { | ||
| 415 |                 $key = (string) preg_replace('|\[([0-9a-z._]+)\]|', ".$index", $key); | ||
| 416 | } | ||
| 417 | } | ||
| 418 | |||
| 419 | $parts = explode(Token::VARIABLE_ATTR_SEPARATOR, $key); | ||
| 420 | |||
| 421 |         if ($parts !== false) { | ||
| 422 | $object = $this->fetch((string) array_shift($parts)); | ||
| 423 |             while (count($parts) > 0) { | ||
| 424 | // since we still have a part to consider | ||
| 425 | // and since we can't dig deeper into plain values | ||
| 426 | // it can be thought as if it has a property with a null value | ||
| 427 | if ( | ||
| 428 | !is_object($object) | ||
| 429 | && !is_array($object) | ||
| 430 | && !is_string($object) | ||
| 431 |                 ) { | ||
| 432 | return null; | ||
| 433 | } | ||
| 434 | |||
| 435 | // first try to cast an object to an array or value | ||
| 436 |                 if (is_object($object)) { | ||
| 437 |                     if (method_exists($object, 'toObject')) { | ||
| 438 | $object = $object->toObject(); | ||
| 439 |                     } elseif (method_exists($object, 'toArray')) { | ||
| 440 | $object = $object->toArray(); | ||
| 441 | } | ||
| 442 | } | ||
| 443 | |||
| 444 |                 if (is_null($object)) { | ||
| 445 | return null; | ||
| 446 | } | ||
| 447 | |||
| 448 |                 if ($object instanceof Drop) { | ||
| 449 | $object->setContext($this); | ||
| 450 | } | ||
| 451 | |||
| 452 | $nextPartName = (string) array_shift($parts); | ||
| 453 |                 if (is_string($object)) { | ||
| 454 |                     if ($nextPartName === 'size') { | ||
| 455 | return strlen($object); | ||
| 456 | } | ||
| 457 | |||
| 458 | return null; | ||
| 459 | } | ||
| 460 | |||
| 461 | |||
| 462 |                 if (is_array($object)) { | ||
| 463 | if ( | ||
| 464 | $nextPartName === 'first' | ||
| 465 | && count($parts) === 0 | ||
| 466 |                         && !array_key_exists('first', $object) | ||
| 467 |                     ) { | ||
| 468 | return ArrayFilter::first($object); | ||
| 469 | } | ||
| 470 | |||
| 471 | if ( | ||
| 472 | $nextPartName === 'last' | ||
| 473 | && count($parts) === 0 | ||
| 474 |                         && !array_key_exists('last', $object) | ||
| 475 |                     ) { | ||
| 476 | return ArrayFilter::last($object); | ||
| 477 | } | ||
| 478 | |||
| 479 | if ( | ||
| 480 | $nextPartName === 'size' | ||
| 481 | && count($parts) === 0 | ||
| 482 |                         && !array_key_exists('size', $object) | ||
| 483 |                     ) { | ||
| 484 | return count($object); | ||
| 485 | } | ||
| 486 | |||
| 487 | // no key - no value | ||
| 488 |                     if (!array_key_exists($nextPartName, $object)) { | ||
| 489 | return null; | ||
| 490 | } | ||
| 491 | |||
| 492 | $object = $object[$nextPartName]; | ||
| 493 | continue; | ||
| 494 | } | ||
| 495 | |||
| 496 |                 if (!is_object($object)) { | ||
| 497 | // we got plain value, yet asked to resolve a part | ||
| 498 | // think plain values have a null part with any name | ||
| 499 | return null; | ||
| 500 | } | ||
| 501 | |||
| 502 |                 if ($object instanceof Countable) { | ||
| 503 | if ( | ||
| 504 | $nextPartName === 'size' | ||
| 505 | && count($parts) === 0 | ||
| 506 |                     ) { | ||
| 507 | return count($object); | ||
| 508 | } | ||
| 509 | } | ||
| 510 | |||
| 511 |                 if ($object instanceof Drop) { | ||
| 512 |                     if (!$object->hasKey($nextPartName)) { | ||
| 513 | return null; | ||
| 514 | } | ||
| 515 | |||
| 516 | $object = $object->invokeDrop($nextPartName); | ||
| 517 | continue; | ||
| 518 | } | ||
| 519 | |||
| 520 | // if it's just a regular object, attempt to access a public method | ||
| 521 | $objectCallable = [$object, $nextPartName]; | ||
| 522 |                 if (is_callable($objectCallable)) { | ||
| 523 | $object = call_user_func($objectCallable); | ||
| 524 | continue; | ||
| 525 | } | ||
| 526 | |||
| 527 | // if a magic accessor method present... | ||
| 528 |                 if (is_object($object) && method_exists($object, '__get')) { | ||
| 529 |                     $object = $object->{$nextPartName}; | ||
| 530 | continue; | ||
| 531 | } | ||
| 532 | |||
| 533 | // Inexistent property is a null, PHP-speak | ||
| 534 |                 if (!property_exists($object, $nextPartName)) { | ||
| 535 | return null; | ||
| 536 | } | ||
| 537 | |||
| 538 | // then try a property (independent of accessibility) | ||
| 539 |                 if (property_exists($object, $nextPartName)) { | ||
| 540 |                     $object = $object->{$nextPartName}; | ||
| 541 | continue; | ||
| 542 | } | ||
| 543 | // we'll try casting this object in the next iteration | ||
| 544 | } | ||
| 545 | |||
| 546 | // lastly, try to get an embedded value of an object | ||
| 547 | // value could be of any type, not just string, so we have to do this | ||
| 548 | // conversion here, not later in AbstractBlock::renderAll | ||
| 549 |             if (is_object($object) && method_exists($object, 'toObject')) { | ||
| 550 | $object = $object->toObject(); | ||
| 551 | } | ||
| 552 | |||
| 553 | /* | ||
| 554 | * Before here were checks for object types and object to string conversion. | ||
| 555 | * | ||
| 556 | * Now we just return what we have: | ||
| 557 | * - Traversable objects are taken care of inside filters | ||
| 558 | * - Object-to-string conversion is handled at the last moment | ||
| 559 | * in AbstractCondition::stringValue, and in AbstractBlock::renderAll | ||
| 560 | * | ||
| 561 | * This way complex objects could be passed between templates and to filters | ||
| 562 | */ | ||
| 563 | return $object; | ||
| 564 | } | ||
| 567 |