Completed
Pull Request — master (#1958)
by Basil
01:56
created

Module::luyaBootstrap()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace luya\base;
4
5
use Yii;
6
use yii\base\InvalidConfigException;
7
use luya\console\interfaces\ImportControllerInterface;
8
use luya\helpers\ObjectHelper;
9
use yii\base\Application;
10
11
/**
12
 * LUYA Module base class.
13
 *
14
 * The module class provides url rule defintions and other helper methods.
15
 *
16
 * In order to use a module within the CMS context it must extend from this base module class.
17
 *
18
 * @property array $urlRules Contains all urlRules for this module. You can either provide a full {{luya\web\UrlRule}} object configuration as array like this:
19
 * ```php
20
 * 'urlRules' => [
21
 *     ['pattern' => 'mymodule/detail/<id:\d+>', 'route' => 'mymodule/detail/user'],
22
 * ],
23
 * ```
24
 *
25
 * Or you can provide a key value pairing where key is the pattern and the value is the route:
26
 *
27
 * ```php
28
 * 'urlRules' => [
29
 *     'mymodule/detail/<id:\d+>' => 'mymodule/detail/user',
30
 * ],
31
 * ```
32
 *
33
 * @author Basil Suter <[email protected]>
34
 * @since 1.0.0
35
 */
36
abstract class Module extends \yii\base\Module
37
{
38
    /**
39
     * @var array Contains the apis for each module to provided them in the admin module. They represents
40
     * the name of the api and the value represents the class. Example value:
41
     *
42
     * ```php
43
     * [
44
     *     'api-admin-user' => 'admin\apis\UserController',
45
     *     'api-cms-navcontainer' => 'admin\apis\NavContainerController'
46
     * ]
47
     * ```
48
     */
49
    public $apis = [];
50
    
51
    /**
52
     * @var array An array with additional rules for a given api name. This allows you to extend and customize the {{yii\rest\UrlRule}} for
53
     * a given API. Example:
54
     *
55
     * ```php
56
     * 'apiRules' => [
57
     *     'api-admin-user' => ['extraPattern' => ['GET {id}/login-list' => 'logins']],
58
     *     'api-admin-group' => ['exception' => ['this-action']],
59
     * ],
60
     * ```
61
     *
62
     * You can define all properties from {{yii\rest\UrlRule}}.
63
     *
64
     * @since 1.0.10
65
     */
66
    public $apiRules = [];
67
68
    /**
69
     * @var array An array with Tag class names to inject into the tag parser on luya boot, where key is the identifier and value the create object conifg:
70
     *
71
     * ```php
72
     * [
73
     *     'link' => 'luya\cms\tags\LinkTag',
74
     *     'file' => ['class' => 'luya\admin\tags\FileTag'],
75
     * ]
76
     * ```
77
     *
78
     * As by default the yii2 configurable object you can also pass properties to your tag object in order to configure them.
79
     */
80
    public $tags = [];
81
    
82
    private $_urlRules = [];
83
    
84
    /**
85
     * UrlRules for this module. You can either provide a full {{luya\web\UrlRule}}
86
     * object configuration as array like this:
87
     *
88
     * ```php
89
     * 'urlRules' => [
90
     *     ['pattern' => 'mymodule/detail/<id:\d+>', 'route' => 'mymodule/detail/user'],
91
     * ],
92
     * ```
93
     *
94
     * Or you can provide a key value pairing where key is the pattern and the value is the route:
95
     *
96
     * ```php
97
     * 'urlRules' => [
98
     *     'mymodule/detail/<id:\d+>' => 'mymodule/detail/user',
99
     * ],
100
     * ```
101
     *
102
     * @var array $rules Contains all urlRules for this module. You can either provide a full {{luya\web\UrlRule}}
103
     * object configuration as array
104
     * @since 1.0.1
105
     */
106
    public function setUrlRules(array $rules)
107
    {
108
        $this->_urlRules = $rules;
109
    }
110
111
    /**
112
     * Getter method for urlRules.
113
     *
114
     * > Never use the getter method, use the $urlRules virtual property as it provides backwards compatibility.
115
     *
116
     * @return array
117
     * @since 1.0.1
118
     */
119
    public function getUrlRules()
120
    {
121
        return $this->_urlRules;
122
    }
123
124
    /**
125
     * @var array An array containing all components which should be registered for the current module. If
126
     * the component does not exists an Exception will be thrown.
127
     */
128
    public $requiredComponents = [];
129
130
    /**
131
     * @var bool Defines the location of the layout file whether in the @app namespace or a module:
132
     *
133
     * - true = looking for layout file in `@app/views/<ID>/layouts`.
134
     * - false = looking for layout file in `@module/views/layouts/`.
135
     *
136
     * This variable is only available if your not in a context call. A context call would be if the cms renders the module.
137
     */
138
    public $useAppLayoutPath = true;
139
    
140
    /**
141
     * @var bool Define the location of the view files inside the controller actions
142
     *
143
     * - true = the view path of the @app/views
144
     * - false = the view path of the @modulename/views
145
     *
146
     */
147
    public $useAppViewPath = false;
148
149
    /**
150
     * @var array mapping from action ID to view configurations.
151
     * Each name-value pair specifies the configuration of a specifed oder wildcard action to a single view folder.
152
     * The first match
153
     * For example,
154
     *
155
     * ```php
156
     * [
157
     *   'default/index' => '@app/views/mymodule/default',
158
     *   'login/info' => '@app/views/mymodule/login',
159
     *   'default/*' => '@app/views/mymodule/default',
160
     *   '*' => '@app/views/mymodule',
161
     * ]
162
     * ```
163
     *
164
     * @since 1.0.11
165
     */
166
    public $viewMap = [];
167
168
    /**
169
     * @var string if this/the module is included via another module (parent module), the parent module will write its
170
     * name inside the child modules $context variable. For example the cms includes the news module, the context variable
171
     * of news would have the value "cms".
172
     */
173
    public $context;
174
175
    /**
176
     * @var string The default name of the moduleLayout
177
     */
178
    public $moduleLayout = 'layout';
179
180
    /**
181
     * @inheritdoc
182
     */
183
    public function init()
184
    {
185
        parent::init();
186
        // verify all the components
187
        foreach ($this->requiredComponents as $component) {
188
            if (!Yii::$app->has($component)) {
189
                throw new InvalidConfigException(sprintf('The required component "%s" is not registered in the configuration file', $component));
190
            }
191
        }
192
        
193
        if (Yii::$app->themeManager->hasActiveTheme) {
194
            $this->layout = Yii::$app->themeManager->activeTheme->layout;
195
        }
196
197
        static::onLoad();
198
    }
199
200
    /**
201
     * The LUYA Bootstrap method will be invoken when the application starts. 
202
     * 
203
     * As LUYA modules will be loaded while bootstraping, this method will ALWAYS be invoken when
204
     * the application starts.
205
     * 
206
     * Compared to the {{yii\base\BootstrapInterface}} the module or class must still be configured
207
     * to bootstrap in the configuration section, the {{luyaBootstrap}} will be invoken always.
208
     *
209
     * @param Application $app
210
     * @since 1.0.21
211
     */
212
    public function luyaBootstrap(Application $app)
0 ignored issues
show
Unused Code introduced by
The parameter $app is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
213
    {
214
    }
215
216
    /**
217
     * Override the default implementation of Yii's getLayoutPath(). If the property `$useAppLayoutPath` is true,
218
     * the *@app* namespace views will be looked up for view files.
219
     * Else the layout path of the active theme will be used.
220
     *
221
     * @return string
222
     * @see \yii\base\Module::getLayoutPath()
223
     */
224
    public function getLayoutPath()
225
    {
226
        if (Yii::$app->themeManager->hasActiveTheme && $this->useAppLayoutPath){
227
            $this->setLayoutPath(Yii::$app->themeManager->activeTheme->layoutPath);
228
        } elseif ($this->useAppLayoutPath) {
229
            $this->setLayoutPath('@app/views/'.$this->id.'/layouts');
230
        }
231
232
        return parent::getLayoutPath();
233
    }
234
235
    /**
236
     * Extract the current module from the route and return the new resolved route.
237
     *
238
     * @param string $route Route to resolve, e.g. `admin/default/index`
239
     * @return string The resolved route without the module id `default/index` when input was `admin/default/index`
240
     * and the current module id is `admin`.
241
     */
242
    public function resolveRoute($route)
243
    {
244
        $routeParts = explode('/', $route);
245
        foreach ($routeParts as $k => $v) {
246
            if (($k == 0 && $v == $this->id) || (empty($v))) {
247
                unset($routeParts[$k]);
248
            }
249
        }
250
        if (count($routeParts) == 0) {
251
            return $this->defaultRoute;
252
        }
253
254
        return implode('/', $routeParts);
255
    }
256
257
    /**
258
     * register a component to the application. id => definition. All components will be registered during bootstrap process.
259
     *
260
     * @return array
261
     */
262
    public function registerComponents()
263
    {
264
        return [];
265
    }
266
267
    /**
268
     * Define a last of importer class with an array or run code directily with the import() method.
269
     *
270
     * Can be either an array with classes:
271
     *
272
     * ```php
273
     * public function import(ImportControllerInterface $importer)
274
     * {
275
     *     return [
276
     *         'path\to\class\Import',
277
     *         MyImporterClass::className(),
278
     *     ];
279
     * }
280
     * ```
281
     *
282
     * Or a direct functional call which executes importer things:
283
     *
284
     * ```php
285
     * public function import(ImportControllerInterface $importer)
286
     * {
287
     *     foreach ($importer->getDirectoryFiles('blocks') as $block) {
288
     *         // do something with block file.
289
     *     }
290
     * }
291
     * ```
292
     *
293
     * @param \luya\console\interfaces\ImportControllerInterface $importer The importer controller class which will be invoke to the import method.
294
     * @return boolean|array If an array is returned it must contain object class to created extending from {{luya\console\Command}}.
295
     */
296
    public function import(ImportControllerInterface $importer)
0 ignored issues
show
Unused Code introduced by
The parameter $importer is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
297
    {
298
        return false;
299
    }
300
    
301
    /**
302
     * returns "luya\base" for example.
303
     *
304
     * @return string
305
     */
306
    public function getNamespace()
307
    {
308
        return implode('\\', array_slice(explode('\\', get_class($this)), 0, -1));
309
    }
310
    
311
    /**
312
     * Returns all controller files of this module from the `getControllerPath()` folder, where the key is the reusable
313
     * id of this controller and value the file on the server.
314
     *
315
     * @return array Returns an array where the key is the controller id and value the original file.
316
     */
317
    public function getControllerFiles()
318
    {
319
        return ObjectHelper::getControllers($this);
320
    }
321
    
322
    /**
323
     * Overrides the yii2 default behavior by not throwing an exception if no alias has been defined
324
     * for the controller namespace. Otherwise each module requires an alias for its first namepsace entry
325
     * which results into exception for external modules without an alias.
326
     * exception.
327
     *
328
     * @inheritdoc
329
     */
330
    public function getControllerPath()
331
    {
332
        return Yii::getAlias('@' . str_replace('\\', '/', $this->controllerNamespace), false);
333
    }
334
335
    // STATIC METHODS
336
337
    /**
338
     * Internal used to register the translations from the translation array or set alias paths.
339
     *
340
     * This is a static behavior, so we can call this call without the object context, for example when
341
     * the composer plugin registers blocks but the module is not registered with translations.
342
     *
343
     * @return void
344
     */
345
    public static function onLoad()
346
    {
347
    }
348
    
349
    /**
350
     * Register a Translation to the i18n component.
351
     *
352
     * In order to register Translations you can register them inside the {{luya\base\Module::onLoad()}} method.
353
     *
354
     * ```php
355
     * public static function onLoad()
356
     * {
357
     *     $this->registerTranslation('mymodule*', static::staticBasePath() . '/messages', [
358
     *         'mymodule' => 'mymodule.php',
359
     *         'mymodule/sub' => 'sub.php',
360
     *     ]);
361
     * }
362
     * ```
363
     *
364
     * @param string $prefix The prefix of which the messages are indicated
365
     * @param string $basePath The path to the messages folder where the messages are located.
366
     * @param array $fileMap The files mapping inside the messages folder.
367
     */
368
    public static function registerTranslation($prefix, $basePath, array $fileMap)
369
    {
370
        if (!isset(Yii::$app->i18n->translations[$prefix])) {
371
            Yii::$app->i18n->translations[$prefix] = [
372
                'class' => 'yii\i18n\PhpMessageSource',
373
                'basePath' => $basePath,
374
                'fileMap' => $fileMap,
375
            ];
376
        }
377
    }
378
    
379
    /**
380
     * Get base path from static view port.
381
     *
382
     * @return string
383
     */
384
    public static function staticBasePath()
385
    {
386
        $class = new \ReflectionClass(get_called_class());
387
        
388
        return dirname($class->getFileName());
389
    }
390
391
    /**
392
     * Base translation method which invokes the onLoad function.
393
     *
394
     * This makes it possible to register module translations without adding the module
395
     * to the components list. This is very important for luya extensions.
396
     *
397
     * @param string $category the message category.
398
     * @param string $message the message to be translated.
399
     * @param array $params the parameters that will be used to replace the corresponding placeholders in the message.
400
     * @param string $language the language code (e.g. `en-US`, `en`). If this is null, the current
401
     * [[\yii\base\Application::language|application language]] will be used.
402
     * @return string the translated message.
403
     */
404
    public static function baseT($category, $message, array $params = [], $language = null)
405
    {
406
        static::onLoad();
407
        return Yii::t($category, $message, $params, $language);
408
    }
409
}
410