Completed
Push — master ( 8048cf...eb2d15 )
by
unknown
03:03
created

SelectInput::choices()   C

Complexity

Conditions 7
Paths 18

Size

Total Lines 30
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 1
Metric Value
c 3
b 1
f 1
dl 0
loc 30
rs 6.7272
cc 7
eloc 18
nc 18
nop 0
1
<?php
2
3
namespace Charcoal\Admin\Property\Input;
4
5
use \Charcoal\Admin\Property\AbstractPropertyInput;
6
7
/**
8
 *
9
 */
10
class SelectInput extends AbstractPropertyInput
0 ignored issues
show
Bug introduced by
There is one abstract method propertyValue in this class; you could implement it, or declare this class as abstract.
Loading history...
11
{
12
    /**
13
     * @return void This method is a generator
14
     */
15
    public function choices()
16
    {
17
        $choices = $this->p()->choices();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Charcoal\Property\PropertyInterface as the method choices() does only exist in the following implementations of said interface: Charcoal\Property\BooleanProperty, Charcoal\Property\HtmlProperty, Charcoal\Property\LangProperty, Charcoal\Property\ObjectProperty, Charcoal\Property\PasswordProperty, Charcoal\Property\PhoneProperty, Charcoal\Property\StringProperty, Charcoal\Property\TextProperty, Charcoal\Property\UrlProperty.

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...
18
19
        if ($this->p()->allowNull() && !$this->p()->multiple()) {
20
            $prepend = [
21
                'value'   => '',
22
                'label'   => $this->placeholder(),
23
                'title'   => $this->placeholder(),
24
                'subtext' => ''
25
            ];
26
27
            yield $prepend;
28
        }
29
30
        foreach ($choices as $choiceIdent => $choice) {
31
            if (!isset($choice['value'])) {
32
                $choice['value'] = $choiceIdent;
33
            }
34
            if (!isset($choice['label'])) {
35
                $choice['label'] = ucwords(strtolower(str_replace('_', ' ', $choiceIdent)));
36
            }
37
            if (!isset($choice['title'])) {
38
                $choice['title'] = $choice['label'];
39
            }
40
            $choice['selected'] = $this->isChoiceSelected($choiceIdent);
41
42
            yield $choice;
43
        }
44
    }
45
46
    /**
47
     * @param mixed $c The choice to check.
48
     * @return boolean
49
     */
50
    public function isChoiceSelected($c)
51
    {
52
        $val = $this->p()->val();
53
        if ($val === null) {
54
            return false;
55
        }
56
        if ($this->p()->multiple()) {
57
            return in_array($c, $val);
58
        } else {
59
            return $c == $val;
60
        }
61
    }
62
}
63