Completed
Push — master ( d2f459...473009 )
by Klochok
16:19 queued 11:12
created

Theme::calcPathDirs()   B

Complexity

Conditions 5
Paths 9

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 4
Bugs 1 Features 0
Metric Value
c 4
b 1
f 0
dl 0
loc 20
ccs 0
cts 18
cp 0
rs 8.8571
cc 5
eloc 12
nc 9
nop 0
crap 30
1
<?php
2
3
/*
4
 * Theme Manager for Yii2
5
 *
6
 * @link      https://github.com/hiqdev/yii2-thememanager
7
 * @package   yii2-thememanager
8
 * @license   BSD-3-Clause
9
 * @copyright Copyright (c) 2015-2016, HiQDev (http://hiqdev.com/)
10
 */
11
12
namespace hiqdev\thememanager;
13
14
use ReflectionClass;
15
use Yii;
16
17
/**
18
 * Theme class.
19
 */
20
class Theme extends \yii\base\Theme implements \hiqdev\yii2\collection\ItemWithNameInterface
21
{
22
    /**
23
     * @var string theme name
24
     */
25
    public $name;
26
27
    /**
28
     * @var string theme label
29
     */
30
    public $label;
31
32
    /**
33
     * @var array assets to be registered for this theme
34
     */
35
    public $assets = [];
36
37
    private $_manager;
38
39
    /**
40
     * Returns the manager object that can be used to render views or view files.
41
     * If not set, it will default to the "themeManager" application component.
42
     *
43
     * @return Manager the manager object
44
     */
45
    public function getManager()
46
    {
47
        if ($this->_manager === null) {
48
            $this->_manager = Yii::$app->get('themeManager');
49
        }
50
51
        return $this->_manager;
52
    }
53
54
    /**
55
     * Sets the manager object to be used by this theme.
56
     *
57
     * @param Manager $manager the manager object.
58
     */
59
    public function setManager($manager)
60
    {
61
        $this->_manager = $manager;
62
    }
63
64
    private $_view;
65
66
    /**
67
     * Returns the view object that can be used to render views or view files.
68
     * The [[render()]] and [[renderFile()]] methods will use
69
     * this view object to implement the actual view rendering.
70
     * If not set, it will default to the "view" application component.
71
     *
72
     * @return \yii\web\View the view object that can be used to render views or view files.
73
     */
74
    public function getView()
75
    {
76
        if ($this->_view === null) {
77
            $this->_view = $this->getManager()->getView();
78
        }
79
80
        return $this->_view;
81
    }
82
83
    /**
84
     * Sets the view object to be used.
85
     *
86
     * @param View $view the view object that can be used to render views or view files.
87
     */
88
    public function setView($view)
89
    {
90
        $this->_view = $view;
91
    }
92
93
    /**
94
     * Getter for pathMap.
95
     */
96
    public function init()
97
    {
98
        parent::init();
99
        if (!$this->pathMap) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->pathMap of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
100
            $dirs          = $this->calcPathDirs();
101
            $this->pathMap = [
102
                $this->getViewPath()   => $this->buildPaths($dirs, 'views'),
103
                $this->getWidgetPath() => $this->buildPaths($dirs, 'widgets'),
104
            ];
105
        }
106
    }
107
108
    protected $_viewPath;
109
    protected $_widgetPath;
110
111
    public function getViewPath()
112
    {
113
        return $this->_viewPath ?: Yii::$app->viewPath;
114
    }
115
116
    public function getWidgetPath()
117
    {
118
        return $this->_widgetPath ?: preg_replace('/(.*)views/', '$1widgets', $this->getViewPath());
119
    }
120
121
    public function calcPathDirs()
122
    {
123
        $ref = $this->getReflection();
124
        for ($depth = 0;$depth < 10;++$depth) {
125
            $dirs[] = dirname($ref->getFilename());
0 ignored issues
show
Coding Style Comprehensibility introduced by
$dirs was never initialized. Although not strictly required by PHP, it is generally a good practice to add $dirs = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
126
            $ref    = $ref->getParentClass();
127
            if (__CLASS__ === $ref->name) {
128
                break;
129
            }
130
        }
131
132
        foreach ($this->manager->pathDirs as $dir) {
0 ignored issues
show
Bug introduced by
The property manager does not seem to exist. Did you mean _manager?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
133
            $dir = Yii::getAlias($dir);
134
            if (!in_array($dir, $dirs, true)) {
0 ignored issues
show
Bug introduced by
The variable $dirs does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
135
                array_unshift($dirs, $dir);
136
            }
137
        }
138
139
        return $dirs;
140
    }
141
142
    public function buildPaths($dirs, $name)
143
    {
144
        foreach ($dirs as $dir) {
145
            $res[] = $dir . DIRECTORY_SEPARATOR . $name;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$res was never initialized. Although not strictly required by PHP, it is generally a good practice to add $res = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
146
        }
147
148
        return $res;
0 ignored issues
show
Bug introduced by
The variable $res does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
149
    }
150
151
    protected $_baseUrl;
152
153
    /**
154
     * @return string the base URL (without ending slash) for this theme.
155
     *                All resources of this theme are considered to be under this base URL.
156
     */
157
    public function getBaseUrl()
158
    {
159
        if (!$this->_baseUrl) {
160
            $this->_baseUrl = '@web/themes/' . $this->name;
161
        }
162
163
        return $this->_baseUrl;
164
    }
165
166
    protected $_reflection;
167
168
    public function getReflection()
169
    {
170
        if (!$this->_reflection) {
171
            $this->_reflection = new ReflectionClass($this);
172
        }
173
174
        return $this->_reflection;
175
    }
176
177
    private $_settings;
178
179
    /**
180
     * @param $settings string theme settings model class name
181
     */
182
    public function setSettings($settings)
183
    {
184
        $this->_settings = $settings;
185
    }
186
187
    public function getSettings()
188
    {
189
        if (!is_object($this->_settings)) {
190
            if (!$this->_settings) {
191
                $this->_settings = static::findSettingsClass(get_called_class());
192
            }
193
            $this->_settings = Yii::createObject($this->_settings);
194
            $this->_settings->load();
195
        }
196
197
        return $this->_settings;
198
    }
199
200
    public static function calcSettingsClass($class)
201
    {
202
        return substr($class, 0, strrpos($class, '\\')) . '\\models\\Settings';
203
    }
204
205
    public static function findSettingsClass($class)
206
    {
207
        $res = static::calcSettingsClass($class);
208
209
        return class_exists($res) ? $res : static::findSettingsClass(get_parent_class($class));
210
    }
211
}
212