Completed
Pull Request — master (#14)
by
unknown
08:12
created

TemplateManager::resolveAndSetTemplatePathIfCan()   C

Complexity

Conditions 14
Paths 26

Size

Total Lines 46
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 46
rs 5.0744
c 0
b 0
f 0
cc 14
eloc 41
nc 26
nop 1

How to fix   Complexity   

Long Method

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:

1
<?php
2
3
namespace SimpleEntityGeneratorBundle\Lib;
4
5
use SimpleEntityGeneratorBundle\Lib\Interfaces\RenderableInterface;
6
use Symfony\Component\HttpKernel\KernelInterface;
7
use Symfony\Component\HttpKernel\Config\FileLocator;
8
use SimpleEntityGeneratorBundle\Lib\Items\ClassConstructorManager;
9
use SimpleEntityGeneratorBundle\Lib\Items\InterfaceManager;
10
use SimpleEntityGeneratorBundle\Lib\Items\TestClassManager;
11
use SimpleEntityGeneratorBundle\Lib\Items\TestMethodManager;
12
use SimpleEntityGeneratorBundle\Lib\Items\MethodGetterManager;
13
use SimpleEntityGeneratorBundle\Lib\Items\MethodGetterInterfaceManager;
14
use SimpleEntityGeneratorBundle\Lib\Items\MethodGetterBooleanManager;
15
use SimpleEntityGeneratorBundle\Lib\Items\MethodGetterBooleanInterfaceManager;
16
use SimpleEntityGeneratorBundle\Lib\Items\ClassManager;
17
use SimpleEntityGeneratorBundle\Lib\Items\MethodSetterManager;
18
use SimpleEntityGeneratorBundle\Lib\Items\MethodSetterInterfaceManager;
19
use SimpleEntityGeneratorBundle\Lib\Items\PropertyManager;
20
21
/**
22
 * @author Sławomir Kania <[email protected]>
23
 */
24
class TemplateManager
25
{
26
27
    /**
28
     * @var KernelInterface
29
     */
30
    private $kernel;
31
32
    /**
33
     * CONSTRUCT
34
     *
35
     * @param KernelInterface $kernel
36
     */
37
    public function __construct(KernelInterface $kernel)
38
    {
39
        $this->kernel = $kernel;
40
    }
41
42
    /**
43
     * @param RenderableInterface $item
44
     */
45
    public function loadAndSetTemplateOnItem(RenderableInterface $item)
46
    {
47
        $this->resolveAndSetTemplatePathIfCan($item);
48
        $template = null;
0 ignored issues
show
Unused Code introduced by
$template is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
49
        if (false === empty($item->getTemplate())) {
50
            $template = $item->getTemplate();
51
        } elseif (false === empty($item->getTemplatePath())) {
52
            $path = $this->getFileLocator()->locate("@".$item->getTemplatePath()); // may throw exception
53
            $template = $this->getFilesManager()->loadContentFromFile($path);
0 ignored issues
show
Bug introduced by
It seems like $path defined by $this->getFileLocator()-...tem->getTemplatePath()) on line 52 can also be of type array; however, SimpleEntityGeneratorBun...::loadContentFromFile() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
54
        } else {
55
            // default template
56
            $reflect = new \ReflectionClass($item);
57
            $paramName = $reflect->getShortName()."TemplatePath";
58
59
            if (false === $this->kernel->getContainer()->hasParameter($paramName)) {
60
                throw new \RuntimeException(sprintf("No parameter %s set", $paramName));
61
            }
62
63
            $path = $this->getFileLocator()->locate("@".$this->kernel->getContainer()->getParameter($paramName)); // may throw exception
64
            $template = $this->getFilesManager()->loadContentFromFile($path);
0 ignored issues
show
Bug introduced by
It seems like $path defined by $this->getFileLocator()-...tParameter($paramName)) on line 63 can also be of type array; however, SimpleEntityGeneratorBun...::loadContentFromFile() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
65
        }
66
67
        $item->setTemplate($template);
68
    }
69
70
    /**
71
     * @return FilesManager
72
     */
73
    public function getFilesManager()
74
    {
75
        return $this->kernel->getContainer()->get("seg.files_manager");
76
    }
77
78
    /**
79
     * @return FileLocator
80
     */
81
    public function getFileLocator()
82
    {
83
        return $this->kernel->getContainer()->get("file_locator");
84
    }
85
86
    /**
87
     * @param RenderableInterface $item
88
     */
89
    protected function resolveAndSetTemplatePathIfCan(RenderableInterface $item)
90
    {
91
        $templatePath = "";
92
        switch (true) {
93
            case $item instanceof ClassManager:
94
                $templatePath = $item->getClassManagerTemplatePath();
95
                break;
96
            case $item instanceof PropertyManager:
97
                $templatePath = $item->getPropertyManagerTemplatePath();
98
                break;
99
            case $item instanceof ClassConstructorManager:
100
                $templatePath = $item->getClassManager()->getClassConstructorManagerTemplatePath();
101
                break;
102
            case $item instanceof InterfaceManager:
103
                $templatePath = $item->getClassManager()->getInterfaceManagerTemplatePath();
104
                break;
105
            case $item instanceof TestClassManager:
106
                $templatePath = $item->getClassManager()->getTestClassManagerTemplatePath();
107
                break;
108
            case $item instanceof TestMethodManager:
109
                $templatePath = $item->getMethod()->getProperty()->getTestClassMethodManagerTemplatePath();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class SimpleEntityGeneratorBun...Lib\Items\MethodManager as the method getProperty() does only exist in the following sub-classes of SimpleEntityGeneratorBun...Lib\Items\MethodManager: SimpleEntityGeneratorBun...ethodForPropertyManager, SimpleEntityGeneratorBun...BooleanInterfaceManager, SimpleEntityGeneratorBun...hodGetterBooleanManager, SimpleEntityGeneratorBun...dGetterInterfaceManager, SimpleEntityGeneratorBun...ems\MethodGetterManager, SimpleEntityGeneratorBun...dSetterInterfaceManager, SimpleEntityGeneratorBun...ems\MethodSetterManager. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
110
                break;
111
            case $item instanceof MethodGetterManager:
112
                $templatePath = $item->getProperty()->getMethodGetterManagerTemplatePath();
113
                break;
114
            case $item instanceof MethodGetterInterfaceManager:
115
                $templatePath = $item->getProperty()->getMethodGetterInterfaceManagerTemplatePath();
116
                break;
117
            case $item instanceof MethodGetterBooleanManager:
118
                $templatePath = $item->getProperty()->getMethodGetterBooleanManagerTemplatePath();
119
                break;
120
            case $item instanceof MethodGetterBooleanInterfaceManager:
121
                $templatePath = $item->getProperty()->getMethodGetterBooleanInterfaceManageTemplatePath();
122
                break;
123
            case $item instanceof MethodSetterInterfaceManager:
124
                $templatePath = $item->getProperty()->getMethodSetterInterfaceManagerTemplatePath();
125
                break;
126
            case $item instanceof MethodSetterManager:
127
                $templatePath = $item->getProperty()->getMethodSetterManagerTemplatePath();
128
                break;
129
        }
130
131
        if (false === empty($templatePath)) {
132
            $item->setTemplatePath($templatePath);
133
        }
134
    }
135
}
136