Passed
Push — drivers ( 453ead...6c2ab9 )
by Joe
01:44
created

Win32Model::setConnection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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