Theme::isVar()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 0
cts 4
cp 0
cc 2
nc 2
nop 1
crap 6
1
<?php
2
/**
3
 * Pluggable themes for Yii2
4
 *
5
 * @link      https://github.com/hiqdev/yii2-thememanager
6
 * @package   yii2-thememanager
7
 * @license   BSD-3-Clause
8
 * @copyright Copyright (c) 2015-2017, HiQDev (http://hiqdev.com/)
9
 */
10
11
namespace hiqdev\thememanager;
12
13
use ReflectionClass;
14
use Yii;
15
use yii\helpers\ArrayHelper;
16
17
/**
18
 * Theme class.
19
 */
20
class Theme extends \yii\base\Theme implements \hiqdev\yii2\collection\ItemWithNameInterface
21
{
22
    use GetManagerTrait;
23
24
    /**
25
     * @var string theme name
26
     */
27
    public $name;
28
29
    /**
30
     * @var string theme label
31
     */
32
    public $label;
33
34
    /**
35
     * @var array assets to be registered for this theme
36
     */
37
    public $assets = [];
38
39
    private $_view;
40
41
    /**
42
     * Returns the view object that can be used to render views or view files.
43
     * The [[render()]] and [[renderFile()]] methods will use
44
     * this view object to implement the actual view rendering.
45
     * If not set, it will default to the "view" application component.
46
     *
47
     * @return \yii\web\View the view object that can be used to render views or view files
48
     */
49
    public function getView()
50
    {
51
        if ($this->_view === null) {
52
            $this->_view = $this->getManager()->getView();
53
        }
54
55
        return $this->_view;
56
    }
57
58
    /**
59
     * Sets the view object to be used.
60
     *
61
     * @param View $view the view object that can be used to render views or view files
62
     */
63
    public function setView($view)
64
    {
65
        $this->_view = $view;
66
    }
67
68
    public $pathMap = [];
69
70
    /**
71
     * Getter for pathMap.
72
     */
73
    public function init()
74
    {
75
        parent::init();
76
        if (!is_array($this->pathMap)) {
77
            $this->pathMap = [];
78
        }
79
80
        $this->pathMap = $this->compilePathMap(ArrayHelper::merge([
81
            '$themedViewPaths' => $this->buildThemedViewPaths(),
82
            '$themedWidgetPaths' => '$themedViewPaths/widgets',
83
            Yii::$app->viewPath => '$themedViewPaths',
84
            __DIR__ . '/widgets/views' => '$themedWidgetPaths',
85
        ], $this->getManager()->pathMap, $this->pathMap));
86
    }
87
88
    public function compilePathMap($map)
89
    {
90
        $map = $this->substituteVars($map);
91
92
        $themeSubpath = '/src/views/themes/' . $this->name;
93
94
        $res = [];
95
        foreach ($map as $from => &$tos) {
96
            $tos = array_unique(array_reverse(array_values($tos)));
97
            $new = [];
98
            foreach ($tos as $to) {
99
                $to = Yii::getAlias($to);
100
                $alt = preg_replace('#(.*)/src/views(.*)$#', '${1}' . $themeSubpath . '${2}', $to);
101
                if ($alt) {
102
                    $new[] = $alt;
103
                }
104
                $new[] = $to;
105
            }
106
            //$res[Yii::getAlias($from)] = $new;
107
            $res[Yii::getAlias($from)] = array_values(array_filter($new, 'file_exists'));
108
        }
109
110
        return array_filter($res);
111
    }
112
113
    public function substituteVars($vars)
114
    {
115
        $proceed = true;
116
        while ($proceed) {
117
            $proceed = false;
118
            foreach ($vars as $key => $exp) {
119
                if ($this->isVar($exp)) {
120
                    $value = $this->calcExp($exp, $vars);
121
                    if (isset($value)) {
122
                        $vars[$key] = $value;
123
                        $proceed = true;
124
                    }
125
                }
126
            }
127
        }
128
129
        foreach (array_keys($vars) as $key) {
130
            if ($this->isVar($key)) {
131
                unset($vars[$key]);
132
            }
133
        }
134
135
        return $vars;
136
    }
137
138
    public function isVar($name)
139
    {
140
        return is_string($name) && (strncmp($name, '$', 1) === 0);
141
    }
142
143
    public function calcExp($exp, $vars)
144
    {
145
        $pos = strpos($exp, '/');
146
        if ($pos === false) {
147
            return $vars[$exp];
148
        }
149
        list($name, $suffix) = explode('/', $exp, 2);
150
151
        return array_map(function ($a) use ($suffix) {
152
            return "$a/$suffix";
153
        }, $vars[$name]);
154
    }
155
156
    public function buildThemedViewPaths()
157
    {
158
        return array_map(function ($a) {
159
            return "$a/views";
160
        }, $this->findParentPaths());
161
    }
162
163
    public function findParentPaths()
164
    {
165
        $dirs = [];
166
        $ref = $this->getReflection();
167
        for ($depth = 0; $depth < 10; ++$depth) {
168
            $dirs[] = dirname($ref->getFileName());
169
            $ref = $ref->getParentClass();
170
            if (__CLASS__ === $ref->name) {
171
                break;
172
            }
173
        }
174
175
        return $dirs;
176
    }
177
178
    protected $_reflection;
179
180
    public function getReflection()
181
    {
182
        if (!$this->_reflection) {
183
            $this->_reflection = new ReflectionClass($this);
184
        }
185
186
        return $this->_reflection;
187
    }
188
189
    private $_settings;
190
191
    /**
192
     * @param string $settings theme settings model class name or config
193
     */
194
    public function setSettings($settings)
195
    {
196
        $this->_settings = $settings;
197
    }
198
199
    public function getSettings()
200
    {
201
        if (!is_object($this->_settings)) {
202
            if (!$this->_settings) {
203
                $this->_settings = static::findSettingsClass(get_called_class());
204
            }
205
            $data = $this->getManager()->getThemeSettings();
206
            $this->_settings = Yii::createObject($this->_settings);
207
            $this->_settings->load($data);
208
        }
209
210
        return $this->_settings;
211
    }
212
213
    public static function calcSettingsClass($class)
214
    {
215
        return substr($class, 0, strrpos($class, '\\')) . '\\models\\Settings';
216
    }
217
218
    public static function findSettingsClass($class)
219
    {
220
        $res = static::calcSettingsClass($class);
221
222
        return class_exists($res) ? $res : static::findSettingsClass(get_parent_class($class));
223
    }
224
225
    public function getDetailedTheme()
226
    {
227
        $localDetailedTheme = str_replace('\Theme', '\DetailedTheme',  get_called_class());
228
        $class = class_exists($localDetailedTheme) ? $localDetailedTheme : DetailedTheme::class;
229
230
        return new $class($this);
231
    }
232
}
233