Model::getAliasedObject()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Silk\User;
4
5
use WP_User;
6
use Silk\Type\Model as BaseModel;
7
use Silk\Support\Collection;
8
use Silk\Exception\WP_ErrorException;
9
use Silk\User\Exception\UserNotFoundException;
10
11
class Model extends BaseModel
12
{
13
    /**
14
     * The object type in WordPress
15
     */
16
    const OBJECT_TYPE = 'user';
17
18
    /**
19
     * The primary ID property on the object
20
     */
21
    const ID_PROPERTY = 'ID';
22
23
    /**
24
     * User Constructor.
25
     *
26
     * @param array|WP_User $user  User object or array of attributes
27
     */
28
    public function __construct($user = null)
29
    {
30
        $attributes = is_array($user) ? $user : [];
31
32
        if (! $user instanceof WP_User) {
33
            $user = new WP_User();
34
        }
35
36
        $this->object = $this->normalizeData($user);
0 ignored issues
show
Bug introduced by
The property object is declared read-only in Silk\Type\Model.
Loading history...
37
38
        $this->fill($attributes);
39
    }
40
41
    /**
42
     * Retrieve a new instance by the ID.
43
     *
44
     * @param int|string $id Primary ID
45
     *
46
     * @return null|static
47
     */
48
    public static function find($id)
49
    {
50
        try {
51
            return static::fromID($id);
52
        } catch (\Exception $e) {
53
            return null;
54
        }
55
    }
56
57
    /**
58
     * Create a new instance from the user ID.
59
     *
60
     * @param  string|int $id  User ID
61
     *
62
     * @throws UserNotFoundException
63
     *
64
     * @return static
65
     */
66
    public static function fromID($id)
67
    {
68
        if (! $user = get_user_by('id', $id)) {
69
            throw new UserNotFoundException("No user found with ID $id");
70
        }
71
72
        return new static($user);
73
    }
74
75
    /**
76
     * Create a new instance from the username.
77
     *
78
     * @param  string $username  Username (login)
79
     *
80
     * @throws UserNotFoundException
81
     *
82
     * @return static
83
     */
84
    public static function fromUsername($username)
85
    {
86
        if (! $user = get_user_by('login', $username)) {
87
            throw new UserNotFoundException("No user found with username: $username");
88
        }
89
90
        return new static($user);
91
    }
92
93
    /**
94
     * Create a new instance from the user's email address.
95
     *
96
     * @param  string $email  User email address
97
     *
98
     * @throws UserNotFoundException
99
     *
100
     * @return static
101
     */
102
    public static function fromEmail($email)
103
    {
104
        if (! $user = get_user_by('email', $email)) {
105
            throw new UserNotFoundException("No user found with email address: $email");
106
        }
107
108
        return new static($user);
109
    }
110
111
    /**
112
     * Create a new instance from the user's slug.
113
     *
114
     * @param  string $slug  User slug (nicename)
115
     *
116
     * @throws UserNotFoundException
117
     *
118
     * @return static
119
     */
120
    public static function fromSlug($slug)
121
    {
122
        if (! $user = get_user_by('slug', $slug)) {
123
            throw new UserNotFoundException("No user found with slug: $slug");
124
        }
125
126
        return new static($user);
127
    }
128
129
    /**
130
     * Create a new instance using the currently authenticated user.
131
     *
132
     * @return static
133
     */
134
    public static function auth()
135
    {
136
        return new static(wp_get_current_user());
137
    }
138
139
    /**
140
     * Get the URL for the user's posts archive.
141
     *
142
     * @return string
143
     */
144
    public function postsUrl()
145
    {
146
        return get_author_posts_url($this->id, $this->slug);
0 ignored issues
show
Bug Best Practice introduced by
The property slug does not exist on Silk\User\Model. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug introduced by
It seems like $this->slug can also be of type object; however, parameter $author_nicename of get_author_posts_url() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

146
        return get_author_posts_url($this->id, /** @scrutinizer ignore-type */ $this->slug);
Loading history...
147
    }
148
149
    /**
150
     * Get a new query builder for the model.
151
     *
152
     * @return QueryBuilder
153
     */
154
    public function newQuery()
155
    {
156
        return QueryBuilder::make()->setModel($this);
157
    }
158
159
    /**
160
     * Save the changes to the database.
161
     *
162
     * @throws WP_ErrorException
163
     *
164
     * @return $this
165
     */
166
    public function save()
167
    {
168
        if (! $this->id) {
169
            $result = wp_insert_user($this->object);
170
        } else {
171
            $result = wp_update_user($this->object);
172
        }
173
174
        if (is_wp_error($result)) {
175
            throw new WP_ErrorException($result);
0 ignored issues
show
Bug introduced by
It seems like $result can also be of type integer; however, parameter $error of Silk\Exception\WP_ErrorException::__construct() does only seem to accept WP_Error, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

175
            throw new WP_ErrorException(/** @scrutinizer ignore-type */ $result);
Loading history...
176
        }
177
178
        $this->setId($result)->refresh();
0 ignored issues
show
Bug introduced by
It seems like $result can also be of type WP_Error; however, parameter $id of Silk\Type\Model::setId() does only seem to accept integer|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

178
        $this->setId(/** @scrutinizer ignore-type */ $result)->refresh();
Loading history...
179
180
        return $this;
181
    }
182
183
    /**
184
     * Delete the modeled record from the database.
185
     *
186
     * @return $this
187
     */
188
    public function delete()
189
    {
190
        if (wp_delete_user($this->id)) {
191
            $this->setObject(new WP_User);
192
        }
193
194
        return $this;
195
    }
196
197
    /**
198
     * Reload the object from the database.
199
     *
200
     * @return $this
201
     */
202
    public function refresh()
203
    {
204
        $this->setObject(new WP_User($this->id));
205
206
        return $this;
207
    }
208
209
    /**
210
     * Set the WP_User object on the model.
211
     *
212
     * @param WP_User $user
213
     *
214
     * @return $this
215
     */
216
    protected function setObject($user)
217
    {
218
        $this->object = $this->normalizeData($user);
0 ignored issues
show
Bug introduced by
The property object is declared read-only in Silk\Type\Model.
Loading history...
219
220
        return $this;
221
    }
222
223
    /**
224
     * Normalize the user data object on the given User.
225
     *
226
     * This is necessary for object aliases and shorthand properties to work properly
227
     * due to the fact that the WP_User's data object is a plain object which
228
     * does not always contain all properties as is the case with other WP objects.
229
     *
230
     * @param WP_User $user
231
     *
232
     * @return WP_User
233
     */
234
    protected function normalizeData(WP_User $user)
235
    {
236
        Collection::make([
237
            'ID',
238
            'user_login',
239
            'user_pass',
240
            'user_nicename',
241
            'user_email',
242
            'user_registered',
243
            'user_activation_key',
244
            'user_status',
245
            'display_name',
246
            'spam',
247
            'deleted',
248
        ])->diff(array_keys((array) $user->data))
249
            ->each(function ($property) use ($user) {
250
                $user->data->$property = null; // exists but ! isset
251
            });
252
253
        return $user;
254
    }
255
256
    /**
257
     * Get the aliased object.
258
     *
259
     * Most user data from the database is stored as an object on the user's `data` property.
260
     *
261
     * @return object|\stdClass
262
     */
263
    protected function getAliasedObject()
264
    {
265
        return $this->object->data;
266
    }
267
}
268