Document::__construct()   B
last analyzed

Complexity

Conditions 4
Paths 1

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
rs 8.6845
c 0
b 0
f 0
cc 4
eloc 14
nc 1
nop 1
1
<?php
2
/*
3
 * Copyright (C) 2015 Michael Herold <[email protected]>
4
 *
5
 * This program is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18
19
namespace hemio\form;
20
21
/**
22
 * Description of Document
23
 *
24
 * @author Michael Herold <[email protected]>
25
 */
26
class Document extends \hemio\html\Document
27
{
28
29
    public function __construct(\hemio\html\Interface_\ContentModelText $objTitleContent)
30
    {
31
        parent::__construct($objTitleContent);
32
33
        $this->addHookToString(
34
            function (\hemio\html\Interface_\HtmlCode $elem) {
35
            $filter = function ($elem) {
36
                return $elem instanceof \hemio\form\Focusable;
37
            };
38
39
            $curLevel     = 0;
40
            $curFocusable = null;
41
            foreach ($elem->getRecursiveIterator($filter) as $focusable) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface hemio\html\Interface_\HtmlCode as the method getRecursiveIterator() does only exist in the following implementations of said interface: hemio\form\Abstract_\Form, hemio\form\Abstract_\FormElement, hemio\form\Abstract_\FormField, hemio\form\Abstract_\FormFieldDefault, hemio\form\Abstract_\FormFieldInput, hemio\form\Abstract_\Template, hemio\form\Abstract_\TemplateFormField, hemio\form\ButtonGroup, hemio\form\Container, hemio\form\ContainerHiding, hemio\form\Document, hemio\form\FieldCheckbox, hemio\form\FieldEmail, hemio\form\FieldNumber, hemio\form\FieldPassword, hemio\form\FieldRadio, hemio\form\FieldSelect, hemio\form\FieldSubmit, hemio\form\FieldTel, hemio\form\FieldText, hemio\form\FieldTextarea, hemio\form\FormGet, hemio\form\FormPost, hemio\form\InputHidden, hemio\form\template\FormLineP, hemio\form\template\FormPlainControl, hemio\html\A, hemio\html\Abbr, hemio\html\Abstract_\ElementContent, hemio\html\Address, hemio\html\Area, hemio\html\Article, hemio\html\Aside, hemio\html\Audio, hemio\html\B, hemio\html\Bdi, hemio\html\Bdo, hemio\html\Blockquote, hemio\html\Body, hemio\html\Button, hemio\html\Canvas, hemio\html\Caption, hemio\html\Cite, hemio\html\Code, hemio\html\Col, hemio\html\Colgroup, hemio\html\Data, hemio\html\Datalist, hemio\html\Dd, hemio\html\Del, hemio\html\Dfn, hemio\html\Div, hemio\html\Dl, hemio\html\Document, hemio\html\Dt, hemio\html\Em, hemio\html\Embed, hemio\html\Fieldset, hemio\html\Figcaption, hemio\html\Figure, hemio\html\Footer, hemio\html\Form, hemio\html\H1, hemio\html\H2, hemio\html\H3, hemio\html\H4, hemio\html\H5, hemio\html\H6, hemio\html\Head, hemio\html\Header, hemio\html\Html, hemio\html\I, hemio\html\Iframe, hemio\html\Ins, hemio\html\Kbd, hemio\html\Keygen, hemio\html\Label, hemio\html\Legend, hemio\html\Li, hemio\html\Map, hemio\html\Mark, hemio\html\Meter, hemio\html\Nav, hemio\html\Noscript, hemio\html\Object, hemio\html\Ol, hemio\html\Optgroup, hemio\html\Option, hemio\html\Output, hemio\html\P, hemio\html\Param, hemio\html\Pre, hemio\html\Progress, hemio\html\Q, hemio\html\Rp, hemio\html\Rt, hemio\html\Ruby, hemio\html\S, hemio\html\Samp, hemio\html\Script, hemio\html\Section, hemio\html\Select, hemio\html\Small, hemio\html\Source, hemio\html\Span, hemio\html\Strong, hemio\html\Style, hemio\html\Sub, hemio\html\Sup, hemio\html\Table, hemio\html\Tbody, hemio\html\Td, hemio\html\Template, hemio\html\Textarea, hemio\html\Tfoot, hemio\html\Th, hemio\html\Thead, hemio\html\Time, hemio\html\Title, hemio\html\Tr, hemio\html\Track, hemio\html\U, hemio\html\Ul, hemio\html\Variable, hemio\html\Video, hemio\html\Wbr.

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...
42
                if ($focusable->getAutofocusLevel() > $curLevel) {
43
                    $curFocusable = $focusable;
44
                    $curLevel     = $focusable->getAutofocusLevel();
45
                }
46
            }
47
48
            if ($curFocusable !== null)
49
                $curFocusable->engageAutofocus();
50
        }
51
        );
52
    }
53
}
54