Completed
Push — master ( 47b0ab...ae4425 )
by Klochok
02:08
created

Theme::getDetailedTheme()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 8

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 11
ccs 0
cts 10
cp 0
rs 9.4285
cc 2
eloc 8
nc 2
nop 0
crap 6
1
<?php
2
/**
3
 * Theme Manager 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
        $res = [];
93
        foreach ($map as $from => &$tos) {
94
            $tos = array_reverse(array_unique(array_values($tos)));
95
            foreach ($tos as &$to) {
96
                $to = Yii::getAlias($to);
97
            }
98
            $res[Yii::getAlias($from)] = $tos;
99
        }
100
101
        return $res;
102
    }
103
104
    public function substituteVars($vars)
105
    {
106
        $proceed = true;
107
        while ($proceed) {
108
            $proceed = false;
109
            foreach ($vars as $key => $exp) {
110
                if ($this->isVar($exp)) {
111
                    $value = $this->calcExp($exp, $vars);
112
                    if (isset($value)) {
113
                        $vars[$key] = $value;
114
                        $proceed = true;
115
                    }
116
                }
117
            }
118
        }
119
120
        foreach (array_keys($vars) as $key) {
121
            if ($this->isVar($key)) {
122
                unset($vars[$key]);
123
            }
124
        }
125
126
        return $vars;
127
    }
128
129
    public function isVar($name)
130
    {
131
        return is_string($name) && (strncmp($name, '$', 1) === 0);
132
    }
133
134
    public function calcExp($exp, $vars)
135
    {
136
        $pos = strpos($exp, '/');
137
        if ($pos === false) {
138
            return $vars[$exp];
139
        }
140
        list($name, $suffix) = explode('/', $exp, 2);
141
142
        return array_map(function ($a) use ($suffix) {
143
            return "$a/$suffix";
144
        }, $vars[$name]);
145
    }
146
147
    public function buildThemedViewPaths()
148
    {
149
        return array_map(function ($a) {
150
            return "$a/views";
151
        }, $this->findParentPaths());
152
    }
153
154
    public function findParentPaths()
155
    {
156
        $dirs = [];
157
        $ref = $this->getReflection();
158
        for ($depth = 0; $depth < 10; ++$depth) {
159
            $dirs[] = dirname($ref->getFileName());
160
            $ref = $ref->getParentClass();
161
            if (__CLASS__ === $ref->name) {
162
                break;
163
            }
164
        }
165
166
        return $dirs;
167
    }
168
169
    protected $_reflection;
170
171
    public function getReflection()
172
    {
173
        if (!$this->_reflection) {
174
            $this->_reflection = new ReflectionClass($this);
175
        }
176
177
        return $this->_reflection;
178
    }
179
180
    private $_settings;
181
182
    /**
183
     * @param string $settings theme settings model class name or config
184
     */
185
    public function setSettings($settings)
186
    {
187
        $this->_settings = $settings;
188
    }
189
190
    public function getSettings()
191
    {
192
        if (!is_object($this->_settings)) {
193
            if (!$this->_settings) {
194
                $this->_settings = static::findSettingsClass(get_called_class());
195
            }
196
            $data = $this->getManager()->getThemeSettings();
197
            $this->_settings = Yii::createObject($this->_settings);
198
            $this->_settings->load($data);
199
        }
200
201
        return $this->_settings;
202
    }
203
204
    public static function calcSettingsClass($class)
205
    {
206
        return substr($class, 0, strrpos($class, '\\')) . '\\models\\Settings';
207
    }
208
209
    public static function findSettingsClass($class)
210
    {
211
        $res = static::calcSettingsClass($class);
212
213
        return class_exists($res) ? $res : static::findSettingsClass(get_parent_class($class));
214
    }
215
216
    public function getDetailedTheme()
217
    {
218
        $parts = explode('\\', get_called_class());
219
        $lastPart = 'Detailed' . end($parts);
220
        array_pop($parts);
221
        array_push($parts, $lastPart);
222
        $class = implode('\\', $parts);
223
        $class = class_exists($class) ? $class : DetailedTheme::class;
224
225
        return new $class($this);
226
    }
227
}
228