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 |