Completed
Push — develop ( 11971b...45f15f )
by Nate
06:59
created

ObjectHelper::findClassFromConfig()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 32

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
dl 0
loc 32
ccs 0
cts 25
cp 0
rs 8.7857
c 0
b 0
f 0
cc 6
nc 8
nop 2
crap 42
1
<?php
2
3
/**
4
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 * @license    https://github.com/flipboxfactory/craft-ember/blob/master/LICENSE
6
 * @link       https://github.com/flipboxfactory/craft-ember/
7
 */
8
9
namespace flipbox\craft\ember\helpers;
10
11
use craft\helpers\ArrayHelper;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, flipbox\craft\ember\helpers\ArrayHelper.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
12
use craft\helpers\Json as JsonHelper;
13
use yii\base\BaseObject;
14
use yii\base\InvalidConfigException;
15
16
/**
17
 * @author Flipbox Factory <[email protected]>
18
 * @since 2.0.0
19
 */
20
class ObjectHelper
21
{
22
    /**
23
     * Configures an object with the initial property values.
24
     *
25
     * @param BaseObject $object
26
     * @param array $properties
27
     * @return BaseObject
28
     */
29
    public static function populate(BaseObject $object, $properties = []): BaseObject
30
    {
31
        // Set properties
32
        foreach ($properties as $name => $value) {
33
            if ($object->canSetProperty($name)) {
34
                $object->$name = $value;
35
            }
36
        }
37
38
        return $object;
39
    }
40
41
    /**
42
     * Create a new object
43
     *
44
     * @param $config
45
     * @param string|null $instanceOf
46
     * @throws InvalidConfigException
47
     * @return BaseObject
48
     */
49
    public static function create($config, string $instanceOf = null): BaseObject
50
    {
51
        // Get class from config
52
        $class = static::checkConfig($config, $instanceOf);
53
54
        // New object
55
        $object = new $class();
56
57
        // Populate
58
        if ($config) {
59
            static::populate($object, $config);
60
        }
61
62
        return $object;
63
    }
64
65
    /**
66
     * Checks the config for a valid class
67
     *
68
     * @param $config
69
     * @param string|null $instanceOf
70
     * @param bool $removeClass
71
     * @throws InvalidConfigException
72
     * @return string
73
     */
74
    public static function checkConfig(&$config, string $instanceOf = null, bool $removeClass = true): string
75
    {
76
        // Get class from config
77
        $class = static::getClassFromConfig($config, $removeClass);
78
79
        // Make sure we have a valid class
80
        if ($instanceOf !== null &&
81
            !(is_subclass_of($class, $instanceOf) || $class instanceof $instanceOf)
82
        ) {
83
            throw new InvalidConfigException(
84
                sprintf(
85
                    "The class '%s' must be an instance of '%s'",
86
                    (string)$class,
87
                    (string)$instanceOf
88
                )
89
            );
90
        }
91
92
        return $class;
93
    }
94
95
    /**
96
     * Get a class from a config
97
     *
98
     * @param $config
99
     * @param bool $removeClass
100
     * @throws InvalidConfigException
101
     * @return string
102
     */
103
    public static function getClassFromConfig(&$config, bool $removeClass = false): string
104
    {
105
        // Find class
106
        $class = static::findClassFromConfig($config, $removeClass);
107
108
        if (empty($class)) {
109
            throw new InvalidConfigException(
110
                sprintf(
111
                    "The configuration must specify a 'class' property: '%s'",
112
                    JsonHelper::encode($config)
113
                )
114
            );
115
        }
116
117
        return $class;
118
    }
119
120
    /**
121
     * Find a class from a config
122
     *
123
     * @param $config
124
     * @param bool $removeClass
125
     * @return null|string
126
     */
127
    public static function findClassFromConfig(&$config, bool $removeClass = false)
128
    {
129
        // Normalize the config
130
        if (is_string($config)) {
131
            // Set as class
132
            $class = $config;
133
134
            // Clear class from config
135
            $config = '';
136
        } elseif (is_object($config)) {
137
            return get_class($config);
138
        } else {
139
            // Force Array
140
            if (!is_array($config)) {
141
                $config = ArrayHelper::toArray($config, [], false);
142
            }
143
144
            if ($removeClass) {
145
                if (!$class = ArrayHelper::remove($config, 'class')) {
146
                    $class = ArrayHelper::remove($config, 'type');
147
                }
148
            } else {
149
                $class = ArrayHelper::getValue(
150
                    $config,
151
                    'class',
152
                    ArrayHelper::getValue($config, 'type')
153
                );
154
            }
155
        }
156
157
        return $class;
158
    }
159
}
160