Completed
Push — master ( b4d6a5...352f6d )
by Basil
02:42
created

Module::getControllerFiles()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
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
        static::onLoad();
194
    }
195
196
    /**
197
     * The LUYA Bootstrap method will be invoken when the application starts.
198
     *
199
     * As LUYA modules will be loaded while bootstraping, this method will ALWAYS be invoken when
200
     * the application starts.
201
     *
202
     * Compared to the {{yii\base\BootstrapInterface}} the module or class must still be configured
203
     * to bootstrap in the configuration section, the {{luyaBootstrap}} will be invoken always.
204
     *
205
     * @param Application $app
206
     * @since 1.0.21
207
     */
208
    public function luyaBootstrap(Application $app)
209
    {
210
    }
211
212
    /**
213
     * Override the default implementation of Yii's getLayoutPath(). If the property `$useAppLayoutPath` is true,
214
     * the *@app* namespace views will be looked up for view files.
215
     * Else the layout path of the active theme will be used.
216
     *
217
     * @return string
218
     * @see \yii\base\Module::getLayoutPath()
219
     */
220
    public function getLayoutPath()
221
    {
222
        if (Yii::$app->themeManager->hasActiveTheme && $this->useAppLayoutPath) {
223
            $this->setLayoutPath(Yii::$app->themeManager->activeTheme->layoutPath);
224
        } elseif ($this->useAppLayoutPath) {
225
            $this->setLayoutPath('@app/views/'.$this->id.'/layouts');
226
        }
227
228
        return parent::getLayoutPath();
229
    }
230
231
    /**
232
     * Extract the current module from the route and return the new resolved route.
233
     *
234
     * @param string $route Route to resolve, e.g. `admin/default/index`
235
     * @return string The resolved route without the module id `default/index` when input was `admin/default/index`
236
     * and the current module id is `admin`.
237
     */
238
    public function resolveRoute($route)
239
    {
240
        $routeParts = explode('/', $route);
241
        foreach ($routeParts as $k => $v) {
242
            if (($k == 0 && $v == $this->id) || (empty($v))) {
243
                unset($routeParts[$k]);
244
            }
245
        }
246
        if (count($routeParts) == 0) {
247
            return $this->defaultRoute;
248
        }
249
250
        return implode('/', $routeParts);
251
    }
252
253
    /**
254
     * register a component to the application. id => definition. All components will be registered during bootstrap process.
255
     *
256
     * @return array
257
     */
258
    public function registerComponents()
259
    {
260
        return [];
261
    }
262
263
    /**
264
     * Define a last of importer class with an array or run code directily with the import() method.
265
     *
266
     * Can be either an array with classes:
267
     *
268
     * ```php
269
     * public function import(ImportControllerInterface $importer)
270
     * {
271
     *     return [
272
     *         'path\to\class\Import',
273
     *         MyImporterClass::className(),
274
     *     ];
275
     * }
276
     * ```
277
     *
278
     * Or a direct functional call which executes importer things:
279
     *
280
     * ```php
281
     * public function import(ImportControllerInterface $importer)
282
     * {
283
     *     foreach ($importer->getDirectoryFiles('blocks') as $block) {
284
     *         // do something with block file.
285
     *     }
286
     * }
287
     * ```
288
     *
289
     * @param \luya\console\interfaces\ImportControllerInterface $importer The importer controller class which will be invoke to the import method.
290
     * @return boolean|array If an array is returned it must contain object class to created extending from {{luya\console\Command}}.
291
     */
292
    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...
293
    {
294
        return false;
295
    }
296
    
297
    /**
298
     * returns "luya\base" for example.
299
     *
300
     * @return string
301
     */
302
    public function getNamespace()
303
    {
304
        return implode('\\', array_slice(explode('\\', get_class($this)), 0, -1));
305
    }
306
    
307
    /**
308
     * Returns all controller files of this module from the `getControllerPath()` folder, where the key is the reusable
309
     * id of this controller and value the file on the server.
310
     *
311
     * @return array Returns an array where the key is the controller id and value the original file.
312
     */
313
    public function getControllerFiles()
314
    {
315
        return ObjectHelper::getControllers($this);
316
    }
317
    
318
    /**
319
     * Overrides the yii2 default behavior by not throwing an exception if no alias has been defined
320
     * for the controller namespace. Otherwise each module requires an alias for its first namepsace entry
321
     * which results into exception for external modules without an alias.
322
     * exception.
323
     *
324
     * @inheritdoc
325
     */
326
    public function getControllerPath()
327
    {
328
        return Yii::getAlias('@' . str_replace('\\', '/', $this->controllerNamespace), false);
329
    }
330
331
    // STATIC METHODS
332
333
    /**
334
     * Internal used to register the translations from the translation array or set alias paths.
335
     *
336
     * This is a static behavior, so we can call this call without the object context, for example when
337
     * the composer plugin registers blocks but the module is not registered with translations.
338
     *
339
     * @return void
340
     */
341
    public static function onLoad()
342
    {
343
    }
344
    
345
    /**
346
     * Register a Translation to the i18n component.
347
     *
348
     * In order to register Translations you can register them inside the {{luya\base\Module::onLoad()}} method.
349
     *
350
     * ```php
351
     * public static function onLoad()
352
     * {
353
     *     $this->registerTranslation('mymodule*', static::staticBasePath() . '/messages', [
354
     *         'mymodule' => 'mymodule.php',
355
     *         'mymodule/sub' => 'sub.php',
356
     *     ]);
357
     * }
358
     * ```
359
     *
360
     * @param string $prefix The prefix of which the messages are indicated
361
     * @param string $basePath The path to the messages folder where the messages are located.
362
     * @param array $fileMap The files mapping inside the messages folder.
363
     */
364
    public static function registerTranslation($prefix, $basePath, array $fileMap)
365
    {
366
        if (!isset(Yii::$app->i18n->translations[$prefix])) {
367
            Yii::$app->i18n->translations[$prefix] = [
368
                'class' => 'yii\i18n\PhpMessageSource',
369
                'basePath' => $basePath,
370
                'fileMap' => $fileMap,
371
            ];
372
        }
373
    }
374
    
375
    /**
376
     * Get base path from static view port.
377
     *
378
     * @return string
379
     */
380
    public static function staticBasePath()
381
    {
382
        $class = new \ReflectionClass(get_called_class());
383
        
384
        return dirname($class->getFileName());
385
    }
386
387
    /**
388
     * Base translation method which invokes the onLoad function.
389
     *
390
     * This makes it possible to register module translations without adding the module
391
     * to the components list. This is very important for luya extensions.
392
     *
393
     * @param string $category the message category.
394
     * @param string $message the message to be translated.
395
     * @param array $params the parameters that will be used to replace the corresponding placeholders in the message.
396
     * @param string $language the language code (e.g. `en-US`, `en`). If this is null, the current
397
     * [[\yii\base\Application::language|application language]] will be used.
398
     * @return string the translated message.
399
     */
400
    public static function baseT($category, $message, array $params = [], $language = null)
401
    {
402
        static::onLoad();
403
        return Yii::t($category, $message, $params, $language);
404
    }
405
}
406