Completed
Push — master ( add877...db5f0d )
by Andrii
02:57
created

ThemeManager::callStatic()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 23
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 23
ccs 0
cts 21
cp 0
rs 8.5906
cc 5
eloc 16
nc 8
nop 2
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 hiqdev\thememanager\models\Settings;
15
use hiqdev\thememanager\storage\SettingsStorageInterface;
16
use Yii;
17
use yii\base\InvalidConfigException;
18
use yii\base\Widget;
19
use yii\web\AssetBundle;
20
21
/**
22
 * Theme Manager.
23
 *
24
 * Usage, in config:
25
 *
26
 * ```php
27
 * 'components' => [
28
 *     'themeManager' => [
29
 *         'class' => \hiqdev\thememanager\ThemeManager::class,
30
 *     ],
31
 * ]
32
 * ```
33
 */
34
class ThemeManager extends \hiqdev\yii2\collection\Manager implements \yii\base\BootstrapInterface
35
{
36
    /**
37
     * @var array basic pathMap for all themes, will be merged with theme own pathMap
38
     */
39
    public $pathMap = [];
40
41
    /**
42
     * {@inheritdoc}
43
     */
44
    protected $_itemClass = Theme::class;
45
46
    /**
47
     * @var string default theme name
48
     */
49
    protected $_defaultTheme;
50
51
    /**
52
     * Sets the default theme name.
53
     *
54
     * @param string $theme default theme name
55
     */
56
    public function setDefaultTheme($theme)
57
    {
58
        $this->_defaultTheme = $theme;
59
    }
60
61
    /**
62
     * Returns the default theme. Returns the first of available themes by default.
63
     *
64
     * @return string default theme name
65
     */
66
    public function getDefaultTheme()
67
    {
68
        if (!$this->_defaultTheme) {
69
            $keys = $this->keys(); /// shame to PHP it can't be done in single line :(
70
            $this->_defaultTheme = reset($keys);
71
        }
72
73
        return $this->_defaultTheme;
74
    }
75
76
    protected $_view;
77
78
    /**
79
     * @return \yii\web\View
80
     * @see setView
81
     */
82
    public function getView()
83
    {
84
        if ($this->_view === null) {
85
            $this->_view = Yii::$app->getView();
86
        }
87
88
        return $this->_view;
89
    }
90
91
    /**
92
     * You can change the View for theme manager.
93
     * @param \yii\web\View $view the view object that will be used to render views or view files
94
     */
95
    public function setView($view)
96
    {
97
        $this->_view = $view;
98
    }
99
100
    /**
101
     * @var Theme current theme object
102
     */
103
    protected $_theme;
104
105
    /**
106
     * Changes theme.
107
     * @param string theme name
108
     * @throws InvalidConfigException
109
     */
110
    public function setTheme($name)
111
    {
112
        if (!$name) {
113
            throw new InvalidConfigException('no theme to set');
114
        }
115
        $this->_theme = $name;
116
    }
117
118
    public function getTheme()
119
    {
120
        if (is_string($this->_theme)) {
121
            if (!$this->has($this->_theme)) {
122
                throw new InvalidConfigException('unknown theme: ' . $this->_theme);
123
            }
124
            $this->_theme = $this->getItem($this->_theme);
125
            $this->getView()->theme = $this->_theme;
126
        }
127
128
        return $this->_theme;
129
    }
130
131
    public function getSettings()
132
    {
133
        return $this->getTheme()->getSettings();
134
    }
135
136
    /**
137
     * @return bool
138
     */
139
    public static function isHomePage()
140
    {
141
        $controller = Yii::$app->controller;
142
        $default_controller = Yii::$app->defaultRoute;
143
        return ($controller->id === $default_controller) && ($controller->action->id === $controller->defaultAction);
144
    }
145
146
    /**
147
     * @var AssetBundle[] assets to be registered at bootstrap
148
     */
149
    public $assets = [];
150
151
    /**
152
     * Register all the assets.
153
     */
154
    public function registerAssets()
155
    {
156
        foreach (array_merge($this->assets, $this->getTheme()->assets) as $asset) {
157
            /** @var AssetBundle $asset */
158
            $asset::register($this->getView());
159
        }
160
    }
161
162
    /**
163
     * @var bool is already bootstrapped
164
     */
165
    protected $_isBootstrapped = false;
166
167
    /**
168
     * {@inheritdoc}
169
     */
170
    public function bootstrap($app)
171
    {
172
        if ($this->_isBootstrapped) {
173
            return;
174
        }
175
        $this->_isBootstrapped = true;
176
177
        Yii::trace('Bootstrap themes', get_called_class() . '::bootstrap');
178
179
        $data = $this->getSettingsStorage()->get();
180
        $model = new Settings();
181
        $model->load($data);
182
        $theme = $this->hasItem($model->theme) ? $model->theme : null;
183
        $theme = $theme ?: $this->getDefaultTheme();
184
        $this->setTheme($theme);
185
        $this->getTheme();
186
    }
187
188
189
    /**
190
     * Draws widget.
191
     * @param mixed $config
192
     * @return string the rendering result of the widget.
193
     */
194
    public function widget($config)
195
    {
196
        return static::callStatic('widget', $config);
197
    }
198
199
    /**
200
     * Calls static method of class from config.
201
     * Uses Yii container to get class definition.
202
     * @param string $method
203
     * @param mixed $config
204
     * @throws InvalidConfigException
205
     * @return mixed
206
     */
207
    public static function callStatic($method, $config)
208
    {
209
        if (is_string($config)) {
210
            $config = ['class' => $config];
211
        }
212
        if (empty($config['class'])) {
213
            throw new InvalidConfigException('no class given');
214
        }
215
        $class = $config['class'];
216
        $container = Yii::$container;
217
        if ($container->has($class)) {
218
            $definition = $container->getDefinitions()[$class];
219
            if (is_array($definition)) {
220
                $config = array_merge($definition, $config);
221
                $class = $definition['class'];
222
            } else {
223
                $class = $definition;
224
            }
225
        }
226
        unset($config['class']);
227
228
        return call_user_func([$class, $method], $config);
229
    }
230
231
    /**
232
     * Checks if widget with given name is defined.
233
     * @param mixed $name name or class
234
     * @return boolean
235
     */
236
    public function hasWidget($name)
237
    {
238
        return Yii::$container->has($name) || class_exists($name);
239
    }
240
241
    /**
242
     * @return SettingsStorageInterface
243
     */
244
    public function getSettingsStorage()
245
    {
246
        return Yii::$app->get('themeSettingsStorage');
247
    }
248
249
    /**
250
     * @return array
251
     */
252
    public function getThemeSettings()
253
    {
254
        return $this->getSettingsStorage()->get();
255
    }
256
}
257