Completed
Push — master ( f497ed...f2713b )
by Andrii
02:34
created

Theme::buildPaths()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 8
ccs 0
cts 7
cp 0
rs 9.4285
cc 2
eloc 4
nc 2
nop 2
crap 6
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
            array_unshift($dirs, $dir);
135
        }
136
137
        return $dirs;
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...
138
    }
139
140
    public function buildPaths($dirs, $name)
141
    {
142
        foreach ($dirs as $dir) {
143
            $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...
144
        }
145
146
        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...
147
    }
148
149
    protected $_baseUrl;
150
151
    /**
152
     * @return string the base URL (without ending slash) for this theme.
153
     *                All resources of this theme are considered to be under this base URL.
154
     */
155
    public function getBaseUrl()
156
    {
157
        if (!$this->_baseUrl) {
158
            $this->_baseUrl = '@web/themes/' . $this->name;
159
        }
160
161
        return $this->_baseUrl;
162
    }
163
164
    protected $_reflection;
165
166
    public function getReflection()
167
    {
168
        if (!$this->_reflection) {
169
            $this->_reflection = new ReflectionClass($this);
170
        }
171
172
        return $this->_reflection;
173
    }
174
175
    private $_settings;
176
177
    /**
178
     * @param $settings string theme settings model class name
179
     */
180
    public function setSettings($settings)
181
    {
182
        $this->_settings = $settings;
183
    }
184
185
    public function getSettings()
186
    {
187
        if (!is_object($this->_settings)) {
188
            if (!$this->_settings) {
189
                $this->_settings = static::findSettingsClass(get_called_class());
190
            }
191
            $this->_settings = Yii::createObject($this->_settings);
192
            $this->_settings->load();
193
        }
194
195
        return $this->_settings;
196
    }
197
198
    public static function calcSettingsClass($class)
199
    {
200
        return substr($class, 0, strrpos($class, '\\')) . '\\models\\Settings';
201
    }
202
203
    public static function findSettingsClass($class)
204
    {
205
        $res = static::calcSettingsClass($class);
206
207
        return class_exists($res) ? $res : static::findSettingsClass(get_parent_class($class));
208
    }
209
}
210