Completed
Push — master ( 352f6d...fa6ea1 )
by Basil
04:37 queued 02:26
created

ApplicationTrait::getAdminModulesMenus()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
cc 3
nc 3
nop 0
1
<?php
2
3
namespace luya\traits;
4
5
use luya\theme\ThemeManager;
6
use Yii;
7
use luya\base\AdminModuleInterface;
8
use luya\base\Module;
9
use luya\base\CoreModuleInterface;
10
use luya\base\PackageInstaller;
11
12
/**
13
 * LUYA Appliation trait
14
 *
15
 * @property string $webroot Returns the webroot directory event for console commands.
16
 * @property \luya\components\Mail $mail Get luya mail component
17
 * @property ThemeManager $themeManager Get luya theme manager
18
 *
19
 * @author Basil Suter <[email protected]>
20
 * @since 1.0.0
21
 */
22
trait ApplicationTrait
23
{
24
    /**
25
     * @var string Title for the application used in different sections like Login screen
26
     */
27
    public $siteTitle = 'LUYA Application';
28
    
29
    /**
30
     * @var string|boolean Set a token, which will be used to collect data from a central host, if you want to enable this feature.
31
     * Use http://passwordsgenerator.net/ to create complex strings. When you have enabled this feature you can collect information's from
32
     * all your hosts with `example.com/admin/remote?token=Sha1EncodedRemoteToken`.
33
     */
34
    public $remoteToken = false;
35
36
    /**
37
     * @var string The directory where your webroot represents, this is basically used to find the webroot directory
38
     * in the console mode, cause some importer classes need those variables.
39
     */
40
    public $webrootDirectory = 'public_html';
41
    
42
    /**
43
     * @var string This value will be used as hostInfo when running console applications in urlManager. An example for using the hostInfo
44
     *
45
     * ```php
46
     * 'consoleHostInfo' => 'https://luya.io'
47
     * ```
48
     */
49
    public $consoleHostInfo;
50
    
51
    /**
52
     * @var string This value is used when declared for console request as urlManger baseUrl in order to enable urlHandling. If {{luya\web\traits\ApplicationTrait::$consoleHostInfo}}
53
     * is defined, consoleBaseUrl will use `/` as default value. The base url is the path where the application is running after hostInfo like
54
     *
55
     * ```php
56
     * 'consoleBaseUrl' => '/luya-kickstarter'
57
     * ```
58
     *
59
     * But in the most cases when the website is online the baseUrl is `/` which is enabled by default when {{luya\web\traits\ApplicationTrait::$consoleHostInfo}} is defined.
60
     */
61
    public $consoleBaseUrl;
62
    
63
    /**
64
     * @var boolean If enabled, the application will throw an exception if a request is not from a secure connection (https). So any none secure request will throw
65
     * a {{yii\web\ForbiddenHttpException}}. This option will also make sure REST APIs are requested by a secure connection.
66
     * @since 1.0.5
67
     */
68
    public $ensureSecureConnection = false;
69
    
70
    /**
71
     * @var array Add tags to the TagParser class. Example
72
     *
73
     * ```php
74
     * 'tags' => [
75
     *     'foobar' => ['class' => '\app\tags\FoobarTag'],
76
     * ],
77
     * ```
78
     */
79
    public $tags = [];
80
81
    /**
82
     * @var array Can override the localisation value used for php internal `setlocale()` method for specific language. For example
83
     * the language is de but the it should use the locale charset `de_CH.utf8` (locale -a will return all locales installed on the server)
84
     * you can define them inside an array where key is the language and value the locale value to be used.
85
     *
86
     * ```php
87
     * public $locales = [
88
     *    'de' => 'de_CH',
89
     *    'en' => 'en_GB',
90
     * ];
91
     * ```
92
     */
93
    public $locales = [];
94
95
    /**
96
     * @var array An array to provide application wide CORS settings.
97
     *
98
     * By default the X-Headers of Yii and LUYA Admin are exposed. In order to override the cors
99
     * config the following example would work (including cors class definition).
100
     *
101
     * ```php
102
     * 'corsConfig' => [
103
     * 'class' => 'yii\filters\Cors',
104
     *     'cors' => [
105
     *         'Origin' => ['*'],
106
     *         'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
107
     *         'Access-Control-Request-Headers' => ['*'],
108
     *         'Access-Control-Allow-Credentials' => null,
109
     *         'Access-Control-Max-Age' => 86400,
110
     *         'Access-Control-Expose-Headers' => [
111
     *             'X-My-Header-Name',
112
     *         ],
113
     *     ],
114
     * ]
115
     * ```
116
     *
117
     * @since 1.0.22
118
     */
119
    public $corsConfig = [
120
        'class' => 'yii\filters\Cors',
121
        'cors' => [
122
            'Origin' => ['*'],
123
            'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
124
            'Access-Control-Request-Headers' => ['*'],
125
            'Access-Control-Allow-Credentials' => null,
126
            'Access-Control-Max-Age' => 86400,
127
            'Access-Control-Expose-Headers' => [
128
                'X-Pagination-Current-Page',
129
                'X-Pagination-Page-Count',
130
                'X-Pagination-Per-Page',
131
                'X-Pagination-Total-Count',
132
                'X-Cruft-Length',
133
            ],
134
        ],
135
    ];
136
    
137
    /**
138
     * Add trace info to luya application trait
139
     */
140
    public function init()
141
    {
142
        parent::init();
143
        
144
        // add trace info
145
        Yii::trace('initialize LUYA Application', __METHOD__);
0 ignored issues
show
Deprecated Code introduced by
The method yii\BaseYii::trace() has been deprecated with message: since 2.0.14. Use [[debug()]] instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
146
        
147
        $this->setLocale($this->language);
0 ignored issues
show
Bug introduced by
The property language does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
148
    }
149
    
150
    /**
151
     * Transform the $language into a locale sign to set php env settings.
152
     *
153
     * Example transform input `de` to `de_CH` when available $locales property as
154
     *
155
     * ```php
156
     * 'locales' => ['de' => 'de_CH']
157
     * ```
158
     *
159
     * @param string $lang Find the locale for the provided $lang short code.
160
     * @return string The localisation code for the provided lang short code.
161
     */
162
    public function ensureLocale($lang)
163
    {
164
        // see if the $lang is available in the $locales map.
165
        if (array_key_exists($lang, $this->locales)) {
166
            return $this->locales[$lang];
167
        }
168
        
169
        // generate from `de` the locale `de_DE` or from `en` `en_EN` only if $lang is 2 chars.
170
        if (strlen($lang) == 2) {
171
            return strtolower($lang) . '_' . strtoupper($lang);
172
        }
173
        
174
        return $lang;
175
    }
176
    
177
    /**
178
     * Set the application localisation trough `setlocale`.
179
     *
180
     * The value will be parsed trough {{ensureLocale()}} in order to generated different possible localisation
181
     * values like `en_EN` or `en_EN.utf8` and it will generate from `de` a locale value like `de_DE`.
182
     *
183
     * setlocale() can have multiple arguments:
184
     *
185
     * > If locale is an array or followed by additional parameters then each array element or parameter
186
     * > is tried to be set as new locale until success. This is useful if a locale is known under different
187
     * > names on different systems or for providing a fallback for a possibly not available locale.
188
     *
189
     * @param string $lang The language short code to set the locale for.
190
     */
191
    public function setLocale($lang)
192
    {
193
        $locale = str_replace(['.utf8', '.UTF-8'], '', $this->ensureLocale($lang));
194
        setlocale(LC_ALL, $locale.'.utf8', $locale.'UTF-8', $locale);
195
    }
196
197
    private $_packageInstaller;
198
    
199
    /**
200
     * Get the package Installer
201
     * @return \luya\base\PackageInstaller
202
     */
203
    public function getPackageInstaller()
204
    {
205
        if ($this->_packageInstaller == null) {
206
            $file = Yii::getAlias('@vendor/luyadev/installer.php');
207
        
208
            $data = is_file($file) ? include $file : [];
209
        
210
            $this->_packageInstaller = new PackageInstaller($data);
211
        }
212
        
213
        return $this->_packageInstaller;
214
    }
215
    
216
    /**
217
     * @inheritdoc
218
     */
219
    protected function bootstrap()
220
    {
221
        foreach ($this->getPackageInstaller()->getConfigs() as $config) {
222
            $this->bootstrap = array_merge($this->bootstrap, $config->bootstrap);
0 ignored issues
show
Bug introduced by
The property bootstrap does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
223
        }
224
        
225
        parent::bootstrap();
226
    }
227
    
228
    private $_webroot;
229
    
230
    /**
231
     * Read only property which is used in cli bootstrap process to set the @webroot alias
232
     *
233
     * ```php
234
     * Yii::setAlias('@webroot', $app->webroot);
235
     * ```
236
     */
237
    public function getWebroot()
238
    {
239
        if ($this->_webroot === null) {
240
            $this->_webroot = realpath(realpath($this->basePath) . DIRECTORY_SEPARATOR . $this->webrootDirectory);
0 ignored issues
show
Bug introduced by
The property basePath does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
241
        }
242
        
243
        return $this->_webroot;
244
    }
245
246
    /**
247
     * Add additional core components to the yii2 base core components.
248
     */
249
    public function luyaCoreComponents()
250
    {
251
        return array_merge(parent::coreComponents(), [
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (coreComponents() instead of luyaCoreComponents()). Are you sure this is correct? If so, you might want to change this to $this->coreComponents().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
252
            'mail' => ['class' => 'luya\components\Mail'],
253
            'formatter' => ['class' => 'luya\components\Formatter'],
254
            'themeManager' => ['class' => 'luya\theme\ThemeManager'],
255
        ]);
256
    }
257
258
    /**
259
     * Get an array with all modules which are an instance of the `luya\base\Module`.
260
     *
261
     * @return \luya\base\Module
262
     */
263
    public function getApplicationModules()
264
    {
265
        $modules = [];
266
267
        foreach ($this->getModules() as $id => $obj) {
0 ignored issues
show
Bug introduced by
It seems like getModules() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
268
            if ($obj instanceof Module) {
269
                $modules[$id] = $obj;
270
            }
271
        }
272
273
        return $modules;
274
    }
275
276
    /**
277
     * Return a list with all registered frontend modules except 'luya' and 'cms'. This is needed in the module block.
278
     *
279
     * @return \luya\base\Module
280
     */
281
    public function getFrontendModules()
282
    {
283
        $modules = [];
284
285
        foreach ($this->getModules() as $id => $obj) {
0 ignored issues
show
Bug introduced by
It seems like getModules() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
286
            if ($obj instanceof Module && !$obj instanceof AdminModuleInterface && !$obj instanceof CoreModuleInterface) {
287
                $modules[$id] = $obj;
288
            }
289
        }
290
291
        return $modules;
292
    }
293
    
294
    private $_adminModules;
295
296
    /**
297
     * Return all Admin Module Interface implementing modules.
298
     *
299
     * @return \luya\base\AdminModuleInterface
300
     */
301
    public function getAdminModules()
302
    {
303
        if ($this->_adminModules === null) {
304
            $this->_adminModules = [];
305
            foreach ($this->getModules() as $id => $obj) {
0 ignored issues
show
Bug introduced by
It seems like getModules() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
306
                if ($obj instanceof Module && $obj instanceof AdminModuleInterface) {
307
                    $this->_adminModules[$id] = $obj;
308
                }
309
            }
310
        }
311
312
        return $this->_adminModules;
313
    }
314
315
    /**
316
     * Get all admin menu modules
317
     *
318
     * @return array An array where the key is the module id and value the menu array.
319
     * @since 1.7.0
320
     */
321
    public function getAdminModulesMenus()
322
    {
323
        $menu = [];
324
        foreach($this->getAdminModules() as $module) {
0 ignored issues
show
Bug introduced by
The expression $this->getAdminModules() of type object<luya\base\AdminModuleInterface> is not traversable.
Loading history...
325
            if ($module->getMenu()) {
326
                $menu[$module->id] = $module->getMenu();
327
            }
328
        }
329
330
        return $menu;
331
    }
332
333
    /**
334
     * Get all assets files from all admin modules
335
     *
336
     * @return array
337
     * @since 1.7.0
338
     */
339
    public function getAdminModulesAssets()
340
    {
341
        $assets = [];
342
        foreach ($this->getAdminModules() as $module) {
0 ignored issues
show
Bug introduced by
The expression $this->getAdminModules() of type object<luya\base\AdminModuleInterface> is not traversable.
Loading history...
343
            $assets = array_merge($module->getAdminAssets(), $assets);
344
        }
345
346
        return $assets;
347
    }
348
349
    /**
350
     * Get all js translations from all admin modules
351
     *
352
     * @return array
353
     * @since 1.7.0
354
     */
355
    public function getAdminModulesJsTranslationMessages()
356
    {
357
        $jsTranslations = [];
358
        foreach ($this->getAdminModules() as $module) {
0 ignored issues
show
Bug introduced by
The expression $this->getAdminModules() of type object<luya\base\AdminModuleInterface> is not traversable.
Loading history...
359
            $jsTranslations = array_merge($module->getJsTranslationMessages(), $jsTranslations);
360
        }
361
362
        return $jsTranslations;
363
    }
364
    
365
}
366