Passed
Push — win32modeltests ( 938292...1d9554 )
by Joe
03:05
created

Win32Model::mapConstant()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
c 0
b 0
f 0
dl 0
loc 11
rs 10
cc 3
nc 3
nop 2
1
<?php
2
3
namespace PhpWinTools\WmiScripting\Models;
4
5
use PhpWinTools\WmiScripting\Connection;
6
use PhpWinTools\WmiScripting\Query\Builder;
7
use PhpWinTools\WmiScripting\Contracts\Jsonable;
8
use PhpWinTools\WmiScripting\Contracts\Arrayable;
9
use PhpWinTools\WmiScripting\Contracts\HasAttributes;
10
use PhpWinTools\WmiScripting\MappingStrings\Mappings;
11
use function PhpWinTools\WmiScripting\Support\connection;
12
use PhpWinTools\WmiScripting\Collections\ModelCollection;
13
use PhpWinTools\WmiScripting\Concerns\HasArrayableAttributes;
14
use PhpWinTools\WmiScripting\Exceptions\InvalidArgumentException;
15
use PhpWinTools\WmiScripting\Exceptions\WmiClassNotFoundException;
16
use PhpWinTools\WmiScripting\Exceptions\InvalidConnectionException;
17
use PhpWinTools\WmiScripting\Support\ApiObjects\Contracts\ObjectPath;
18
19
/**
20
 * @link https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-provider
21
 */
22
class Win32Model implements Arrayable, Jsonable, HasAttributes
23
{
24
    use HasArrayableAttributes;
25
26
    /** @var string */
27
    protected $uuid;
28
29
    /** @var ObjectPath|null */
30
    protected $objectPath;
31
32
    /** @var Builder|null */
33
    protected $queryBuilder;
34
35
    /** @var array */
36
    protected $hidden_attributes = ['queryBuilder', 'connection', 'wmi_class_name'];
37
38
    /** @var bool */
39
    protected $merge_parent_casting = true;
40
41
    /** @var bool */
42
    protected $merge_parent_hidden_attributes = true;
43
44
    /** @var array */
45
    protected $attribute_casting = [];
46
47
    protected $connection = 'default';
48
49
    protected $wmi_class_name;
50
51
    /* TODO: Remove ObjectPath dependency. Should be passed into attributes */
52
    public function __construct(array $attributes = [], ObjectPath $objectPath = null)
53
    {
54
        $this->mergeHiddenAttributes($this->hidden_attributes, $this->merge_parent_hidden_attributes);
55
        $this->fill($attributes);
56
57
        $this->objectPath = $objectPath;
58
    }
59
60
    /**
61
     * @param array           $attributes
62
     * @param ObjectPath|null $objectPath
63
     *
64
     * @return Win32Model
65
     */
66
    public static function newInstance(array $attributes = [], ObjectPath $objectPath = null)
67
    {
68
        return new static($attributes, $objectPath);
69
    }
70
71
    /**
72
     * @param Connection|string|null $connection
73
     *
74
     * @return ModelCollection|Win32Model[]
75
     */
76
    public static function all($connection = null)
77
    {
78
        return static::query(static::newInstance()->getConnection($connection))->all();
79
    }
80
81
    /**
82
     * @param Connection|string|null $connection
83
     *
84
     * @return Builder
85
     */
86
    public static function query($connection = null)
87
    {
88
        return new Builder($self = static::newInstance(), $self->getConnection($connection));
89
    }
90
91
    /**
92
     * @return string
93
     */
94
    public function getConnectionName()
95
    {
96
        return $this->connection;
97
    }
98
99
    /**
100
     * @param Connection|string|null $connection
101
     *
102
     * @throws InvalidConnectionException
103
     *
104
     * @return Connection
105
     */
106
    public function getConnection($connection = null)
107
    {
108
        return connection($connection, $this->connection);
109
    }
110
111
    /**
112
     * @return string
113
     */
114
    public function getModelNameAttribute()
115
    {
116
        return $this->getClassName();
117
    }
118
119
    /**
120
     * @return string
121
     */
122
    public function getWmiClassNameAttribute()
123
    {
124
        if (!is_null($this->wmi_class_name)) {
125
            return $this->wmi_class_name;
126
        }
127
128
        if ($this->wmi_class_name = $this->wmiClassNameSearch()) {
129
            return $this->wmi_class_name;
130
        }
131
132
        throw new WmiClassNotFoundException(
133
            'Cannot find a suitable WMI Class to query. Please set $wmi_class_name manually.'
134
        );
135
    }
136
137
    /**
138
     * Uses the Classes constant class to map models to WMI models for querying. If the current instance
139
     * does not yield results then we search the class' parents until a suitable match is found.
140
     *
141
     * @return string|null
142
     */
143
    protected function wmiClassNameSearch()
144
    {
145
        if ($result = array_search(static::class, Classes::CLASS_MAP, true)) {
146
            return $result;
147
        }
148
149
        foreach (class_parents($this) as $parent) {
150
            if ($result = array_search($parent, Classes::CLASS_MAP, true)) {
151
                return $result;
152
            }
153
        }
154
155
        return null;
156
    }
157
158
    /**
159
     * @return string
160
     */
161
    public function getClassName()
162
    {
163
        $classname = get_called_class();
164
165
        if (preg_match('@\\\\([\w]+)$@', $classname, $matches)) {
166
            $classname = $matches[1];
167
        }
168
169
        return $classname;
170
    }
171
172
    /**
173
     * @return string
174
     */
175
    public function toJson(): string
176
    {
177
        return json_encode($this->toArray());
178
    }
179
180
    /**
181
     * @return string
182
     */
183
    public function toString(): string
184
    {
185
        return $this->toJson();
186
    }
187
188
    /**
189
     * @return string
190
     */
191
    public function __toString()
192
    {
193
        return $this->toString();
194
    }
195
196
    /**
197
     * @param array $attributes
198
     */
199
    protected function fill(array $attributes)
200
    {
201
        foreach ($attributes as $key => $value) {
202
            $key = lcfirst($key);
203
            $value = $this->reduceValueArray($value);
204
            if ($this->hasProperty($key)) {
205
                $this->{$key} = $this->cast($key, $value);
206
                continue;
207
            }
208
209
            $this->unmapped_attributes[$key] = $this->cast($key, $value);
210
        }
211
    }
212
213
    /**
214
     * @param $value
215
     *
216
     * @return mixed
217
     */
218
    protected function reduceValueArray($value)
219
    {
220
        if (is_array($value) && array_key_exists('value', $value)) {
221
            $value = $value['value'];
222
        }
223
224
        return $value;
225
    }
226
227
    /**
228
     * @param Mappings|string $mapping_string_class
229
     * @param mixed           $constant
230
     *
231
     * @throws InvalidArgumentException
232
     *
233
     * @return mixed
234
     */
235
    protected function mapConstant(string $mapping_string_class, $constant)
236
    {
237
        if (!array_key_exists(Mappings::class, class_parents($mapping_string_class))) {
238
            throw new InvalidArgumentException("{$mapping_string_class} must extend " . Mappings::class);
239
        }
240
241
        if (trim($type = call_user_func_array($mapping_string_class . '::string', [$constant])) === '') {
242
            return "[{$constant}] - UNKNOWN";
243
        }
244
245
        return $type;
246
    }
247
}
248