Completed
Push — develop ( dfd31d...f6e11d )
by
unknown
25:04 queued 17:04
created

AbstractSettingsForm   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 110
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 4

Importance

Changes 2
Bugs 2 Features 0
Metric Value
wmc 12
c 2
b 2
f 0
lcom 2
cbo 4
dl 0
loc 110
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getHydrator() 0 8 2
A setObject() 0 11 2
A setName() 0 10 1
A bind() 0 6 1
A getModuleName() 0 8 1
A __construct() 0 5 1
B build() 0 25 3
A factory() 0 4 1
1
<?php
2
/**
3
 * YAWIK
4
 *
5
 * @filesource
6
 * @copyright (c) 2013 - 2016 Cross Solution (http://cross-solution.de)
7
 * @license   MIT
8
 */
9
10
/** AbstractSettingsForm.php */
11
namespace Settings\Form;
12
13
use Core\Form\Form;
14
use Settings\Entity\ModuleSettingsContainerInterface;
15
use Zend\ServiceManager\ServiceLocatorInterface;
16
use Zend\Form\FormInterface;
17
use Settings\Entity\Hydrator\SettingsEntityHydrator;
18
19
class AbstractSettingsForm extends Form
20
{
21
    /**
22
     * @var bool
23
     */
24
    protected $isBuild = false;
25
    
26
    /**
27
     * @var ServiceLocatorInterface
28
     */
29
    protected $formManager;
30
    
31
    /**
32
     * @param ServiceLocatorInterface $formManager
33
     */
34
    public function __construct(ServiceLocatorInterface $formManager)
35
    {
36
        parent::__construct();
37
        $this->formManager = $formManager;
38
    }
39
    
40
    /**
41
     * @see \Core\Form\Form::getHydrator()
42
     */
43
    public function getHydrator()
44
    {
45
        if (!$this->hydrator) {
46
            $hydrator = new SettingsEntityHydrator();
47
            $this->setHydrator($hydrator);
48
        }
49
        return $this->hydrator;
50
    }
51
    
52
    public function build()
53
    {
54
        if ($this->isBuild) {
55
            return;
56
        }
57
        $this->setAttribute('method', 'post');
58
        $object = $this->getObject();
59
        $fieldsetName = $object->getModuleName() . '/SettingsFieldset';
60
        
61
        if ($this->formManager->has($fieldsetName)) {
62
            $fieldset = $this->formManager->get($fieldsetName);
63
        } else {
64
            $fieldset = $this->formManager->get('Settings/Fieldset');
65
            $fieldset->setLabel($object->getModuleName());
66
        }
67
        
68
        $fieldset->setUseAsBaseFieldset(true)
69
                 ->setName('base');
70
        
71
        $fieldset->setObject($object);
72
        $this->add($fieldset);
0 ignored issues
show
Bug introduced by
It seems like $fieldset can also be of type object; however, Core\Form\Form::add() does only seem to accept array|object<Traversable...\Form\ElementInterface>, 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...
73
        
74
        $this->add($this->formManager->get('DefaultButtonsFieldset'));
75
        $this->isBuild=true;
76
    }
77
        
78
79
    public function setObject($object)
80
    {
81
        if (!$object instanceof ModuleSettingsContainerInterface) {
82
            throw new \InvalidArgumentException('Object must implement ModuleSettingsContainerInterface');
83
        }
84
        parent::setObject($object);
85
        $moduleName = $object->getModuleName();
86
        $this->setName($moduleName);
87
        $this->build();
88
        return $this;
89
    }
90
    
91
    public function setName($name)
92
    {
93
        parent::setName(strtolower($name) . '-settings');
94
        $urlHelper = $this->formManager->getServiceLocator()
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\ServiceManager\ServiceLocatorInterface as the method getServiceLocator() does only exist in the following implementations of said interface: Acl\Assertion\AssertionManager, Core\Mail\MailService, Core\Paginator\PaginatorService, Zend\Barcode\ObjectPluginManager, Zend\Barcode\RendererPluginManager, Zend\Cache\PatternPluginManager, Zend\Cache\Storage\AdapterPluginManager, Zend\Cache\Storage\PluginManager, Zend\Config\ReaderPluginManager, Zend\Config\WriterPluginManager, Zend\Feed\Reader\ExtensionPluginManager, Zend\Feed\Writer\ExtensionPluginManager, Zend\File\Transfer\Adapter\FilterPluginManager, Zend\File\Transfer\Adapter\ValidatorPluginManager, Zend\Filter\FilterPluginManager, Zend\Form\FormElementMan...lementManagerV2Polyfill, Zend\Form\FormElementMan...lementManagerV3Polyfill, Zend\Hydrator\HydratorPluginManager, Zend\I18n\Translator\LoaderPluginManager, Zend\InputFilter\InputFilterPluginManager, Zend\Log\FilterPluginManager, Zend\Log\FormatterPluginManager, Zend\Log\ProcessorPluginManager, Zend\Log\WriterPluginManager, Zend\Log\Writer\FilterPluginManager, Zend\Log\Writer\FormatterPluginManager, Zend\Mail\Protocol\SmtpPluginManager, Zend\Mvc\Controller\ControllerManager, Zend\Mvc\Controller\PluginManager, Zend\Mvc\Router\RoutePluginManager, Zend\Paginator\AdapterPluginManager, Zend\Paginator\ScrollingStylePluginManager, Zend\Serializer\AdapterPluginManager, Zend\ServiceManager\AbstractPluginManager, Zend\Tag\Cloud\DecoratorPluginManager, Zend\Text\Table\DecoratorManager, Zend\Validator\ValidatorPluginManager, Zend\View\HelperPluginManager, Zend\View\Helper\Navigation\PluginManager.

Let’s take a look at an example:

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

class MyUser implements 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 implementation 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 interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
95
                     ->get('ViewHelperManager')
96
                     ->get('url');
97
        
98
        $url = $urlHelper('lang/settings', array('module' => $name), true);
99
        $this->setAttribute('action', $url);
100
    }
101
102
    
103
    public function bind($object, $flags = FormInterface::VALUES_NORMALIZED)
104
    {
105
        /** Ensure the form is build prior to binding */
106
        $this->setObject($object);
107
        return parent::bind($object);
108
    }
109
    
110
    
111
    protected function getModuleName()
112
    {
113
        $refl       = new \ReflectionClass($this);
114
        $namespace  = ltrim($refl->getNamespaceName(), '\\');
115
        $moduleName = substr($namespace, 0, strpos($namespace, '\\'));
116
117
        return strtolower($moduleName);
118
    }
119
    
120
    /**
121
     * @param ServiceLocatorInterface $formManager
122
     * @return AbstractSettingsForm
123
     */
124
    public static function factory(ServiceLocatorInterface $formManager)
125
    {
126
        return new static($formManager);
127
    }
128
}
129