Completed
Push — master ( 6730cd...13507f )
by J.D.
03:41
created

WordPoints_Entity::set_the_value()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 26
Code Lines 14

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 26
rs 8.8571
cc 3
eloc 14
nc 3
nop 1
1
<?php
2
3
/**
4
 * Class for representing an entity.
5
 *
6
 * @package wordpoints-hooks-api
7
 * @since 1.0.0
8
 */
9
10
/**
11
 * Represents an entity.
12
 *
13
 * An entity can be just about anything, like a Post, a User, a Comment, a Site, etc.
14
 * This class defines a single common interface for interacting with entities. This
15
 * is useful when some code needs to be able to work with several different kinds of
16
 * entities and can't know beforehand what they are.
17
 *
18
 * Each different type of entity is defined by a child of this class.
19
 *
20
 * @since 1.0.0
21
 */
22
abstract class WordPoints_Entity
23
	extends WordPoints_Entityish
24
	implements WordPoints_Entity_ParentI {
25
26
	//
27
	// Protected
28
	//
29
30
	/**
31
	 * The context in which this type of entity exists.
32
	 *
33
	 * Most entities exist only in the context of a specific site on the network (in
34
	 * multisite—when not on multisite they are just global to the install). Entities
35
	 * with other contexts need to specify that by overriding this property.
36
	 *
37
	 * @since 1.0.0
38
	 *
39
	 * @see wordpoints_entities_get_current_context_id()
40
	 *
41
	 * @var string[]
42
	 */
43
	protected $context = array( 'network', 'site' );
44
45
	/**
46
	 * The field the entity is identified by.
47
	 *
48
	 * You must either define this or override get_id_field() in your subclass.
49
	 *
50
	 * @since 1.0.0
51
	 *
52
	 * @var string
53
	 */
54
	protected $id_field;
55
56
	/**
57
	 * The field the entity can be identified by humans by.
58
	 *
59
	 * You must either define this or override get_entity_human_id().
60
	 *
61
	 * @since 1.0.0
62
	 *
63
	 * @var string
64
	 */
65
	protected $human_id_field;
66
67
	/**
68
	 * A function to call with an entity ID to retrieve that entity.
69
	 *
70
	 * You must either define this or override get_entity().
71
	 *
72
	 * @since 1.0.0
73
	 *
74
	 * @var callable
75
	 */
76
	protected $getter;
77
78
	/**
79
	 * The entity itself.
80
	 *
81
	 * This will probably always be an array or object.
82
	 *
83
	 * @since 1.0.0
84
	 *
85
	 * @var mixed
86
	 */
87
	protected $the_entity;
88
89
	/**
90
	 * The GUID of the context in which the entity exists.
91
	 *
92
	 * @since 1.0.0
93
	 *
94
	 * @see wordpoints_entities_get_current_context_id()
95
	 *
96
	 * @var array
97
	 */
98
	protected $the_context = array();
99
100
	/**
101
	 * Get an entity by its ID.
102
	 *
103
	 * @since 1.0.0
104
	 *
105
	 * @param mixed $id The unique ID of the entity.
106
	 *
107
	 * @return mixed The entity, or false if not found.
108
	 */
109
	protected function get_entity( $id ) {
110
111
		$entity = call_user_func( $this->getter, $id );
112
113
		if ( ! $this->is_entity( $entity ) ) {
114
			return false;
115
		}
116
117
		return $entity;
118
	}
119
120
	/**
121
	 * Checks if a value is an entity of this type.
122
	 *
123
	 * @since 1.0.0
124
	 *
125
	 * @param mixed $entity A value that might be an entity.
126
	 *
127
	 * @return bool Whether the passed value is an entity.
128
	 */
129
	protected function is_entity( $entity ) {
130
131
		if ( ! is_object( $entity ) && ! is_array( $entity ) ) {
132
			return false;
133
		}
134
135
		return (bool) $this->get_entity_id( $entity );
136
	}
137
138
	/**
139
	 * Gets the value of one of an entity's attributes.
140
	 *
141
	 * @since 1.0.0
142
	 *
143
	 * @param mixed  $entity An entity of this type.
144
	 * @param string $attr   The attribute whose value to get.
145
	 *
146
	 * @return mixed The value of the attribute of the entity.
147
	 */
148
	protected function get_attr_value( $entity, $attr ) {
149
150
		if ( is_array( $entity ) ) {
151
			if ( isset( $entity[ $attr ] ) ) {
152
				return $entity[ $attr ];
153
			}
154
		} else {
155
			if ( isset( $entity->{$attr} ) ) {
156
				return $entity->{$attr};
157
			}
158
		}
159
160
		return null;
161
	}
162
163
	/**
164
	 * Get the ID from an entity.
165
	 *
166
	 * @since 1.0.0
167
	 *
168
	 * @param mixed $entity The entity (usually object or array).
169
	 *
170
	 * @return mixed The ID of the entity.
171
	 */
172
	protected function get_entity_id( $entity ) {
173
		return $this->get_attr_value( $entity, $this->get_id_field() );
174
	}
175
176
	/**
177
	 * Get the human ID from an entity.
178
	 *
179
	 * The human ID is a human readable identifier for the entity, and may be
180
	 * different than the regular ID. It is also possible that the human ID will not
181
	 * always be unique.
182
	 *
183
	 * @since 1.0.0
184
	 *
185
	 * @param mixed $entity The entity (usually object or array).
186
	 *
187
	 * @return mixed The human ID of the entity.
188
	 */
189
	protected function get_entity_human_id( $entity ) {
190
		return $this->get_attr_value( $entity, $this->human_id_field );
191
	}
192
193
	//
194
	// Public
195
	//
196
197
	/**
198
	 * Get the slug(s) of the context in which this type of entity exists.
199
	 *
200
	 * @since 1.0.0
201
	 *
202
	 * @see wordpoints_entities_get_current_context_id()
203
	 *
204
	 * @return string[] The slug(s) of the context in which this type of entity
205
	 *                  must exist.
206
	 */
207
	public function get_context() {
208
		return $this->context;
209
	}
210
211
	/**
212
	 * Get the attribute that holds the entity's unique ID.
213
	 *
214
	 * @since 1.0.0
215
	 *
216
	 * @return string The attribute that holds the entity's unique ID.
217
	 */
218
	public function get_id_field() {
219
		return $this->id_field;
220
	}
221
222
	/**
223
	 * Get the human ID for an entity.
224
	 *
225
	 * TODO this is unused, may not be needed.
226
	 *
227
	 * @since 1.0.0
228
	 *
229
	 * @see self::get_entity_human_id()
230
	 *
231
	 * @param mixed $id The ID of an entity.
232
	 *
233
	 * @return string|int|float|false The human identifier for the entity, or false.
234
	 */
235
	public function get_human_id( $id ) {
236
237
		$entity = $this->get_entity( $id );
238
239
		if ( ! $entity ) {
240
			return false;
241
		}
242
243
		return $this->get_entity_human_id( $entity );
244
	}
245
246
	/**
247
	 * Check if an entity exists, by ID.
248
	 *
249
	 * @since 1.0.0
250
	 *
251
	 * @param mixed $id The entity ID.
252
	 *
253
	 * @return bool Whether or not an entity with that ID exists.
254
	 */
255
	public function exists( $id ) {
256
		return (bool) $this->get_entity( $id );
257
	}
258
259
	/**
260
	 * Get a child of this entity.
261
	 *
262
	 * Entities can have children, which currently fall into two types: attributes
263
	 * and relationships.
264
	 *
265
	 * @since 1.0.0
266
	 *
267
	 * @param string $child_slug The slug of the child.
268
	 *
269
	 * @return WordPoints_Entityish|false The child's object, or false if not found.
270
	 */
271
	public function get_child( $child_slug ) {
272
273
		$children = wordpoints_entities()->children;
0 ignored issues
show
Documentation introduced by
The property children does not exist on object<WordPoints_App_Registry>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
274
275
		$child = $children->get( $this->slug, $child_slug );
276
277
		if (
278
			isset( $this->the_value )
279
			&& $child instanceof WordPoints_Entity_ChildI
280
		) {
281
			$child->set_the_value_from_entity( $this );
282
		}
283
284
		return $child;
285
	}
286
287
	/**
288
	 * Set the value of this entity.
289
	 *
290
	 * This class can represent a type of entity generically (e.g., Post), or a
291
	 * specific entity of that type (the Post with ID 3). This function allows you to
292
	 * make this object instance represent a specific entity.
293
	 *
294
	 * If the value passed is not an entity, and is not a valid ID, it will be
295
	 * ignored and the value will not be set.
296
	 *
297
	 * @since 1.0.0
298
	 *
299
	 * @param mixed $value An entity or entity ID.
300
	 *
301
	 * @return bool Whether the value was set.
302
	 */
303
	public function set_the_value( $value ) {
304
305
		$this->the_value = $this->the_entity = $this->the_context = null;
0 ignored issues
show
Documentation Bug introduced by
It seems like null of type null is incompatible with the declared type array of property $the_context.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
306
307
		if ( $this->is_entity( $value ) ) {
308
309
			$entity = $value;
310
			$value = $this->get_entity_id( $value );
311
312
		} else {
313
314
			$entity = $this->get_entity( $value );
315
316
			if ( ! $entity ) {
317
				return false;
318
			}
319
		}
320
321
		$this->the_value   = $value;
322
		$this->the_entity  = $entity;
323
		$this->the_context = wordpoints_entities_get_current_context_id(
0 ignored issues
show
Documentation Bug introduced by
It seems like wordpoints_entities_get_...d($this->get_context()) can also be of type false. However, the property $the_context is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
324
			$this->get_context()
325
		);
326
327
		return true;
328
	}
329
330
	/**
331
	 * Get the value of one of this entity's attributes.
332
	 *
333
	 * @since 1.0.0
334
	 *
335
	 * @param string $attr The attribute to get the value of.
336
	 *
337
	 * @return mixed The value of the attribute.
338
	 */
339
	public function get_the_attr_value( $attr ) {
340
		return $this->get_attr_value( $this->the_entity, $attr );
341
	}
342
343
	/**
344
	 * Get the ID of the entity.
345
	 *
346
	 * @since 1.0.0
347
	 *
348
	 * @return mixed The ID of the entity.
349
	 */
350
	public function get_the_id() {
351
		return $this->get_the_value();
352
	}
353
354
	/**
355
	 * Get the human ID of the entity.
356
	 *
357
	 * @since 1.0.0
358
	 *
359
	 * @see self::get_entity_human_id()
360
	 *
361
	 * @return string|int|float|null The human identifier for the entity, or null.
362
	 */
363
	public function get_the_human_id() {
364
		return $this->get_entity_human_id( $this->the_entity );
365
	}
366
367
	/**
368
	 * Get the context in which the current entity exists.
369
	 *
370
	 * @since 1.0.0
371
	 *
372
	 * @see wordpoints_entities_get_current_context_id()
373
	 *
374
	 * @return array|null The context values indexed by context slugs.
375
	 */
376
	public function get_the_context() {
377
		return $this->the_context;
378
	}
379
380
	/**
381
	 * Get the Globally Unique ID of the entity.
382
	 *
383
	 * The GUID is an array of values that includes the GUID of the entity context
384
	 * in addition to the ID of the entity itself.
385
	 *
386
	 * @since 1.0.0
387
	 *
388
	 * @return array|false|null The GUID, false if it could not be determined, or
389
	 *                          null if the value isn't set.
390
	 */
391
	public function get_the_guid() {
392
393
		$guid = $this->get_the_context();
394
395
		if ( ! is_array( $guid ) ) {
396
			return $guid;
397
		}
398
399
		$guid[ $this->slug ] = $this->get_the_id();
400
401
		return $guid;
402
	}
403
}
404
405
// EOF
406