Completed
Push — develop ( 3610c0...c97a92 )
by David
01:25 queued 13s
created
src/includes/class-wordlift-relation-service.php 2 patches
Indentation   +428 added lines, -428 removed lines patch added patch discarded remove patch
@@ -18,404 +18,404 @@  discard block
 block discarded – undo
18 18
  */
19 19
 class Wordlift_Relation_Service {
20 20
 
21
-	/**
22
-	 * The relation table name in MySQL, set during instantiation.
23
-	 *
24
-	 * @since  3.15.0
25
-	 * @access private
26
-	 * @var string $relation_table The relation table name.
27
-	 */
28
-	private $relation_table;
29
-
30
-	/**
31
-	 * A {@link Wordlift_Log_Service} instance.
32
-	 *
33
-	 * @since 3.15.3
34
-	 *
35
-	 * @var Wordlift_Log_Service $log A {@link Wordlift_Log_Service} instance.
36
-	 */
37
-	private static $log;
38
-
39
-	/**
40
-	 * Create a {@link Wordlift_Relation_Service} instance.
41
-	 *
42
-	 * @since 3.15.0
43
-	 */
44
-	protected function __construct() {
45
-		global $wpdb;
46
-
47
-		self::$log = Wordlift_Log_Service::get_logger( get_class() );
48
-
49
-		// The relations table.
50
-		$this->relation_table = "{$wpdb->prefix}wl_relation_instances";
51
-
52
-	}
53
-
54
-	/**
55
-	 * The singleton instance.
56
-	 *
57
-	 * @since  3.15.0
58
-	 * @access private
59
-	 * @var Wordlift_Relation_Service $instance The singleton instance.
60
-	 */
61
-	private static $instance = null;
62
-
63
-	/**
64
-	 * Get the singleton instance.
65
-	 *
66
-	 * @return Wordlift_Relation_Service The {@link Wordlift_Relation_Service} singleton instance.
67
-	 * @since  3.15.0
68
-	 * @access public
69
-	 */
70
-	public static function get_instance() {
71
-
72
-		if ( ! isset( self::$instance ) ) {
73
-			self::$instance = new self();
74
-		}
75
-
76
-		return self::$instance;
77
-	}
78
-
79
-	/**
80
-	 * Get the articles referencing the specified entity {@link WP_Post}.
81
-	 *
82
-	 * @param int|array     $object_id The entity {@link WP_Post}'s id.
83
-	 * @param string        $fields The fields to return, 'ids' to only return ids or
84
-	 *                                      '*' to return all fields, by default '*'.
85
-	 * @param null|string   $predicate The predicate (who|what|...), by default all.
86
-	 * @param null|string   $status The status, by default all.
87
-	 * @param array         $excludes An array of ids to exclude from the results.
88
-	 * @param null|int      $limit The maximum number of results, by default
89
-	 *                                    no limit.
90
-	 * @param null|array    $include The {@link WP_Post}s' ids to include.
91
-	 *
92
-	 * @param null | string $order_by
93
-	 *
94
-	 * @param array         $post_types
95
-	 *
96
-	 * @return array|object|null Database query results
97
-	 * @since 3.15.0
98
-	 */
99
-	public function get_article_subjects( $object_id, $fields = '*', $predicate = null, $status = null, $excludes = array(), $limit = null, $include = null, $order_by = null, $post_types = array(), $offset = null ) {
100
-		global $wpdb;
101
-
102
-		// The output fields.
103
-		$actual_fields = self::fields( $fields );
104
-
105
-		self::$log->trace( 'Getting article subjects for object ' . implode( ', ', (array) $object_id ) . '...' );
106
-
107
-		$objects = $this->article_id_to_entity_id( $object_id );
108
-
109
-		// If there are no related objects, return an empty array.
110
-		if ( empty( $objects ) ) {
111
-			self::$log->debug( 'No entities found for object ' . implode( ', ', (array) $object_id ) . '.' );
112
-
113
-			return array();
114
-		}
115
-
116
-		self::$log->debug( count( $objects ) . ' entity id(s) found for object ' . implode( ', ', (array) $object_id ) . '.' );
117
-
118
-		$sql =
119
-			"
21
+    /**
22
+     * The relation table name in MySQL, set during instantiation.
23
+     *
24
+     * @since  3.15.0
25
+     * @access private
26
+     * @var string $relation_table The relation table name.
27
+     */
28
+    private $relation_table;
29
+
30
+    /**
31
+     * A {@link Wordlift_Log_Service} instance.
32
+     *
33
+     * @since 3.15.3
34
+     *
35
+     * @var Wordlift_Log_Service $log A {@link Wordlift_Log_Service} instance.
36
+     */
37
+    private static $log;
38
+
39
+    /**
40
+     * Create a {@link Wordlift_Relation_Service} instance.
41
+     *
42
+     * @since 3.15.0
43
+     */
44
+    protected function __construct() {
45
+        global $wpdb;
46
+
47
+        self::$log = Wordlift_Log_Service::get_logger( get_class() );
48
+
49
+        // The relations table.
50
+        $this->relation_table = "{$wpdb->prefix}wl_relation_instances";
51
+
52
+    }
53
+
54
+    /**
55
+     * The singleton instance.
56
+     *
57
+     * @since  3.15.0
58
+     * @access private
59
+     * @var Wordlift_Relation_Service $instance The singleton instance.
60
+     */
61
+    private static $instance = null;
62
+
63
+    /**
64
+     * Get the singleton instance.
65
+     *
66
+     * @return Wordlift_Relation_Service The {@link Wordlift_Relation_Service} singleton instance.
67
+     * @since  3.15.0
68
+     * @access public
69
+     */
70
+    public static function get_instance() {
71
+
72
+        if ( ! isset( self::$instance ) ) {
73
+            self::$instance = new self();
74
+        }
75
+
76
+        return self::$instance;
77
+    }
78
+
79
+    /**
80
+     * Get the articles referencing the specified entity {@link WP_Post}.
81
+     *
82
+     * @param int|array     $object_id The entity {@link WP_Post}'s id.
83
+     * @param string        $fields The fields to return, 'ids' to only return ids or
84
+     *                                      '*' to return all fields, by default '*'.
85
+     * @param null|string   $predicate The predicate (who|what|...), by default all.
86
+     * @param null|string   $status The status, by default all.
87
+     * @param array         $excludes An array of ids to exclude from the results.
88
+     * @param null|int      $limit The maximum number of results, by default
89
+     *                                    no limit.
90
+     * @param null|array    $include The {@link WP_Post}s' ids to include.
91
+     *
92
+     * @param null | string $order_by
93
+     *
94
+     * @param array         $post_types
95
+     *
96
+     * @return array|object|null Database query results
97
+     * @since 3.15.0
98
+     */
99
+    public function get_article_subjects( $object_id, $fields = '*', $predicate = null, $status = null, $excludes = array(), $limit = null, $include = null, $order_by = null, $post_types = array(), $offset = null ) {
100
+        global $wpdb;
101
+
102
+        // The output fields.
103
+        $actual_fields = self::fields( $fields );
104
+
105
+        self::$log->trace( 'Getting article subjects for object ' . implode( ', ', (array) $object_id ) . '...' );
106
+
107
+        $objects = $this->article_id_to_entity_id( $object_id );
108
+
109
+        // If there are no related objects, return an empty array.
110
+        if ( empty( $objects ) ) {
111
+            self::$log->debug( 'No entities found for object ' . implode( ', ', (array) $object_id ) . '.' );
112
+
113
+            return array();
114
+        }
115
+
116
+        self::$log->debug( count( $objects ) . ' entity id(s) found for object ' . implode( ', ', (array) $object_id ) . '.' );
117
+
118
+        $sql =
119
+            "
120 120
 			SELECT DISTINCT p.$actual_fields
121 121
 			FROM {$this->relation_table} r
122 122
 			INNER JOIN $wpdb->posts p
123 123
 				ON p.id = r.subject_id
124 124
 			"
125
-			// Add the status clause.
126
-			. self::and_status( $status )
127
-			. self::inner_join_is_article()
128
-			. self::where_object_id( $objects )
129
-			// Since `object_id` can be an article ID we need to exclude it from
130
-			// the results.
131
-			. self::and_article_not_in( array_merge( $excludes, (array) $object_id ) )
132
-			. self::and_article_in( $include )
133
-			. self::and_post_type_in( $post_types )
134
-			. self::and_predicate( $predicate )
135
-			. self::order_by( $order_by )
136
-			. self::limit( $limit )
137
-			. self::offset( $offset );
138
-
139
-		return '*' === $actual_fields ? $wpdb->get_results( $sql ) : $wpdb->get_col( $sql );  // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
140
-	}
141
-
142
-	/**
143
-	 * The `post_type IN` clause.
144
-	 *
145
-	 * @param array $post_types If the post type is not provided then the valid
146
-	 * entity post types are used.
147
-	 *
148
-	 * @return string The `post_type IN` clause.
149
-	 * @since 3.15.3
150
-	 */
151
-	private static function and_post_type_in( $post_types = array() ) {
152
-
153
-		if ( array() === $post_types ) {
154
-			$post_types = Wordlift_Entity_Service::valid_entity_post_types();
155
-		}
156
-
157
-		return " AND p.post_type IN ( '"
158
-			. implode(
159
-				"','",
160
-				array_map( 'esc_sql', $post_types )
161
-			)
162
-			   . "' )";
163
-	}
164
-
165
-	/**
166
-	 * Add the limit clause if specified.
167
-	 *
168
-	 * @param null|int $limit The maximum number of results.
169
-	 *
170
-	 * @return string The limit clause (empty if no limit has been specified).
171
-	 * @since 3.15.0
172
-	 */
173
-	private static function limit( $limit = null ) {
174
-
175
-		if ( null === $limit ) {
176
-			return '';
177
-		}
178
-
179
-		return "LIMIT $limit";
180
-	}
181
-
182
-	/**
183
-	 * Add the OFFSET clause if specified.
184
-	 *
185
-	 * @param null|int $offset The number of results to skip.
186
-	 *
187
-	 * @return string The offset clause (empty if no offset has been specified).
188
-	 * @since 3.35.11
189
-	 */
190
-	private static function offset( $offset = null ) {
191
-
192
-		if ( null === $offset || ! is_numeric( $offset ) ) {
193
-			return '';
194
-		}
195
-
196
-		return " OFFSET $offset";
197
-	}
198
-
199
-	/**
200
-	 * @param $order_by string | null
201
-	 *
202
-	 * @return string
203
-	 */
204
-	private static function order_by( $order_by ) {
205
-		if ( ! $order_by ) {
206
-			return '';
207
-		}
208
-		$order_by         = (string) $order_by;
209
-		$order_by_clauses = array( 'DESC', 'ASC' );
210
-
211
-		if ( in_array( $order_by, $order_by_clauses, true ) ) {
212
-			return " ORDER BY p.post_modified ${order_by} ";
213
-		} else {
214
-			return ' ORDER BY p.post_modified DESC ';
215
-		}
216
-	}
217
-
218
-	/**
219
-	 * Map the provided ids into entities (i.e. return the id if it's an entity
220
-	 * or get the entities if it's a post).
221
-	 *
222
-	 * @param int|array $object_id An array of posts/entities' ids.
223
-	 *
224
-	 * @return array An array of entities' ids.
225
-	 * @since 3.15.0
226
-	 */
227
-	private function article_id_to_entity_id( $object_id ) {
228
-
229
-		$entity_service = Wordlift_Entity_Service::get_instance();
230
-
231
-		$relation_service = $this;
232
-
233
-		return array_reduce(
234
-			(array) $object_id,
235
-			function ( $carry, $item ) use ( $entity_service, $relation_service ) {
236
-				if ( $entity_service->is_entity( $item ) ) {
237
-					return array_merge( $carry, (array) $item );
238
-				}
239
-
240
-				return array_merge( $carry, $relation_service->get_objects( $item, 'ids' ) );
241
-			},
242
-			array()
243
-		);
244
-
245
-	}
246
-
247
-	/**
248
-	 * Add the WHERE clause.
249
-	 *
250
-	 * @param int|array $object_id An array of {@link WP_Post}s' ids.
251
-	 *
252
-	 * @return string The WHERE clause.
253
-	 * @since 3.15.0
254
-	 */
255
-	private static function where_object_id( $object_id ) {
256
-
257
-		if ( empty( $object_id ) ) {
258
-			// self::$log->warn( sprintf( "%s `where_object_id` called with empty `object_id`.", var_export( debug_backtrace( false, 3 ), true ) ) );
259
-
260
-			return ' WHERE 1 = 1';
261
-		}
262
-
263
-		return ' WHERE r.object_id IN ( ' . implode( ',', wp_parse_id_list( (array) $object_id ) ) . ' )';
264
-	}
265
-
266
-	/**
267
-	 * Add the exclude clause.
268
-	 *
269
-	 * @param int|array $exclude An array of {@link WP_Post}s' ids to exclude.
270
-	 *
271
-	 * @return string The exclude clause.
272
-	 * @since 3.15.0
273
-	 */
274
-	private static function and_article_not_in( $exclude ) {
275
-
276
-		return ' AND NOT p.ID IN ( ' . implode( ',', wp_parse_id_list( (array) $exclude ) ) . ' )';
277
-	}
278
-
279
-	/**
280
-	 * Add the include clause.
281
-	 *
282
-	 * @param null|int|array $include An array of {@link WP_Post}s' ids.
283
-	 *
284
-	 * @return string An empty string if $include is null otherwise the include
285
-	 *                clause.
286
-	 * @since 3.15.0
287
-	 */
288
-	private static function and_article_in( $include = null ) {
289
-
290
-		if ( null === $include ) {
291
-			return '';
292
-		}
293
-
294
-		return ' AND p.ID IN ( ' . implode( ',', wp_parse_id_list( (array) $include ) ) . ' )';
295
-	}
296
-
297
-	/**
298
-	 * Get the entities' {@link WP_Post}s' ids referencing the specified {@link WP_Post}.
299
-	 *
300
-	 * @param int         $object_id The object {@link WP_Post}'s id.
301
-	 * @param string      $fields The fields to return, 'ids' to only return ids or
302
-	 *                                    '*' to return all fields, by default '*'.
303
-	 * @param null|string $status The status, by default all.
304
-	 *
305
-	 * @return array|object|null Database query results
306
-	 * @since 3.15.0
307
-	 */
308
-	public function get_non_article_subjects( $object_id, $fields = '*', $status = null ) {
309
-		global $wpdb;
310
-
311
-		// The output fields.
312
-		$actual_fields = self::fields( $fields );
313
-
314
-		$sql = $wpdb->prepare(
315
-			"SELECT p.$actual_fields FROM {$wpdb->prefix}wl_relation_instances r INNER JOIN $wpdb->posts p ON p.id = r.subject_id" // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
316
-			// Add the status clause.
317
-			. self::and_status( $status ) // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
318
-			. self::inner_join_is_not_article() // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
319
-			. ' WHERE r.object_id = %d '
320
-			. self::and_post_type_in(), // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
321
-			$object_id
322
-		);
323
-
324
-		return '*' === $actual_fields ? $wpdb->get_results( $sql ) : $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
325
-	}
326
-
327
-	/**
328
-	 * Get the entities referenced by the specified {@link WP_Post}.
329
-	 *
330
-	 * @param int         $subject_id The {@link WP_Post}'s id.
331
-	 * @param string      $fields The fields to return, 'ids' to only return ids or
332
-	 *                                     '*' to return all fields, by default '*'.
333
-	 * @param null|string $predicate The predicate (who|what|...), by default all.
334
-	 * @param null|string $status The status, by default all.
335
-	 *
336
-	 * @return array|object|null Database query results
337
-	 * @since 3.15.0
338
-	 */
339
-	public function get_objects( $subject_id, $fields = '*', $predicate = null, $status = null ) {
340
-		global $wpdb;
341
-
342
-		// The output fields.
343
-		$actual_fields = self::fields( $fields );
344
-
345
-		$sql = $wpdb->prepare(
346
-			"SELECT p.$actual_fields FROM {$this->relation_table} r INNER JOIN $wpdb->posts p ON p.id = r.object_id" // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
347
-			// Add the status clause.
348
-			. self::and_status( $status ) // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
349
-			. self::inner_join_is_not_article() // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
350
-			. ' WHERE r.subject_id = %d '
351
-			. self::and_post_type_in() // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
352
-			. self::and_predicate( $predicate ), // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
353
-			$subject_id
354
-		);
355
-
356
-		return '*' === $actual_fields ? $wpdb->get_results( $sql ) : $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
357
-	}
358
-
359
-	/**
360
-	 * Add the `post_status` clause.
361
-	 *
362
-	 * @param null|string|array $status The status values.
363
-	 *
364
-	 * @return string An empty string if $status is null, otherwise the status clause.
365
-	 * @since 3.15.0
366
-	 */
367
-	private static function and_status( $status = null ) {
368
-
369
-		if ( null === $status ) {
370
-			return '';
371
-		}
372
-
373
-		return " AND p.post_status IN ('" . implode( "', '", array_map( 'esc_sql', (array) $status ) ) . "')";
374
-	}
375
-
376
-	/**
377
-	 * Add the `predicate` clause.
378
-	 *
379
-	 * @param null|string|array $predicate An array of predicates.
380
-	 *
381
-	 * @return string An empty string if $predicate is null otherwise the predicate
382
-	 *                clause.
383
-	 * @since 3.15.0
384
-	 */
385
-	private static function and_predicate( $predicate = null ) {
386
-
387
-		if ( null === $predicate ) {
388
-			return '';
389
-		}
390
-
391
-		return " AND r.predicate IN ('" . implode( "', '", array_map( 'esc_sql', (array) $predicate ) ) . "')";
392
-	}
393
-
394
-	/**
395
-	 * The select fields.
396
-	 *
397
-	 * @param string $fields Either 'ids' or '*', by default '*'.
398
-	 *
399
-	 * @return string The `id` field if `ids` otherwise `*`.
400
-	 * @since 3.15.0
401
-	 */
402
-	private static function fields( $fields = '*' ) {
403
-
404
-		// The output fields.
405
-		return 'ids' === $fields ? 'id' : '*';
406
-	}
407
-
408
-	/**
409
-	 * The inner join clause for articles.
410
-	 *
411
-	 * @return string The articles inner join clause.
412
-	 * @since 3.15.0
413
-	 */
414
-	private static function inner_join_is_article() {
415
-		global $wpdb;
416
-
417
-		return $wpdb->prepare(
418
-			"
125
+            // Add the status clause.
126
+            . self::and_status( $status )
127
+            . self::inner_join_is_article()
128
+            . self::where_object_id( $objects )
129
+            // Since `object_id` can be an article ID we need to exclude it from
130
+            // the results.
131
+            . self::and_article_not_in( array_merge( $excludes, (array) $object_id ) )
132
+            . self::and_article_in( $include )
133
+            . self::and_post_type_in( $post_types )
134
+            . self::and_predicate( $predicate )
135
+            . self::order_by( $order_by )
136
+            . self::limit( $limit )
137
+            . self::offset( $offset );
138
+
139
+        return '*' === $actual_fields ? $wpdb->get_results( $sql ) : $wpdb->get_col( $sql );  // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
140
+    }
141
+
142
+    /**
143
+     * The `post_type IN` clause.
144
+     *
145
+     * @param array $post_types If the post type is not provided then the valid
146
+     * entity post types are used.
147
+     *
148
+     * @return string The `post_type IN` clause.
149
+     * @since 3.15.3
150
+     */
151
+    private static function and_post_type_in( $post_types = array() ) {
152
+
153
+        if ( array() === $post_types ) {
154
+            $post_types = Wordlift_Entity_Service::valid_entity_post_types();
155
+        }
156
+
157
+        return " AND p.post_type IN ( '"
158
+            . implode(
159
+                "','",
160
+                array_map( 'esc_sql', $post_types )
161
+            )
162
+                . "' )";
163
+    }
164
+
165
+    /**
166
+     * Add the limit clause if specified.
167
+     *
168
+     * @param null|int $limit The maximum number of results.
169
+     *
170
+     * @return string The limit clause (empty if no limit has been specified).
171
+     * @since 3.15.0
172
+     */
173
+    private static function limit( $limit = null ) {
174
+
175
+        if ( null === $limit ) {
176
+            return '';
177
+        }
178
+
179
+        return "LIMIT $limit";
180
+    }
181
+
182
+    /**
183
+     * Add the OFFSET clause if specified.
184
+     *
185
+     * @param null|int $offset The number of results to skip.
186
+     *
187
+     * @return string The offset clause (empty if no offset has been specified).
188
+     * @since 3.35.11
189
+     */
190
+    private static function offset( $offset = null ) {
191
+
192
+        if ( null === $offset || ! is_numeric( $offset ) ) {
193
+            return '';
194
+        }
195
+
196
+        return " OFFSET $offset";
197
+    }
198
+
199
+    /**
200
+     * @param $order_by string | null
201
+     *
202
+     * @return string
203
+     */
204
+    private static function order_by( $order_by ) {
205
+        if ( ! $order_by ) {
206
+            return '';
207
+        }
208
+        $order_by         = (string) $order_by;
209
+        $order_by_clauses = array( 'DESC', 'ASC' );
210
+
211
+        if ( in_array( $order_by, $order_by_clauses, true ) ) {
212
+            return " ORDER BY p.post_modified ${order_by} ";
213
+        } else {
214
+            return ' ORDER BY p.post_modified DESC ';
215
+        }
216
+    }
217
+
218
+    /**
219
+     * Map the provided ids into entities (i.e. return the id if it's an entity
220
+     * or get the entities if it's a post).
221
+     *
222
+     * @param int|array $object_id An array of posts/entities' ids.
223
+     *
224
+     * @return array An array of entities' ids.
225
+     * @since 3.15.0
226
+     */
227
+    private function article_id_to_entity_id( $object_id ) {
228
+
229
+        $entity_service = Wordlift_Entity_Service::get_instance();
230
+
231
+        $relation_service = $this;
232
+
233
+        return array_reduce(
234
+            (array) $object_id,
235
+            function ( $carry, $item ) use ( $entity_service, $relation_service ) {
236
+                if ( $entity_service->is_entity( $item ) ) {
237
+                    return array_merge( $carry, (array) $item );
238
+                }
239
+
240
+                return array_merge( $carry, $relation_service->get_objects( $item, 'ids' ) );
241
+            },
242
+            array()
243
+        );
244
+
245
+    }
246
+
247
+    /**
248
+     * Add the WHERE clause.
249
+     *
250
+     * @param int|array $object_id An array of {@link WP_Post}s' ids.
251
+     *
252
+     * @return string The WHERE clause.
253
+     * @since 3.15.0
254
+     */
255
+    private static function where_object_id( $object_id ) {
256
+
257
+        if ( empty( $object_id ) ) {
258
+            // self::$log->warn( sprintf( "%s `where_object_id` called with empty `object_id`.", var_export( debug_backtrace( false, 3 ), true ) ) );
259
+
260
+            return ' WHERE 1 = 1';
261
+        }
262
+
263
+        return ' WHERE r.object_id IN ( ' . implode( ',', wp_parse_id_list( (array) $object_id ) ) . ' )';
264
+    }
265
+
266
+    /**
267
+     * Add the exclude clause.
268
+     *
269
+     * @param int|array $exclude An array of {@link WP_Post}s' ids to exclude.
270
+     *
271
+     * @return string The exclude clause.
272
+     * @since 3.15.0
273
+     */
274
+    private static function and_article_not_in( $exclude ) {
275
+
276
+        return ' AND NOT p.ID IN ( ' . implode( ',', wp_parse_id_list( (array) $exclude ) ) . ' )';
277
+    }
278
+
279
+    /**
280
+     * Add the include clause.
281
+     *
282
+     * @param null|int|array $include An array of {@link WP_Post}s' ids.
283
+     *
284
+     * @return string An empty string if $include is null otherwise the include
285
+     *                clause.
286
+     * @since 3.15.0
287
+     */
288
+    private static function and_article_in( $include = null ) {
289
+
290
+        if ( null === $include ) {
291
+            return '';
292
+        }
293
+
294
+        return ' AND p.ID IN ( ' . implode( ',', wp_parse_id_list( (array) $include ) ) . ' )';
295
+    }
296
+
297
+    /**
298
+     * Get the entities' {@link WP_Post}s' ids referencing the specified {@link WP_Post}.
299
+     *
300
+     * @param int         $object_id The object {@link WP_Post}'s id.
301
+     * @param string      $fields The fields to return, 'ids' to only return ids or
302
+     *                                    '*' to return all fields, by default '*'.
303
+     * @param null|string $status The status, by default all.
304
+     *
305
+     * @return array|object|null Database query results
306
+     * @since 3.15.0
307
+     */
308
+    public function get_non_article_subjects( $object_id, $fields = '*', $status = null ) {
309
+        global $wpdb;
310
+
311
+        // The output fields.
312
+        $actual_fields = self::fields( $fields );
313
+
314
+        $sql = $wpdb->prepare(
315
+            "SELECT p.$actual_fields FROM {$wpdb->prefix}wl_relation_instances r INNER JOIN $wpdb->posts p ON p.id = r.subject_id" // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
316
+            // Add the status clause.
317
+            . self::and_status( $status ) // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
318
+            . self::inner_join_is_not_article() // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
319
+            . ' WHERE r.object_id = %d '
320
+            . self::and_post_type_in(), // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
321
+            $object_id
322
+        );
323
+
324
+        return '*' === $actual_fields ? $wpdb->get_results( $sql ) : $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
325
+    }
326
+
327
+    /**
328
+     * Get the entities referenced by the specified {@link WP_Post}.
329
+     *
330
+     * @param int         $subject_id The {@link WP_Post}'s id.
331
+     * @param string      $fields The fields to return, 'ids' to only return ids or
332
+     *                                     '*' to return all fields, by default '*'.
333
+     * @param null|string $predicate The predicate (who|what|...), by default all.
334
+     * @param null|string $status The status, by default all.
335
+     *
336
+     * @return array|object|null Database query results
337
+     * @since 3.15.0
338
+     */
339
+    public function get_objects( $subject_id, $fields = '*', $predicate = null, $status = null ) {
340
+        global $wpdb;
341
+
342
+        // The output fields.
343
+        $actual_fields = self::fields( $fields );
344
+
345
+        $sql = $wpdb->prepare(
346
+            "SELECT p.$actual_fields FROM {$this->relation_table} r INNER JOIN $wpdb->posts p ON p.id = r.object_id" // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
347
+            // Add the status clause.
348
+            . self::and_status( $status ) // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
349
+            . self::inner_join_is_not_article() // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
350
+            . ' WHERE r.subject_id = %d '
351
+            . self::and_post_type_in() // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
352
+            . self::and_predicate( $predicate ), // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
353
+            $subject_id
354
+        );
355
+
356
+        return '*' === $actual_fields ? $wpdb->get_results( $sql ) : $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
357
+    }
358
+
359
+    /**
360
+     * Add the `post_status` clause.
361
+     *
362
+     * @param null|string|array $status The status values.
363
+     *
364
+     * @return string An empty string if $status is null, otherwise the status clause.
365
+     * @since 3.15.0
366
+     */
367
+    private static function and_status( $status = null ) {
368
+
369
+        if ( null === $status ) {
370
+            return '';
371
+        }
372
+
373
+        return " AND p.post_status IN ('" . implode( "', '", array_map( 'esc_sql', (array) $status ) ) . "')";
374
+    }
375
+
376
+    /**
377
+     * Add the `predicate` clause.
378
+     *
379
+     * @param null|string|array $predicate An array of predicates.
380
+     *
381
+     * @return string An empty string if $predicate is null otherwise the predicate
382
+     *                clause.
383
+     * @since 3.15.0
384
+     */
385
+    private static function and_predicate( $predicate = null ) {
386
+
387
+        if ( null === $predicate ) {
388
+            return '';
389
+        }
390
+
391
+        return " AND r.predicate IN ('" . implode( "', '", array_map( 'esc_sql', (array) $predicate ) ) . "')";
392
+    }
393
+
394
+    /**
395
+     * The select fields.
396
+     *
397
+     * @param string $fields Either 'ids' or '*', by default '*'.
398
+     *
399
+     * @return string The `id` field if `ids` otherwise `*`.
400
+     * @since 3.15.0
401
+     */
402
+    private static function fields( $fields = '*' ) {
403
+
404
+        // The output fields.
405
+        return 'ids' === $fields ? 'id' : '*';
406
+    }
407
+
408
+    /**
409
+     * The inner join clause for articles.
410
+     *
411
+     * @return string The articles inner join clause.
412
+     * @since 3.15.0
413
+     */
414
+    private static function inner_join_is_article() {
415
+        global $wpdb;
416
+
417
+        return $wpdb->prepare(
418
+            "
419 419
 			INNER JOIN $wpdb->term_relationships tr
420 420
 			 ON p.id = tr.object_id
421 421
 			INNER JOIN $wpdb->term_taxonomy tt
@@ -425,22 +425,22 @@  discard block
 block discarded – undo
425 425
 			 ON t.term_id = tt.term_id
426 426
 			  AND t.slug = %s
427 427
 			",
428
-			'wl_entity_type',
429
-			'article'
430
-		);
431
-	}
432
-
433
-	/**
434
-	 * The inner join clause for non-articles.
435
-	 *
436
-	 * @return string The non-articles inner join clause.
437
-	 * @since 3.15.0
438
-	 */
439
-	private static function inner_join_is_not_article() {
440
-		global $wpdb;
441
-
442
-		return $wpdb->prepare(
443
-			"
428
+            'wl_entity_type',
429
+            'article'
430
+        );
431
+    }
432
+
433
+    /**
434
+     * The inner join clause for non-articles.
435
+     *
436
+     * @return string The non-articles inner join clause.
437
+     * @since 3.15.0
438
+     */
439
+    private static function inner_join_is_not_article() {
440
+        global $wpdb;
441
+
442
+        return $wpdb->prepare(
443
+            "
444 444
 			INNER JOIN $wpdb->term_relationships tr
445 445
 			 ON p.id = tr.object_id
446 446
 			INNER JOIN $wpdb->term_taxonomy tt
@@ -450,29 +450,29 @@  discard block
 block discarded – undo
450 450
 			 ON t.term_id = tt.term_id
451 451
 			  AND NOT t.slug = %s
452 452
 			",
453
-			'wl_entity_type',
454
-			'article'
455
-		);
456
-	}
457
-
458
-	/**
459
-	 * Find all the subject IDs and their referenced/related object IDs. The
460
-	 * object IDs are returned as comma separated IDs in the `object_ids` key.
461
-	 *
462
-	 * @return mixed Database query results
463
-	 * @since 3.18.0
464
-	 */
465
-	public function find_all_grouped_by_subject_id() {
466
-		global $wpdb;
467
-
468
-		return $wpdb->get_results(
469
-			"
453
+            'wl_entity_type',
454
+            'article'
455
+        );
456
+    }
457
+
458
+    /**
459
+     * Find all the subject IDs and their referenced/related object IDs. The
460
+     * object IDs are returned as comma separated IDs in the `object_ids` key.
461
+     *
462
+     * @return mixed Database query results
463
+     * @since 3.18.0
464
+     */
465
+    public function find_all_grouped_by_subject_id() {
466
+        global $wpdb;
467
+
468
+        return $wpdb->get_results(
469
+            "
470 470
 			SELECT subject_id, GROUP_CONCAT( DISTINCT object_id ORDER BY object_id SEPARATOR ',' ) AS object_ids
471 471
 			FROM {$wpdb->prefix}wl_relation_instances
472 472
 			GROUP BY subject_id
473 473
 			"
474
-		);
474
+        );
475 475
 
476
-	}
476
+    }
477 477
 
478 478
 }
Please login to merge, or discard this patch.
Spacing   +60 added lines, -60 removed lines patch added patch discarded remove patch
@@ -44,7 +44,7 @@  discard block
 block discarded – undo
44 44
 	protected function __construct() {
45 45
 		global $wpdb;
46 46
 
47
-		self::$log = Wordlift_Log_Service::get_logger( get_class() );
47
+		self::$log = Wordlift_Log_Service::get_logger(get_class());
48 48
 
49 49
 		// The relations table.
50 50
 		$this->relation_table = "{$wpdb->prefix}wl_relation_instances";
@@ -69,7 +69,7 @@  discard block
 block discarded – undo
69 69
 	 */
70 70
 	public static function get_instance() {
71 71
 
72
-		if ( ! isset( self::$instance ) ) {
72
+		if ( ! isset(self::$instance)) {
73 73
 			self::$instance = new self();
74 74
 		}
75 75
 
@@ -96,24 +96,24 @@  discard block
 block discarded – undo
96 96
 	 * @return array|object|null Database query results
97 97
 	 * @since 3.15.0
98 98
 	 */
99
-	public function get_article_subjects( $object_id, $fields = '*', $predicate = null, $status = null, $excludes = array(), $limit = null, $include = null, $order_by = null, $post_types = array(), $offset = null ) {
99
+	public function get_article_subjects($object_id, $fields = '*', $predicate = null, $status = null, $excludes = array(), $limit = null, $include = null, $order_by = null, $post_types = array(), $offset = null) {
100 100
 		global $wpdb;
101 101
 
102 102
 		// The output fields.
103
-		$actual_fields = self::fields( $fields );
103
+		$actual_fields = self::fields($fields);
104 104
 
105
-		self::$log->trace( 'Getting article subjects for object ' . implode( ', ', (array) $object_id ) . '...' );
105
+		self::$log->trace('Getting article subjects for object '.implode(', ', (array) $object_id).'...');
106 106
 
107
-		$objects = $this->article_id_to_entity_id( $object_id );
107
+		$objects = $this->article_id_to_entity_id($object_id);
108 108
 
109 109
 		// If there are no related objects, return an empty array.
110
-		if ( empty( $objects ) ) {
111
-			self::$log->debug( 'No entities found for object ' . implode( ', ', (array) $object_id ) . '.' );
110
+		if (empty($objects)) {
111
+			self::$log->debug('No entities found for object '.implode(', ', (array) $object_id).'.');
112 112
 
113 113
 			return array();
114 114
 		}
115 115
 
116
-		self::$log->debug( count( $objects ) . ' entity id(s) found for object ' . implode( ', ', (array) $object_id ) . '.' );
116
+		self::$log->debug(count($objects).' entity id(s) found for object '.implode(', ', (array) $object_id).'.');
117 117
 
118 118
 		$sql =
119 119
 			"
@@ -123,20 +123,20 @@  discard block
 block discarded – undo
123 123
 				ON p.id = r.subject_id
124 124
 			"
125 125
 			// Add the status clause.
126
-			. self::and_status( $status )
126
+			. self::and_status($status)
127 127
 			. self::inner_join_is_article()
128
-			. self::where_object_id( $objects )
128
+			. self::where_object_id($objects)
129 129
 			// Since `object_id` can be an article ID we need to exclude it from
130 130
 			// the results.
131
-			. self::and_article_not_in( array_merge( $excludes, (array) $object_id ) )
132
-			. self::and_article_in( $include )
133
-			. self::and_post_type_in( $post_types )
134
-			. self::and_predicate( $predicate )
135
-			. self::order_by( $order_by )
136
-			. self::limit( $limit )
137
-			. self::offset( $offset );
138
-
139
-		return '*' === $actual_fields ? $wpdb->get_results( $sql ) : $wpdb->get_col( $sql );  // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
131
+			. self::and_article_not_in(array_merge($excludes, (array) $object_id))
132
+			. self::and_article_in($include)
133
+			. self::and_post_type_in($post_types)
134
+			. self::and_predicate($predicate)
135
+			. self::order_by($order_by)
136
+			. self::limit($limit)
137
+			. self::offset($offset);
138
+
139
+		return '*' === $actual_fields ? $wpdb->get_results($sql) : $wpdb->get_col($sql); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
140 140
 	}
141 141
 
142 142
 	/**
@@ -148,16 +148,16 @@  discard block
 block discarded – undo
148 148
 	 * @return string The `post_type IN` clause.
149 149
 	 * @since 3.15.3
150 150
 	 */
151
-	private static function and_post_type_in( $post_types = array() ) {
151
+	private static function and_post_type_in($post_types = array()) {
152 152
 
153
-		if ( array() === $post_types ) {
153
+		if (array() === $post_types) {
154 154
 			$post_types = Wordlift_Entity_Service::valid_entity_post_types();
155 155
 		}
156 156
 
157 157
 		return " AND p.post_type IN ( '"
158 158
 			. implode(
159 159
 				"','",
160
-				array_map( 'esc_sql', $post_types )
160
+				array_map('esc_sql', $post_types)
161 161
 			)
162 162
 			   . "' )";
163 163
 	}
@@ -170,9 +170,9 @@  discard block
 block discarded – undo
170 170
 	 * @return string The limit clause (empty if no limit has been specified).
171 171
 	 * @since 3.15.0
172 172
 	 */
173
-	private static function limit( $limit = null ) {
173
+	private static function limit($limit = null) {
174 174
 
175
-		if ( null === $limit ) {
175
+		if (null === $limit) {
176 176
 			return '';
177 177
 		}
178 178
 
@@ -187,9 +187,9 @@  discard block
 block discarded – undo
187 187
 	 * @return string The offset clause (empty if no offset has been specified).
188 188
 	 * @since 3.35.11
189 189
 	 */
190
-	private static function offset( $offset = null ) {
190
+	private static function offset($offset = null) {
191 191
 
192
-		if ( null === $offset || ! is_numeric( $offset ) ) {
192
+		if (null === $offset || ! is_numeric($offset)) {
193 193
 			return '';
194 194
 		}
195 195
 
@@ -201,14 +201,14 @@  discard block
 block discarded – undo
201 201
 	 *
202 202
 	 * @return string
203 203
 	 */
204
-	private static function order_by( $order_by ) {
205
-		if ( ! $order_by ) {
204
+	private static function order_by($order_by) {
205
+		if ( ! $order_by) {
206 206
 			return '';
207 207
 		}
208 208
 		$order_by         = (string) $order_by;
209
-		$order_by_clauses = array( 'DESC', 'ASC' );
209
+		$order_by_clauses = array('DESC', 'ASC');
210 210
 
211
-		if ( in_array( $order_by, $order_by_clauses, true ) ) {
211
+		if (in_array($order_by, $order_by_clauses, true)) {
212 212
 			return " ORDER BY p.post_modified ${order_by} ";
213 213
 		} else {
214 214
 			return ' ORDER BY p.post_modified DESC ';
@@ -224,7 +224,7 @@  discard block
 block discarded – undo
224 224
 	 * @return array An array of entities' ids.
225 225
 	 * @since 3.15.0
226 226
 	 */
227
-	private function article_id_to_entity_id( $object_id ) {
227
+	private function article_id_to_entity_id($object_id) {
228 228
 
229 229
 		$entity_service = Wordlift_Entity_Service::get_instance();
230 230
 
@@ -232,12 +232,12 @@  discard block
 block discarded – undo
232 232
 
233 233
 		return array_reduce(
234 234
 			(array) $object_id,
235
-			function ( $carry, $item ) use ( $entity_service, $relation_service ) {
236
-				if ( $entity_service->is_entity( $item ) ) {
237
-					return array_merge( $carry, (array) $item );
235
+			function($carry, $item) use ($entity_service, $relation_service) {
236
+				if ($entity_service->is_entity($item)) {
237
+					return array_merge($carry, (array) $item);
238 238
 				}
239 239
 
240
-				return array_merge( $carry, $relation_service->get_objects( $item, 'ids' ) );
240
+				return array_merge($carry, $relation_service->get_objects($item, 'ids'));
241 241
 			},
242 242
 			array()
243 243
 		);
@@ -252,15 +252,15 @@  discard block
 block discarded – undo
252 252
 	 * @return string The WHERE clause.
253 253
 	 * @since 3.15.0
254 254
 	 */
255
-	private static function where_object_id( $object_id ) {
255
+	private static function where_object_id($object_id) {
256 256
 
257
-		if ( empty( $object_id ) ) {
257
+		if (empty($object_id)) {
258 258
 			// self::$log->warn( sprintf( "%s `where_object_id` called with empty `object_id`.", var_export( debug_backtrace( false, 3 ), true ) ) );
259 259
 
260 260
 			return ' WHERE 1 = 1';
261 261
 		}
262 262
 
263
-		return ' WHERE r.object_id IN ( ' . implode( ',', wp_parse_id_list( (array) $object_id ) ) . ' )';
263
+		return ' WHERE r.object_id IN ( '.implode(',', wp_parse_id_list((array) $object_id)).' )';
264 264
 	}
265 265
 
266 266
 	/**
@@ -271,9 +271,9 @@  discard block
 block discarded – undo
271 271
 	 * @return string The exclude clause.
272 272
 	 * @since 3.15.0
273 273
 	 */
274
-	private static function and_article_not_in( $exclude ) {
274
+	private static function and_article_not_in($exclude) {
275 275
 
276
-		return ' AND NOT p.ID IN ( ' . implode( ',', wp_parse_id_list( (array) $exclude ) ) . ' )';
276
+		return ' AND NOT p.ID IN ( '.implode(',', wp_parse_id_list((array) $exclude)).' )';
277 277
 	}
278 278
 
279 279
 	/**
@@ -285,13 +285,13 @@  discard block
 block discarded – undo
285 285
 	 *                clause.
286 286
 	 * @since 3.15.0
287 287
 	 */
288
-	private static function and_article_in( $include = null ) {
288
+	private static function and_article_in($include = null) {
289 289
 
290
-		if ( null === $include ) {
290
+		if (null === $include) {
291 291
 			return '';
292 292
 		}
293 293
 
294
-		return ' AND p.ID IN ( ' . implode( ',', wp_parse_id_list( (array) $include ) ) . ' )';
294
+		return ' AND p.ID IN ( '.implode(',', wp_parse_id_list((array) $include)).' )';
295 295
 	}
296 296
 
297 297
 	/**
@@ -305,23 +305,23 @@  discard block
 block discarded – undo
305 305
 	 * @return array|object|null Database query results
306 306
 	 * @since 3.15.0
307 307
 	 */
308
-	public function get_non_article_subjects( $object_id, $fields = '*', $status = null ) {
308
+	public function get_non_article_subjects($object_id, $fields = '*', $status = null) {
309 309
 		global $wpdb;
310 310
 
311 311
 		// The output fields.
312
-		$actual_fields = self::fields( $fields );
312
+		$actual_fields = self::fields($fields);
313 313
 
314 314
 		$sql = $wpdb->prepare(
315 315
 			"SELECT p.$actual_fields FROM {$wpdb->prefix}wl_relation_instances r INNER JOIN $wpdb->posts p ON p.id = r.subject_id" // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
316 316
 			// Add the status clause.
317
-			. self::and_status( $status ) // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
317
+			. self::and_status($status) // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
318 318
 			. self::inner_join_is_not_article() // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
319 319
 			. ' WHERE r.object_id = %d '
320 320
 			. self::and_post_type_in(), // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
321 321
 			$object_id
322 322
 		);
323 323
 
324
-		return '*' === $actual_fields ? $wpdb->get_results( $sql ) : $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
324
+		return '*' === $actual_fields ? $wpdb->get_results($sql) : $wpdb->get_col($sql); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
325 325
 	}
326 326
 
327 327
 	/**
@@ -336,24 +336,24 @@  discard block
 block discarded – undo
336 336
 	 * @return array|object|null Database query results
337 337
 	 * @since 3.15.0
338 338
 	 */
339
-	public function get_objects( $subject_id, $fields = '*', $predicate = null, $status = null ) {
339
+	public function get_objects($subject_id, $fields = '*', $predicate = null, $status = null) {
340 340
 		global $wpdb;
341 341
 
342 342
 		// The output fields.
343
-		$actual_fields = self::fields( $fields );
343
+		$actual_fields = self::fields($fields);
344 344
 
345 345
 		$sql = $wpdb->prepare(
346 346
 			"SELECT p.$actual_fields FROM {$this->relation_table} r INNER JOIN $wpdb->posts p ON p.id = r.object_id" // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
347 347
 			// Add the status clause.
348
-			. self::and_status( $status ) // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
348
+			. self::and_status($status) // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
349 349
 			. self::inner_join_is_not_article() // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
350 350
 			. ' WHERE r.subject_id = %d '
351 351
 			. self::and_post_type_in() // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
352
-			. self::and_predicate( $predicate ), // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
352
+			. self::and_predicate($predicate), // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
353 353
 			$subject_id
354 354
 		);
355 355
 
356
-		return '*' === $actual_fields ? $wpdb->get_results( $sql ) : $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
356
+		return '*' === $actual_fields ? $wpdb->get_results($sql) : $wpdb->get_col($sql); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
357 357
 	}
358 358
 
359 359
 	/**
@@ -364,13 +364,13 @@  discard block
 block discarded – undo
364 364
 	 * @return string An empty string if $status is null, otherwise the status clause.
365 365
 	 * @since 3.15.0
366 366
 	 */
367
-	private static function and_status( $status = null ) {
367
+	private static function and_status($status = null) {
368 368
 
369
-		if ( null === $status ) {
369
+		if (null === $status) {
370 370
 			return '';
371 371
 		}
372 372
 
373
-		return " AND p.post_status IN ('" . implode( "', '", array_map( 'esc_sql', (array) $status ) ) . "')";
373
+		return " AND p.post_status IN ('".implode("', '", array_map('esc_sql', (array) $status))."')";
374 374
 	}
375 375
 
376 376
 	/**
@@ -382,13 +382,13 @@  discard block
 block discarded – undo
382 382
 	 *                clause.
383 383
 	 * @since 3.15.0
384 384
 	 */
385
-	private static function and_predicate( $predicate = null ) {
385
+	private static function and_predicate($predicate = null) {
386 386
 
387
-		if ( null === $predicate ) {
387
+		if (null === $predicate) {
388 388
 			return '';
389 389
 		}
390 390
 
391
-		return " AND r.predicate IN ('" . implode( "', '", array_map( 'esc_sql', (array) $predicate ) ) . "')";
391
+		return " AND r.predicate IN ('".implode("', '", array_map('esc_sql', (array) $predicate))."')";
392 392
 	}
393 393
 
394 394
 	/**
@@ -399,7 +399,7 @@  discard block
 block discarded – undo
399 399
 	 * @return string The `id` field if `ids` otherwise `*`.
400 400
 	 * @since 3.15.0
401 401
 	 */
402
-	private static function fields( $fields = '*' ) {
402
+	private static function fields($fields = '*') {
403 403
 
404 404
 		// The output fields.
405 405
 		return 'ids' === $fields ? 'id' : '*';
Please login to merge, or discard this patch.