Completed
Push — remove-yii-autoloader ( ec27ff )
by Alexander
03:32
created

BaseYii::autoload()   C

Complexity

Conditions 10
Paths 8

Size

Total Lines 22
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 10.0363

Importance

Changes 0
Metric Value
dl 0
loc 22
ccs 13
cts 14
cp 0.9286
rs 6.1368
c 0
b 0
f 0
cc 10
eloc 14
nc 8
nop 1
crap 10.0363

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @link http://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license http://www.yiiframework.com/license/
6
 */
7
8
namespace yii;
9
10
use Psr\Log\LoggerInterface;
11
use Psr\Log\LogLevel;
12
use yii\base\InvalidConfigException;
13
use yii\base\InvalidArgumentException;
14
use yii\base\UnknownClassException;
15
use yii\di\Container;
16
use yii\di\Instance;
17
use yii\helpers\VarDumper;
18
use yii\log\Logger;
19
use yii\profile\Profiler;
20
use yii\profile\ProfilerInterface;
21
22
/**
23
 * Gets the application start timestamp.
24
 */
25
defined('YII_BEGIN_TIME') or define('YII_BEGIN_TIME', microtime(true));
26
/**
27
 * This constant defines the framework installation directory.
28
 */
29
defined('YII2_PATH') or define('YII2_PATH', __DIR__);
30
/**
31
 * This constant defines whether the application should be in debug mode or not. Defaults to false.
32
 */
33
defined('YII_DEBUG') or define('YII_DEBUG', false);
34
/**
35
 * This constant defines in which environment the application is running. Defaults to 'prod', meaning production environment.
36
 * You may define this constant in the bootstrap script. The value could be 'prod' (production), 'dev' (development), 'test', 'staging', etc.
37
 */
38
defined('YII_ENV') or define('YII_ENV', 'prod');
39
/**
40
 * Whether the the application is running in production environment
41
 */
42
defined('YII_ENV_PROD') or define('YII_ENV_PROD', YII_ENV === 'prod');
43
/**
44
 * Whether the the application is running in development environment
45
 */
46
defined('YII_ENV_DEV') or define('YII_ENV_DEV', YII_ENV === 'dev');
47
/**
48
 * Whether the the application is running in testing environment
49
 */
50
defined('YII_ENV_TEST') or define('YII_ENV_TEST', YII_ENV === 'test');
51
52
/**
53
 * This constant defines whether error handling should be enabled. Defaults to true.
54
 */
55
defined('YII_ENABLE_ERROR_HANDLER') or define('YII_ENABLE_ERROR_HANDLER', true);
56
57
/**
58
 * BaseYii is the core helper class for the Yii framework.
59
 *
60
 * Do not use BaseYii directly. Instead, use its child class [[\Yii]] which you can replace to
61
 * customize methods of BaseYii.
62
 *
63
 * @author Qiang Xue <[email protected]>
64
 * @since 2.0
65
 */
66
class BaseYii
67
{
68
    /**
69
     * @var \yii\console\Application|\yii\web\Application the application instance
70
     */
71
    public static $app;
72
    /**
73
     * @var array registered path aliases
74
     * @see getAlias()
75
     * @see setAlias()
76
     */
77
    public static $aliases = ['@yii' => __DIR__];
78
    /**
79
     * @var Container the dependency injection (DI) container used by [[createObject()]].
80
     * You may use [[Container::set()]] to set up the needed dependencies of classes and
81
     * their initial property values.
82
     * @see createObject()
83
     * @see Container
84
     */
85
    public static $container;
86
87
88
    /**
89
     * Returns a string representing the current version of the Yii framework.
90
     * @return string the version of Yii framework
91
     */
92
    public static function getVersion()
93
    {
94
        return '2.0.13-dev';
95
    }
96
97
    /**
98
     * Translates a path alias into an actual path.
99
     *
100
     * The translation is done according to the following procedure:
101
     *
102
     * 1. If the given alias does not start with '@', it is returned back without change;
103
     * 2. Otherwise, look for the longest registered alias that matches the beginning part
104
     *    of the given alias. If it exists, replace the matching part of the given alias with
105
     *    the corresponding registered path.
106
     * 3. Throw an exception or return false, depending on the `$throwException` parameter.
107
     *
108
     * For example, by default '@yii' is registered as the alias to the Yii framework directory,
109
     * say '/path/to/yii'. The alias '@yii/web' would then be translated into '/path/to/yii/web'.
110
     *
111
     * If you have registered two aliases '@foo' and '@foo/bar'. Then translating '@foo/bar/config'
112
     * would replace the part '@foo/bar' (instead of '@foo') with the corresponding registered path.
113
     * This is because the longest alias takes precedence.
114
     *
115
     * However, if the alias to be translated is '@foo/barbar/config', then '@foo' will be replaced
116
     * instead of '@foo/bar', because '/' serves as the boundary character.
117
     *
118
     * Note, this method does not check if the returned path exists or not.
119
     *
120
     * See the [guide article on aliases](guide:concept-aliases) for more information.
121
     *
122
     * @param string $alias the alias to be translated.
123
     * @param bool $throwException whether to throw an exception if the given alias is invalid.
124
     * If this is false and an invalid alias is given, false will be returned by this method.
125
     * @return string|bool the path corresponding to the alias, false if the root alias is not previously registered.
126
     * @throws InvalidArgumentException if the alias is invalid while $throwException is true.
127
     * @see setAlias()
128
     */
129
    public static function getAlias($alias, $throwException = true)
130
    {
131
        if (strncmp($alias, '@', 1)) {
132
            // not an alias
133
            return $alias;
134
        }
135
136
        $pos = strpos($alias, '/');
137
        $root = $pos === false ? $alias : substr($alias, 0, $pos);
138
139
        if (isset(static::$aliases[$root])) {
140
            if (is_string(static::$aliases[$root])) {
141
                return $pos === false ? static::$aliases[$root] : static::$aliases[$root] . substr($alias, $pos);
142
            }
143
144
            foreach (static::$aliases[$root] as $name => $path) {
145
                if (strpos($alias . '/', $name . '/') === 0) {
146
                    return $path . substr($alias, strlen($name));
147
                }
148
            }
149
        }
150
151
        if ($throwException) {
152
            throw new InvalidArgumentException("Invalid path alias: $alias");
153
        }
154
155
        return false;
156
    }
157
158
    /**
159
     * Returns the root alias part of a given alias.
160
     * A root alias is an alias that has been registered via [[setAlias()]] previously.
161
     * If a given alias matches multiple root aliases, the longest one will be returned.
162
     * @param string $alias the alias
163
     * @return string|bool the root alias, or false if no root alias is found
164
     */
165
    public static function getRootAlias($alias)
166
    {
167
        $pos = strpos($alias, '/');
168
        $root = $pos === false ? $alias : substr($alias, 0, $pos);
169
170
        if (isset(static::$aliases[$root])) {
171
            if (is_string(static::$aliases[$root])) {
172
                return $root;
173
            }
174
175
            foreach (static::$aliases[$root] as $name => $path) {
176
                if (strpos($alias . '/', $name . '/') === 0) {
177
                    return $name;
178
                }
179
            }
180
        }
181
182
        return false;
183
    }
184
185
    /**
186
     * Registers a path alias.
187
     *
188
     * A path alias is a short name representing a long path (a file path, a URL, etc.)
189
     * For example, we use '@yii' as the alias of the path to the Yii framework directory.
190
     *
191
     * A path alias must start with the character '@' so that it can be easily differentiated
192
     * from non-alias paths.
193
     *
194
     * Note that this method does not check if the given path exists or not. All it does is
195
     * to associate the alias with the path.
196
     *
197
     * Any trailing '/' and '\' characters in the given path will be trimmed.
198
     *
199
     * See the [guide article on aliases](guide:concept-aliases) for more information.
200
     *
201
     * @param string $alias the alias name (e.g. "@yii"). It must start with a '@' character.
202
     * It may contain the forward slash '/' which serves as boundary character when performing
203
     * alias translation by [[getAlias()]].
204
     * @param string $path the path corresponding to the alias. If this is null, the alias will
205
     * be removed. Trailing '/' and '\' characters will be trimmed. This can be
206
     *
207
     * - a directory or a file path (e.g. `/tmp`, `/tmp/main.txt`)
208
     * - a URL (e.g. `http://www.yiiframework.com`)
209
     * - a path alias (e.g. `@yii/base`). In this case, the path alias will be converted into the
210
     *   actual path first by calling [[getAlias()]].
211
     *
212
     * @throws InvalidArgumentException if $path is an invalid alias.
213
     * @see getAlias()
214
     */
215
    public static function setAlias($alias, $path)
216
    {
217
        if (strncmp($alias, '@', 1)) {
218
            $alias = '@' . $alias;
219
        }
220
        $pos = strpos($alias, '/');
221
        $root = $pos === false ? $alias : substr($alias, 0, $pos);
222
        if ($path !== null) {
223
            $path = strncmp($path, '@', 1) ? rtrim($path, '\\/') : static::getAlias($path);
224
            if (!isset(static::$aliases[$root])) {
225
                if ($pos === false) {
226
                    static::$aliases[$root] = $path;
227
                } else {
228
                    static::$aliases[$root] = [$alias => $path];
229
                }
230
            } elseif (is_string(static::$aliases[$root])) {
231
                if ($pos === false) {
232
                    static::$aliases[$root] = $path;
233
                } else {
234
                    static::$aliases[$root] = [
235
                        $alias => $path,
236
                        $root => static::$aliases[$root],
237
                    ];
238
                }
239
            } else {
240
                static::$aliases[$root][$alias] = $path;
241
                krsort(static::$aliases[$root]);
242
            }
243
        } elseif (isset(static::$aliases[$root])) {
244
            if (is_array(static::$aliases[$root])) {
245
                unset(static::$aliases[$root][$alias]);
246
            } elseif ($pos === false) {
247
                unset(static::$aliases[$root]);
248
            }
249
        }
250
    }
251
252
    /**
253
     * Creates a new object using the given configuration.
254
     *
255
     * You may view this method as an enhanced version of the `new` operator.
256
     * The method supports creating an object based on a class name, a configuration array or
257
     * an anonymous function.
258
     *
259
     * Below are some usage examples:
260
     *
261
     * ```php
262
     * // create an object using a class name
263
     * $object = Yii::createObject(\yii\db\Connection::class);
264
     *
265
     * // create an object using a configuration array
266
     * $object = Yii::createObject([
267
     *     'class' => \yii\db\Connection::class,
268
     *     'dsn' => 'mysql:host=127.0.0.1;dbname=demo',
269
     *     'username' => 'root',
270
     *     'password' => '',
271
     *     'charset' => 'utf8',
272
     * ]);
273
     *
274
     * // create an object with two constructor parameters
275
     * $object = \Yii::createObject('MyClass', [$param1, $param2]);
276
     * ```
277
     *
278
     * Using [[\yii\di\Container|dependency injection container]], this method can also identify
279
     * dependent objects, instantiate them and inject them into the newly created object.
280
     *
281
     * @param string|array|callable $type the object type. This can be specified in one of the following forms:
282
     *
283
     * - a string: representing the class name of the object to be created
284
     * - a configuration array: the array must contain a `class` element which is treated as the object class,
285
     *   and the rest of the name-value pairs will be used to initialize the corresponding object properties
286
     * - a PHP callable: either an anonymous function or an array representing a class method (`[$class or $object, $method]`).
287
     *   The callable should return a new instance of the object being created.
288
     *
289
     * @param array $params the constructor parameters
290
     * @return object the created object
291
     * @throws InvalidConfigException if the configuration is invalid.
292
     * @see \yii\di\Container
293
     */
294
    public static function createObject($type, array $params = [])
295
    {
296
        if (is_string($type)) {
297
            return static::$container->get($type, $params);
298
        } elseif (is_array($type) && isset($type['class'])) {
299
            $class = $type['class'];
300
            unset($type['class']);
301
            return static::$container->get($class, $params, $type);
302
        } elseif (is_callable($type, true)) {
303
            return static::$container->invoke($type, $params);
304
        } elseif (is_array($type)) {
305
            throw new InvalidConfigException('Object configuration must be an array containing a "class" element.');
306
        }
307
308
        throw new InvalidConfigException('Unsupported configuration type: ' . gettype($type));
309
    }
310
311
    /**
312
     * @var LoggerInterface logger instance.
313
     */
314
    private static $_logger;
315
316
    /**
317
     * @return LoggerInterface message logger
318
     */
319
    public static function getLogger()
320
    {
321
        if (self::$_logger !== null) {
322
            return self::$_logger;
323
        }
324
325
        return self::$_logger = Instance::ensure(['class' => Logger::class], LoggerInterface::class);
326
    }
327
328
    /**
329
     * Sets the logger object.
330
     * @param LoggerInterface|\Closure|array|null $logger the logger object or its DI compatible configuration.
331
     */
332
    public static function setLogger($logger)
333
    {
334
        if ($logger === null) {
335
            self::$_logger = null;
336
            return;
337
        }
338
339
        if (is_array($logger)) {
340
            if (!isset($logger['class']) && is_object(self::$_logger)) {
341
                static::configure(self::$_logger, $logger);
342
                return;
343
            }
344
            $logger = array_merge(['class' => Logger::class], $logger);
345
        } elseif ($logger instanceof \Closure) {
346
            $logger = call_user_func($logger);
347
        }
348
349
        self::$_logger = Instance::ensure($logger, LoggerInterface::class);
350
    }
351
352
    /**
353
     * @var ProfilerInterface profiler instance.
354
     * @since 2.1
355
     */
356
    private static $_profiler;
357
358
    /**
359
     * @return ProfilerInterface profiler instance.
360
     * @since 2.1
361
     */
362
    public static function getProfiler()
363
    {
364
        if (self::$_profiler !== null) {
365
            return self::$_profiler;
366
        }
367
        return self::$_profiler = Instance::ensure(['class' => Profiler::class], ProfilerInterface::class);
368
    }
369
370
    /**
371
     * @param ProfilerInterface|\Closure|array|null $profiler profiler instance or its DI compatible configuration.
372
     * @since 2.1
373
     */
374
    public static function setProfiler($profiler)
375
    {
376
        if ($profiler === null) {
377
            self::$_profiler = null;
378
            return;
379
        }
380
381
        if (is_array($profiler)) {
382
            if (!isset($profiler['class']) && is_object(self::$_profiler)) {
383
                static::configure(self::$_profiler, $profiler);
384
                return;
385
            }
386
            $profiler = array_merge(['class' => Profiler::class], $profiler);
387
        } elseif ($profiler instanceof \Closure) {
388
            $profiler = call_user_func($profiler);
389
        }
390
391
        self::$_profiler = Instance::ensure($profiler, ProfilerInterface::class);
392
    }
393
394
    /**
395
     * Logs a message with category.
396
     * @param string $level log level.
397
     * @param mixed $message the message to be logged. This can be a simple string or a more
398
     * complex data structure, such as array.
399
     * @param string $category the category of the message.
400
     * @since 2.1.0
401
     */
402
    public static function log($level, $message, $category = 'application')
403
    {
404
        $context = ['category' => $category];
405
        if (!is_string($message)) {
406
            if ($message instanceof \Throwable) {
407
                // exceptions are string-convertable, thus should be passed as it is to the logger
408
                // if exception instance is given to produce a stack trace, it MUST be in a key named "exception".
409
                $context['exception'] = $message;
410
            } else {
411
                // exceptions may not be serializable if in the call stack somewhere is a Closure
412
                $message = VarDumper::export($message);
413
            }
414
        }
415
        static::getLogger()->log($level, $message, $context);
0 ignored issues
show
Bug introduced by
It seems like $message defined by parameter $message on line 402 can also be of type object<Throwable>; however, Psr\Log\LoggerInterface::log() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
416
    }
417
418
    /**
419
     * Logs a debug message.
420
     * Trace messages are logged mainly for development purpose to see
421
     * the execution work flow of some code.
422
     * @param string|array $message the message to be logged. This can be a simple string or a more
423
     * complex data structure, such as array.
424
     * @param string $category the category of the message.
425
     */
426
    public static function debug($message, $category = 'application')
427
    {
428
        if (YII_DEBUG) {
429
            static::log(LogLevel::DEBUG, $message, $category);
430
        }
431
    }
432
433
    /**
434
     * Logs an error message.
435
     * An error message is typically logged when an unrecoverable error occurs
436
     * during the execution of an application.
437
     * @param string|array $message the message to be logged. This can be a simple string or a more
438
     * complex data structure, such as array.
439
     * @param string $category the category of the message.
440
     */
441
    public static function error($message, $category = 'application')
442
    {
443
        static::log(LogLevel::ERROR, $message, $category);
444
    }
445
446
    /**
447
     * Logs a warning message.
448
     * A warning message is typically logged when an error occurs while the execution
449
     * can still continue.
450
     * @param string|array $message the message to be logged. This can be a simple string or a more
451
     * complex data structure, such as array.
452
     * @param string $category the category of the message.
453
     */
454
    public static function warning($message, $category = 'application')
455
    {
456
        static::log(LogLevel::WARNING, $message, $category);
457
    }
458
459
    /**
460
     * Logs an informative message.
461
     * An informative message is typically logged by an application to keep record of
462
     * something important (e.g. an administrator logs in).
463
     * @param string|array $message the message to be logged. This can be a simple string or a more
464
     * complex data structure, such as array.
465
     * @param string $category the category of the message.
466
     */
467
    public static function info($message, $category = 'application')
468
    {
469
        static::log(LogLevel::INFO, $message, $category);
470
    }
471
472
    /**
473
     * Marks the beginning of a code block for profiling.
474
     * This has to be matched with a call to [[endProfile]] with the same category name.
475
     * The begin- and end- calls must also be properly nested. For example,
476
     *
477
     * ```php
478
     * \Yii::beginProfile('block1');
479
     * // some code to be profiled
480
     *     \Yii::beginProfile('block2');
481
     *     // some other code to be profiled
482
     *     \Yii::endProfile('block2');
483
     * \Yii::endProfile('block1');
484
     * ```
485
     * @param string $token token for the code block
486
     * @param string $category the category of this log message
487
     * @see endProfile()
488
     */
489
    public static function beginProfile($token, $category = 'application')
490
    {
491
        static::getProfiler()->begin($token, ['category' => $category]);
492
    }
493
494
    /**
495
     * Marks the end of a code block for profiling.
496
     * This has to be matched with a previous call to [[beginProfile]] with the same category name.
497
     * @param string $token token for the code block
498
     * @param string $category the category of this log message
499
     * @see beginProfile()
500
     */
501
    public static function endProfile($token, $category = 'application')
502
    {
503
        static::getProfiler()->end($token, ['category' => $category]);
504
    }
505
506
    /**
507
     * Returns an HTML hyperlink that can be displayed on your Web page showing "Powered by Yii Framework" information.
508
     * @return string an HTML hyperlink that can be displayed on your Web page showing "Powered by Yii Framework" information
509
     */
510
    public static function powered()
511
    {
512
        return \Yii::t('yii', 'Powered by {yii}', [
513
            'yii' => '<a href="http://www.yiiframework.com/" rel="external">' . \Yii::t('yii',
514
                    'Yii Framework') . '</a>',
515
        ]);
516
    }
517
518
    /**
519
     * Translates a message to the specified language.
520
     *
521
     * This is a shortcut method of [[\yii\i18n\I18N::translate()]].
522
     *
523
     * The translation will be conducted according to the message category and the target language will be used.
524
     *
525
     * You can add parameters to a translation message that will be substituted with the corresponding value after
526
     * translation. The format for this is to use curly brackets around the parameter name as you can see in the following example:
527
     *
528
     * ```php
529
     * $username = 'Alexander';
530
     * echo \Yii::t('app', 'Hello, {username}!', ['username' => $username]);
531
     * ```
532
     *
533
     * Further formatting of message parameters is supported using the [PHP intl extensions](http://www.php.net/manual/en/intro.intl.php)
534
     * message formatter. See [[\yii\i18n\I18N::translate()]] for more details.
535
     *
536
     * @param string $category the message category.
537
     * @param string $message the message to be translated.
538
     * @param array $params the parameters that will be used to replace the corresponding placeholders in the message.
539
     * @param string $language the language code (e.g. `en-US`, `en`). If this is null, the current
540
     * [[\yii\base\Application::language|application language]] will be used.
541
     * @return string the translated message.
542
     */
543
    public static function t($category, $message, $params = [], $language = null)
544
    {
545
        if (static::$app !== null) {
546
            return static::$app->getI18n()->translate($category, $message, $params, $language ?: static::$app->language);
547
        }
548
549
        $placeholders = [];
550
        foreach ((array) $params as $name => $value) {
551
            $placeholders['{' . $name . '}'] = $value;
552
        }
553
554
        return ($placeholders === []) ? $message : strtr($message, $placeholders);
555
    }
556
557
    /**
558
     * Configures an object with the initial property values.
559
     * @param object $object the object to be configured
560
     * @param array $properties the property initial values given in terms of name-value pairs.
561
     * @return object the object itself
562
     */
563
    public static function configure($object, $properties)
564
    {
565
        foreach ($properties as $name => $value) {
566
            $object->$name = $value;
567
        }
568
569
        return $object;
570
    }
571
572
    /**
573
     * Returns the public member variables of an object.
574
     * This method is provided such that we can get the public member variables of an object.
575
     * It is different from "get_object_vars()" because the latter will return private
576
     * and protected variables if it is called within the object itself.
577
     * @param object $object the object to be handled
578
     * @return array the public member variables of the object
579
     */
580
    public static function getObjectVars($object)
581
    {
582
        return get_object_vars($object);
583
    }
584
}
585