TableRow::__invoke()   F
last analyzed

Complexity

Conditions 22
Paths 494

Size

Total Lines 109
Code Lines 64

Duplication

Lines 13
Ratio 11.93 %

Importance

Changes 0
Metric Value
dl 13
loc 109
rs 3.0425
c 0
b 0
f 0
cc 22
eloc 64
nc 494
nop 5

How to fix   Long Method    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 ZfcDatagrid\Renderer\BootstrapTable\View\Helper;
4
5
use Zend\View\Helper\AbstractHelper;
6
use ZfcDatagrid\Column;
7
use ZfcDatagrid\Column\Action\AbstractAction;
8
9
/**
10
 * View Helper.
11
 */
12
class TableRow extends AbstractHelper
13
{
14
    /** @var \Zend\I18n\Translator\Translator|null|false */
15
    private $translator;
16
17
    /**
18
     * @param false|null|\Zend\I18n\Translator\Translator $translator
19
     *
20
     * @return self
21
     */
22
    public function setTranslator($translator)
23
    {
24
        $this->translator = $translator;
25
26
        return $this;
27
    }
28
29
    /**
30
     * @param string $message
31
     *
32
     * @return string
33
     */
34
    private function translate($message)
35
    {
36
        if (null === $this->translator) {
37
            return $message;
38
        }
39
40
        return $this->translator->translate($message);
41
    }
42
43
    /**
44
     * @param $row
45
     * @param bool|true $open
46
     *
47
     * @return string
48
     */
49
    private function getTr($row, $open = true)
50
    {
51
        if ($open !== true) {
52
            return '</tr>';
53
        } else {
54
            if (isset($row['idConcated'])) {
55
                return '<tr id="'.$row['idConcated'].'">';
56
            } else {
57
                return '<tr>';
58
            }
59
        }
60
    }
61
62
    /**
63
     * @param $dataValue
64
     * @param array $attributes
65
     *
66
     * @return string
67
     */
68
    private function getTd($dataValue, $attributes = [])
69
    {
70
        $attr = [];
71
        foreach ($attributes as $name => $value) {
72
            if ($value != '') {
73
                $attr[] = $name.'="'.$value.'"';
74
            }
75
        }
76
77
        $attr = implode(' ', $attr);
78
79
        return '<td '.$attr.'>'.$dataValue.'</td>';
80
    }
81
82
    /**
83
     * @param array          $row
84
     * @param array          $cols
85
     * @param AbstractAction $rowClickAction
86
     * @param array          $rowStyles
87
     *
88
     * @throws \Exception
89
     *
90
     * @return string
91
     */
92
    public function __invoke($row, array $cols, AbstractAction $rowClickAction = null, array $rowStyles = [], $hasMassActions = false)
93
    {
94
        $return = $this->getTr($row);
95
96
        if (true === $hasMassActions) {
97
            $return .= '<td><input type="checkbox" name="massActionSelected[]" value="'.$row['idConcated'].'" /></td>';
98
        }
99
100
        foreach ($cols as $col) {
101
            /* @var $col Column\AbstractColumn */
102
103
            $value = $row[$col->getUniqueId()];
104
105
            $cssStyles = [];
106
            $classes = [];
107
108
            if ($col->isHidden() === true) {
109
                $classes[] = 'hidden';
110
            }
111
112
            switch (get_class($col->getType())) {
113
114
                case Column\Type\Number::class:
115
                    $cssStyles[] = 'text-align: right';
116
                    break;
117
118
                case Column\Type\PhpArray::class:
119
                    $value = '<pre>'.print_r($value, true).'</pre>';
120
                    break;
121
            }
122
123
            $styles = array_merge($rowStyles, $col->getStyles());
124
            foreach ($styles as $style) {
125
                /* @var $style Column\Style\AbstractStyle */
126
                if ($style->isApply($row) === true) {
127
                    switch (get_class($style)) {
128
129
                        case Column\Style\Bold::class:
130
                            $cssStyles[] = 'font-weight: bold';
131
                            break;
132
133
                        case Column\Style\Italic::class:
134
                            $cssStyles[] = 'font-style: italic';
135
                            break;
136
137
                        case Column\Style\Color::class:
138
                            $cssStyles[] = 'color: #'.$style->getRgbHexString();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class ZfcDatagrid\Column\Style\AbstractStyle as the method getRgbHexString() does only exist in the following sub-classes of ZfcDatagrid\Column\Style\AbstractStyle: ZfcDatagrid\Column\Style\AbstractColor, ZfcDatagrid\Column\Style\BackgroundColor, ZfcDatagrid\Column\Style\Color. 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...
139
                            break;
140
141
                        case Column\Style\BackgroundColor::class:
142
                            $cssStyles[] = 'background-color: #'.$style->getRgbHexString();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class ZfcDatagrid\Column\Style\AbstractStyle as the method getRgbHexString() does only exist in the following sub-classes of ZfcDatagrid\Column\Style\AbstractStyle: ZfcDatagrid\Column\Style\AbstractColor, ZfcDatagrid\Column\Style\BackgroundColor, ZfcDatagrid\Column\Style\Color. 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...
143
                            break;
144
145
                        case Column\Style\Align::class:
146
                            $cssStyles[] = 'text-align: '.$style->getAlignment();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class ZfcDatagrid\Column\Style\AbstractStyle as the method getAlignment() does only exist in the following sub-classes of ZfcDatagrid\Column\Style\AbstractStyle: ZfcDatagrid\Column\Style\Align. 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...
147
                            break;
148
149
                        case Column\Style\Strikethrough::class:
150
                            $value = '<s>'.$value.'</s>';
151
                            break;
152
153
                        case Column\Style\CSSClass::class:
154
                            $classes[] = $style->getClass();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class ZfcDatagrid\Column\Style\AbstractStyle as the method getClass() does only exist in the following sub-classes of ZfcDatagrid\Column\Style\AbstractStyle: ZfcDatagrid\Column\Style\CSSClass. 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...
155
                            break;
156
157
                        case Column\Style\Html::class:
158
                            // do NOTHING! just pass the HTML!
159
                            break;
160
161
                        default:
162
                            throw new \InvalidArgumentException('Not defined style: "'.get_class($style).'"');
163
                            break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
164
                    }
165
                }
166
            }
167
168 View Code Duplication
            if ($col instanceof Column\Action) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
169
                /* @var $col Column\Action */
170
                $actions = [];
171
                foreach ($col->getActions() as $action) {
172
                    /* @var $action Column\Action\AbstractAction */
173
                    if ($action->isDisplayed($row) === true) {
174
                        $action->setTitle($this->translate($action->getTitle()));
175
                        $actions[] = $action->toHtml($row);
176
                    }
177
                }
178
179
                $value = implode(' ', $actions);
180
            }
181
182
            // "rowClick" action
183
            if ($col instanceof Column\Select && $rowClickAction instanceof AbstractAction
184
                    && $col->isRowClickEnabled()) {
185
                $value = '<a href="'.$rowClickAction->getLinkReplaced($row).'">'.$value.'</a>';
186
            }
187
188
            $attributes = [
189
                'class' => implode(' ', $classes),
190
                'style' => implode(';', $cssStyles),
191
                'data-columnUniqueId' => $col->getUniqueId(),
192
            ];
193
194
            $return .= $this->getTd($value, $attributes);
195
        }
196
197
        $return .= $this->getTr($row, false);
198
199
        return $return;
200
    }
201
}
202