Completed
Push — master ( 89011d...ce8f51 )
by Klochok
03:44
created

IndexAction::getDataProvider()   C

Complexity

Conditions 11
Paths 81

Size

Total Lines 46
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 132

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 46
ccs 0
cts 33
cp 0
rs 5.2653
cc 11
eloc 24
nc 81
nop 0
crap 132

How to fix   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
 * HiPanel core package.
4
 *
5
 * @link      https://hipanel.com/
6
 * @package   hipanel-core
7
 * @license   BSD-3-Clause
8
 * @copyright Copyright (c) 2014-2017, HiQDev (http://hiqdev.com/)
9
 */
10
11
namespace hipanel\actions;
12
13
use hipanel\base\FilterStorage;
14
use hipanel\models\IndexPageUiOptions;
15
use Yii;
16
use yii\helpers\ArrayHelper;
17
use yii\helpers\Inflector;
18
19
/**
20
 * Class IndexAction.
21
 */
22
class IndexAction extends SearchAction
23
{
24
    /**
25
     * @var string view to render
26
     */
27
    protected $_view;
28
29
    public function setView($value)
30
    {
31
        $this->_view = $value;
32
    }
33
34
    public function getView()
35
    {
36
        if ($this->_view === null) {
37
            $this->_view = lcfirst(Inflector::id2camel($this->id));
38
        }
39
40
        return $this->_view;
41
    }
42
43
    /**
44
     * @var array The map of filters for the [[hipanel\base\FilterStorage|FilterStorage]]
45
     */
46
    public $filterStorageMap = [];
47
48
    protected function getDefaultRules()
49
    {
50
        return array_merge([
0 ignored issues
show
Bug Best Practice introduced by
The return type of return array_merge(array...nt::getDefaultRules()); (array<string,array>) is incompatible with the return type of the parent method hipanel\actions\SearchAction::getDefaultRules of type array<string,array<strin...rray<string,callable>>>.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
51
            'html | pjax' => [
52
                'save' => false,
53
                'flash' => false,
54
                'success' => [
55
                    'class' => RenderAction::class,
56
                    'view' => $this->getView(),
57
                    'data' => $this->data,
58
                    'params' => function () {
59
                        return [
60
                            'model' => $this->getSearchModel(),
61
                            'dataProvider' => $this->getDataProvider(),
62
                            'uiModel' => $this->getUiModel(),
63
                        ];
64
                    },
65
                ],
66
            ],
67
        ], parent::getDefaultRules());
68
    }
69
70
    public function getUiModel()
71
    {
72
        return $this->controller->indexPageUiOptionsModel;
73
    }
74
75
    /**
76
     * {@inheritdoc}
77
     */
78
    public function getDataProvider()
79
    {
80
        if ($this->dataProvider === null) {
81
            $request = Yii::$app->request;
82
83
            $formName = $this->getSearchModel()->formName();
0 ignored issues
show
Bug introduced by
It seems like formName() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
84
            $requestFilters = $request->get($formName) ?: $request->get() ?: $request->post();
85
86
            // Don't save filters for ajax requests, because
87
            // the request is probably triggered with select2 or smt similar
88
            if ($request->getIsPjax() || !$request->getIsAjax()) {
89
                $filterStorage = new FilterStorage(['map' => $this->filterStorageMap]);
90
91
                if ($request->getIsPost() && $request->post('clear-filters')) {
92
                    $filterStorage->clearFilters();
93
                }
94
95
                $filterStorage->set($requestFilters);
96
97
                // Apply filters from storage only when request does not contain any data
98
                if (empty($requestFilters)) {
99
                    $requestFilters = $filterStorage->get();
100
                }
101
            }
102
103
            $search = ArrayHelper::merge($this->findOptions, $requestFilters);
104
105
            $this->returnOptions[$this->controller->modelClassName()] = ArrayHelper::merge(
106
                ArrayHelper::remove($search, 'return', []),
107
                ArrayHelper::remove($search, 'rename', [])
108
            );
109
110
            if ($formName !== '') {
111
                $search = [$formName => $search];
112
            }
113
            $this->dataProvider = $this->getSearchModel()->search($search, $this->dataProviderOptions);
114
115
            if ($this->getUiModel()->sort) {
116
                $attribute = $this->getUiModel()->sortAttribute;
0 ignored issues
show
Documentation introduced by
The property sortAttribute does not exist on object<hipanel\models\IndexPageUiOptions>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
117
                $direction = $this->getUiModel()->sortDirection;
0 ignored issues
show
Documentation introduced by
The property sortDirection does not exist on object<hipanel\models\IndexPageUiOptions>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
118
                $this->dataProvider->setSort(['defaultOrder' => [$attribute => $direction]]);
119
            }
120
        }
121
122
        return $this->dataProvider;
123
    }
124
}
125