ElementFactory::__call()   B
last analyzed

Complexity

Conditions 9
Paths 10

Size

Total Lines 35
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 9
eloc 21
c 2
b 0
f 0
nc 10
nop 2
dl 0
loc 35
rs 8.0555
1
<?php
2
3
namespace ntentan\honam\engines\php\helpers\form;
4
5
use ntentan\honam\exceptions\HonamException;
6
use ntentan\utils\Text;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, ntentan\honam\engines\php\helpers\form\Text. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
7
8
/**
9
 * A trait that allows for chaining the methods in form elements.
10
 */
11
trait ElementFactory
12
{
13
14
    private $caller;
15
16
    /**
17
     * Recursively go through the chain of classes in the form to find one that supplies the required method.
18
     */
19
    public function findMethodClass($name)
20
    {
21
        if ($this->caller === null) {
22
            return null;
23
        } else if (method_exists($this->caller, $name)) {
24
            return $this->caller;
25
        } else {
26
            return $this->caller->findMethodClass($name);
27
        }
28
    }
29
30
    public function __call($name, $arguments)
31
    {
32
        // Check if the method exists in the object under which the element was created.
33
        $methodClass = $this->findMethodClass($name);
34
        if ($methodClass !== null) {
35
            return call_user_func_array([$methodClass, $name], $arguments);
36
        }
37
38
        if (str_starts_with($name, "open_")) {
39
            // Allow for magic methods that open containers.
40
            $containerCheck = true;
41
            $name = substr($name, 5);
42
        } else if (str_starts_with($name, "close_")) {
43
            // Allow for magic methods that close containers.
44
            return $this->popContainer(substr($name, 6));
0 ignored issues
show
Bug introduced by
The method popContainer() does not exist on ntentan\honam\engines\ph...ers\form\ElementFactory. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

44
            return $this->/** @scrutinizer ignore-call */ popContainer(substr($name, 6));
Loading history...
45
        } else {
46
            $containerCheck = false;
47
        }
48
49
        // Create an instance of the element we need
50
        $elementClass = new \ReflectionClass(__NAMESPACE__ . "\\" . Text::ucamelize($name));
51
        $element = $elementClass->newInstanceArgs($arguments == null ? array() : $arguments);
52
        $element->setTemplateRenderer($this->templateRenderer);
53
        $element->setCaller($this);
54
55
        //
56
        if ($containerCheck && is_a($element, __NAMESPACE__ . "\\Container")) {
57
            $this->pushContainer($name, $element);
0 ignored issues
show
Bug introduced by
The method pushContainer() does not exist on ntentan\honam\engines\ph...ers\form\ElementFactory. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

57
            $this->/** @scrutinizer ignore-call */ 
58
                   pushContainer($name, $element);
Loading history...
58
        } else if ($containerCheck) {
59
            throw new HonamException("Element $name is not a container. Use the open_ prefix only when creating a container.");
60
        } else if (!$containerCheck) {
0 ignored issues
show
introduced by
The condition $containerCheck is always false.
Loading history...
61
            $this->getActiveContainer()->add($element);
0 ignored issues
show
Bug introduced by
The method getActiveContainer() does not exist on ntentan\honam\engines\ph...ers\form\ElementFactory. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

61
            $this->/** @scrutinizer ignore-call */ 
62
                   getActiveContainer()->add($element);
Loading history...
62
        }
63
64
        return $element;
65
    }
66
67
    public function setCaller($caller)
68
    {
69
        $this->caller = $caller;
70
    }
71
}
72