Form   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 110
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 5

Importance

Changes 0
Metric Value
wmc 20
lcom 2
cbo 5
dl 0
loc 110
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 2
A getPresenter() 0 4 1
C attached() 0 27 8
A isAnchored() 0 4 1
B receiveHttpData() 0 19 5
A signalReceived() 0 11 3
1
<?php
2
3
/**
4
 * This file is part of the Nette Framework (http://nette.org)
5
 *
6
 * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
7
 *
8
 * For the full copyright and license information, please view
9
 * the file license.txt that was distributed with this source code.
10
 */
11
12
namespace Nette\Application\UI;
13
14
use Nette;
15
16
/**
17
 * Web form adapted for Presenter.
18
 *
19
 * @author     David Grudl
20
 *
21
 * @property-read Presenter $presenter
22
 */
23
class Form extends Nette\Forms\Form implements ISignalReceiver
24
{
25
    /**
26
     * Application form constructor.
27
     */
28
    public function __construct(Nette\ComponentModel\IContainer $parent = null, $name = null)
29
    {
30
        parent::__construct();
31
        $this->monitor('Nette\Application\UI\Presenter');
32
        if ($parent !== NULL) {
33
            $parent->addComponent($this, $name);
34
        }
35
    }
36
37
    /**
38
     * Returns the presenter where this component belongs to.
39
     * @param  bool   throw exception if presenter doesn't exist?
40
     * @return Nette\ComponentModel\IComponent
41
     */
42
    public function getPresenter($need = true)
43
    {
44
        return $this->lookup('Nette\Application\UI\Presenter', $need);
45
    }
46
47
    /**
48
     * This method will be called when the component (or component's parent)
49
     * becomes attached to a monitored object. Do not call this method yourself.
50
     * @param  Nette\ComponentModel\IComponent
51
     * @return void
52
     */
53
    protected function attached($presenter)
54
    {
55
        if ($presenter instanceof Presenter) {
56
            $name = $this->lookupPath('Nette\Application\UI\Presenter');
57
58
            if (!isset($this->getElementPrototype()->id)) {
59
                $this->getElementPrototype()->id = 'frm-'.$name;
60
            }
61
62
            if (!$this->getAction()) {
63
                $this->setAction(new Link(
64
                    $presenter,
65
                    $name.self::NAME_SEPARATOR.'submit!',
66
                    array()
67
                ));
68
            }
69
70
            if (iterator_count($this->getControls()) && $this->isSubmitted()) {
71
                foreach ($this->getControls() as $control) {
72
                    if (!$control->isDisabled()) {
73
                        $control->loadHttpData();
74
                    }
75
                }
76
            }
77
        }
78
        parent::attached($presenter);
79
    }
80
81
    /**
82
     * Tells if the form is anchored.
83
     * @return bool
84
     */
85
    public function isAnchored()
86
    {
87
        return (bool) $this->getPresenter(false);
88
    }
89
90
    /**
91
     * Internal: returns submitted HTTP data or NULL when form was not submitted.
92
     * @return array|NULL
93
     */
94
    protected function receiveHttpData()
95
    {
96
        $presenter = $this->getPresenter();
97
        if (!$presenter->isSignalReceiver($this, 'submit')) {
98
            return;
99
        }
100
101
        $isPost = $this->getMethod() === self::POST;
102
        $request = $presenter->getRequest();
103
        if ($request->isMethod('forward') || $request->isMethod('post') !== $isPost) {
104
            return;
105
        }
106
107
        if ($isPost) {
108
            return Nette\Utils\Arrays::mergeTree($request->getPost(), $request->getFiles());
109
        } else {
110
            return $request->getParameters();
111
        }
112
    }
113
114
    /********************* interface ISignalReceiver ****************d*g**/
115
116
    /**
117
     * This method is called by presenter.
118
     * @param  string
119
     * @return void
120
     */
121
    public function signalReceived($signal)
122
    {
123
        if ($signal === 'submit') {
124
            if (!$this->getPresenter()->getRequest()->hasFlag(Nette\Application\Request::RESTORED)) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Nette\ComponentModel\IComponent as the method getRequest() does only exist in the following implementations of said interface: AdminModule\BasePresenter, AdminModule\CloningPresenter, AdminModule\FilesystemPresenter, AdminModule\HomepagePresenter, AdminModule\LanguagesPresenter, AdminModule\LoginPresenter, AdminModule\PagesPresenter, AdminModule\SettingsPresenter, AdminModule\TranslationsPresenter, AdminModule\TranslatorPresenter, AdminModule\UpdatePresenter, AdminModule\UsersPresenter, ErrorPresenter, FrontendModule\BasePresenter, FrontendModule\HomepagePresenter, FrontendModule\LoginPresenter, Grido\Tests\TestPresenter, Nette\Application\UI\Presenter, WebCMS2\Common\BasePresenter.

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...
125
                $this->fireEvents();
126
            }
127
        } else {
128
            $class = get_class($this);
129
            throw new BadSignalException("Missing handler for signal '$signal' in $class.");
130
        }
131
    }
132
}
133