PluginProbe
Groups – Memberships and Access Control / 4.7.0
Groups – Memberships and Access Control v4.7.0
4.7.1 4.7.0 4.6.0 4.5.0 4.4.0 4.3.0 trunk 1.0.0-beta-1 1.0.0-beta-2 1.0.0-beta-3 1.0.0-beta-3b 1.0.0-beta-3c 1.0.0-beta-3d 1.1.4 1.1.5 1.10.0 1.10.1 1.10.2 1.10.3 1.11.0 1.11.1 1.11.2 1.11.3 1.12.0 1.13.0 All 131 releases
← All changes | lib/core/class-groups-group.php +672 -139 1.11.34.7.0 View file →
@@ -22,33 +22,305 @@
22 22 if ( !defined( 'ABSPATH' ) ) {
23 23 exit;
24 24 }
25 25
26 -require_once( GROUPS_CORE_LIB . "/interface-i-capable.php" );
26 +// phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
27 27
28 +require_once GROUPS_CORE_LIB . '/interface-i-capable.php';
29 +
28 30 /**
29 31 * Group OPM.
30 32 */
31 33 class Groups_Group implements I_Capable {
32 34
33 - const CACHE_GROUP = 'groups';
35 + /**
36 + * @var string cache group
37 + */
38 + const CACHE_GROUP = 'groups';
39 +
40 + /**
41 + * @var string key
42 + *
43 + * @deprecated since 4.3.0
44 + */
45 + const READ_GROUP_BY_ID = 'read_group_by_id';
46 +
47 + /**
48 + * @var string key
49 + *
50 + * @deprecated since 4.3.0
51 + */
34 52 const READ_BY_NAME = 'read_by_name';
35 53
36 54 /**
55 + * @var string key
56 + */
57 + const ID_MAP = 'map_group_by_id';
58 +
59 + /**
60 + * @var string key
61 + */
62 + const NAME_MAP = 'map_group_by_name';
63 +
64 + /**
65 + * @var int map limit
66 + */
67 + const MAX_MAP = 10000;
68 +
69 + /**
70 + * Lock timeout in microseconds.
71 + *
72 + * @var int
73 + */
74 + const LOCK_TIMEOUT = 30000000;
75 +
76 + /**
77 + * Lock name.
78 + *
79 + * @var string
80 + */
81 + const LOCK = 'groups_group_lock';
82 +
83 + /**
84 + * Mutex lock.
85 + *
86 + * @var Groups_Lock
87 + */
88 + private static $lock = null;
89 +
90 + /**
37 91 * @var Object Persisted group.
92 + *
93 + * @access private - do not access this property directly, the visibility will be made private in the future
38 94 */
39 - var $group = null;
95 + public $group = null;
40 96
41 97 /**
98 + * Lock object.
99 + *
100 + * @throws Groups_Lock_Exception
101 + *
102 + * @return Groups_Lock
103 + */
104 + private static function get_lock() {
105 + $lock = null;
106 + if ( self::$lock !== null ) {
107 + $lock = self::$lock;
108 + } else {
109 + $timeout = apply_filters( 'groups_group_lock_timeout', self::LOCK_TIMEOUT );
110 + if ( is_numeric( $timeout ) ) {
111 + $timeout = max( 0, intval( $timeout ) );
112 + } else {
113 + $timeout = null;
114 + }
115 + $lock = new Groups_Lock( self::LOCK, $timeout );
116 + self::$lock = $lock;
117 + }
118 + return $lock;
119 + }
120 +
121 + /**
122 + * Mutex locked.
123 + *
124 + * @return boolean
125 + */
126 + private static function is_locked() {
127 + return self::$lock !== null && self::$lock->is_locked();
128 + }
129 +
130 + /**
131 + * Mutex reader.
132 + *
133 + * @return boolean
134 + */
135 + private static function reader() {
136 + $locked = false;
137 + try {
138 + $lock = self::get_lock();
139 + $locked = $lock->reader();
140 + } catch ( Groups_Lock_Exception $lex ) {
141 + if ( defined( 'GROUPS_DEBUG' ) && GROUPS_DEBUG ) {
142 + Groups_Log::log(
143 + sprintf(
144 + 'Group read lock fail [%s] [%s]',
145 + self::LOCK,
146 + $lex->getMessage()
147 + )
148 + );
149 + }
150 + }
151 + return $locked;
152 + }
153 +
154 + /**
155 + * Mutex writer.
156 + *
157 + * @return boolean
158 + */
159 + private static function writer() {
160 + $locked = false;
161 + try {
162 + $lock = self::get_lock();
163 + $locked = $lock->writer();
164 + } catch ( Groups_Lock_Exception $lex ) {
165 + if ( defined( 'GROUPS_DEBUG' ) && GROUPS_DEBUG ) {
166 + Groups_Log::log(
167 + sprintf(
168 + 'Group write lock fail [%s] [%s]',
169 + self::LOCK,
170 + $lex->getMessage()
171 + )
172 + );
173 + }
174 + }
175 + return $locked;
176 + }
177 +
178 + /**
179 + * Mutex release.
180 + *
181 + * @return boolean
182 + */
183 + private static function release() {
184 + $released = false;
185 + if ( self::$lock !== null ) {
186 + $released = self::$lock->release();
187 + }
188 + return $released;
189 + }
190 +
191 + /**
42 192 * Create by group id.
193 + *
43 194 * Must have been persisted.
195 + *
44 196 * @param int $group_id
45 197 */
46 198 public function __construct( $group_id ) {
47 199 $this->group = self::read( $group_id );
200 + if ( $this->group === false ) {
201 + $this->group = null;
202 + }
48 203 }
49 204
50 205 /**
206 + * Provides the object ID.
207 + *
208 + * @return int
209 + */
210 + public function get_id() {
211 + return $this->get_group_id();
212 + }
213 +
214 + /**
215 + * Provides the object ID.
216 + *
217 + * @return int
218 + */
219 + public function get_group_id() {
220 + return $this->group_id; // @phpstan-ignore property.notFound
221 + }
222 +
223 + /**
224 + * Provides the parent group's ID.
225 + *
226 + * @return int
227 + */
228 + public function get_parent_id() {
229 + return $this->parent_id; // @phpstan-ignore property.notFound
230 + }
231 +
232 + /**
233 + * Provides the creator's ID.
234 + *
235 + * @return int
236 + */
237 + public function get_creator_id() {
238 + return $this->creator_id; // @phpstan-ignore property.notFound
239 + }
240 +
241 + /**
242 + * Provides the date and time of creation.
243 + *
244 + * @return string
245 + */
246 + public function get_datetime() {
247 + return $this->datetime; // @phpstan-ignore property.notFound
248 + }
249 +
250 + /**
251 + * Provides the group's name.
252 + *
253 + * @return string
254 + */
255 + public function get_name() {
256 + return $this->name; // @phpstan-ignore property.notFound
257 + }
258 +
259 + /**
260 + * Provides the group's description.
261 + *
262 + * @return string
263 + */
264 + public function get_description() {
265 + return $this->description; // @phpstan-ignore property.notFound
266 + }
267 +
268 + /**
269 + * Provides the capabilities of the group.
270 + *
271 + * @return Groups_Capability[]
272 + */
273 + public function get_capabilities() {
274 + return $this->capabilities; // @phpstan-ignore property.notFound
275 + }
276 +
277 + /**
278 + * Provides the IDs of the capabilities of this group.
279 + *
280 + * @return int[]
281 + */
282 + public function get_capability_ids() {
283 + return $this->capability_ids; // @phpstan-ignore property.notFound
284 + }
285 +
286 + /**
287 + * Provides the capabilities of the group and of all its ancestors.
288 + *
289 + * @return Groups_Capability[]
290 + */
291 + public function get_capabilities_deep() {
292 + return $this->capabilities_deep; // @phpstan-ignore property.notFound
293 + }
294 +
295 + /**
296 + * Provides the IDs of the capabilities of this group and of all its ancestors.
297 + *
298 + * @return int[]
299 + */
300 + public function get_capability_ids_deep() {
301 + return $this->capability_ids_deep; // @phpstan-ignore property.notFound
302 + }
303 +
304 + /**
305 + * Provides the members of the group.
306 + *
307 + * @return Groups_User[]
308 + */
309 + public function get_users() {
310 + return $this->users; // @phpstan-ignore property.notFound
311 + }
312 +
313 + /**
314 + * Provides the user IDs of the members of this group.
315 + *
316 + * @return int[]
317 + */
318 + public function get_user_ids() {
319 + return $this->user_ids; // @phpstan-ignore property.notFound
320 + }
321 +
322 + /**
51 323 * Retrieve a property by name.
52 324 *
53 325 * Possible properties:
54 326 * - group_id
@@ -60,61 +332,69 @@
60 332 * - capabilities, returns an array of Groups_Capability
61 333 * - users, returns an array of Groups_User
62 334 *
63 335 * @param string $name property's name
64 - * @return property value, will return null if property does not exist
336 + *
337 + * @return mixed property value, will return null if property does not exist
65 338 */
66 339 public function __get( $name ) {
67 340 global $wpdb;
68 341 $result = null;
69 342 if ( $this->group !== null ) {
70 - switch( $name ) {
71 - case "group_id" :
72 - case "parent_id" :
73 - case "creator_id" :
74 - case "datetime" :
75 - case "name" :
76 - case "description" :
343 + switch ( $name ) {
344 + case 'group_id' :
345 + case 'parent_id' :
346 + case 'creator_id' :
347 + case 'datetime' :
348 + case 'name' :
349 + case 'description' :
77 350 $result = $this->group->$name;
78 351 break;
79 - case "capabilities" :
80 - $group_capability_table = _groups_get_tablename( "group_capability" );
352 + case 'capability_ids' :
353 + $result = array();
354 + $group_capability_table = _groups_get_tablename( 'group_capability' );
81 355 $rows = $wpdb->get_results( $wpdb->prepare(
82 - "SELECT capability_id FROM $group_capability_table WHERE group_id = %d",
356 + "SELECT capability_id FROM $group_capability_table WHERE group_id = %d", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
83 357 Groups_Utility::id( $this->group->group_id )
84 358 ) );
85 359 if ( $rows ) {
86 - $result = array();
87 360 foreach ( $rows as $row ) {
88 - $result[] = new Groups_Capability( $row->capability_id );
361 + $result[] = $row->capability_id;
89 362 }
90 363 }
91 364 break;
365 + case 'capabilities' :
366 + $result = array();
367 + $capability_ids = $this->capability_ids; // @phpstan-ignore property.notFound
368 + foreach ( $capability_ids as $capability_id ) {
369 + $result[] = new Groups_Capability( $capability_id );
370 + }
371 + break;
92 372 case 'capabilities_deep' :
93 - $capability_ids = $this->capability_ids_deep;
94 373 $result = array();
95 - foreach( $capability_ids as $capability_id ) {
374 + $capability_ids = $this->capability_ids_deep; // @phpstan-ignore property.notFound
375 + foreach ( $capability_ids as $capability_id ) {
96 376 $result[] = new Groups_Capability( $capability_id );
97 377 }
98 378 break;
99 379 case 'capability_ids_deep' :
100 380 $capability_ids = array();
101 - $group_table = _groups_get_tablename( "group" );
381 + $group_table = _groups_get_tablename( 'group' );
102 382 $group_capability_table = _groups_get_tablename( "group_capability" );
103 383 // Find this group's and all its parent groups' capabilities.
104 384 $group_ids = array( Groups_Utility::id( $this->group->group_id ) );
105 385 $iterations = 0;
106 386 $old_group_ids_count = 0;
107 - $all_groups = $wpdb->get_var( "SELECT COUNT(*) FROM $group_table" );
387 + $all_groups = $wpdb->get_var( "SELECT COUNT(*) FROM $group_table" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
108 388 while( ( $iterations < $all_groups ) && ( count( $group_ids ) !== $old_group_ids_count ) ) {
109 389 $iterations++;
110 390 $old_group_ids_count = count( $group_ids );
111 - $id_list = implode( ",", $group_ids );
391 + $id_list = implode( ',', $group_ids );
112 392 $parent_group_ids = $wpdb->get_results(
113 - "SELECT parent_id FROM $group_table WHERE parent_id IS NOT NULL AND group_id IN ($id_list)"
393 + "SELECT parent_id FROM $group_table WHERE parent_id IS NOT NULL AND group_id IN ($id_list)" // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
114 394 );
115 395 if ( $parent_group_ids ) {
116 - foreach( $parent_group_ids as $parent_group_id ) {
396 + foreach ( $parent_group_ids as $parent_group_id ) {
117 397 $parent_group_id = Groups_Utility::id( $parent_group_id->parent_id );
118 398 if ( !in_array( $parent_group_id, $group_ids ) ) {
119 399 $group_ids[] = $parent_group_id;
120 400 }
@@ -121,11 +401,11 @@
121 401 }
122 402 }
123 403 }
124 404 if ( count( $group_ids ) > 0 ) {
125 - $id_list = implode( ",", $group_ids );
405 + $id_list = implode( ',', $group_ids );
126 406 $rows = $wpdb->get_results(
127 - "SELECT DISTINCT capability_id FROM $group_capability_table WHERE group_id IN ($id_list)"
407 + "SELECT DISTINCT capability_id FROM $group_capability_table WHERE group_id IN ($id_list)" // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
128 408 );
129 409 if ( $rows ) {
130 410 foreach ( $rows as $row ) {
131 411 $capability_ids[] = $row->capability_id;
@@ -134,20 +414,35 @@
134 414 }
135 415 $result = $capability_ids;
136 416 break;
137 417 case 'users' :
138 - $user_group_table = _groups_get_tablename( "user_group" );
418 + $result = array();
419 + $user_group_table = _groups_get_tablename( 'user_group' );
139 420 $users = $wpdb->get_results( $wpdb->prepare(
140 - "SELECT ID FROM $wpdb->users LEFT JOIN $user_group_table ON $wpdb->users.ID = $user_group_table.user_id WHERE $user_group_table.group_id = %d",
421 + "SELECT $wpdb->users.* FROM $wpdb->users LEFT JOIN $user_group_table ON $wpdb->users.ID = $user_group_table.user_id WHERE $user_group_table.group_id = %d", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
141 422 Groups_Utility::id( $this->group->group_id )
142 423 ) );
143 424 if ( $users ) {
144 - $result = array();
145 - foreach( $users as $user ) {
146 - $result[] = new Groups_User( $user->ID );
425 + foreach ( $users as $user ) {
426 + $groups_user = new Groups_User();
427 + $groups_user->set_user( new WP_User( $user ) );
428 + $result[] = $groups_user;
147 429 }
148 430 }
149 431 break;
432 + case 'user_ids' :
433 + $result = array();
434 + $user_group_table = _groups_get_tablename( 'user_group' );
435 + $user_ids = $wpdb->get_results( $wpdb->prepare(
436 + "SELECT $wpdb->users.ID FROM $wpdb->users LEFT JOIN $user_group_table ON $wpdb->users.ID = $user_group_table.user_id WHERE $user_group_table.group_id = %d", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
437 + Groups_Utility::id( $this->group->group_id )
438 + ) );
439 + if ( $user_ids ) {
440 + foreach ( $user_ids as $user_id ) {
441 + $result[] = $user_id->ID;
442 + }
443 + }
444 + break;
150 445 }
151 446 }
152 447 return $result;
153 448 }
@@ -152,12 +447,11 @@
152 447 return $result;
153 448 }
154 449
155 450 /**
156 - * (non-PHPdoc)
157 451 * @see I_Capable::can()
158 452 */
159 - public function can( $capability ) {
453 + public function can( $capability, $object = null, $args = null ) {
160 454
161 455 global $wpdb;
162 456 $result = false;
163 457
@@ -162,19 +456,19 @@
162 456 $result = false;
163 457
164 458 if ( $this->group !== null ) {
165 459
166 - $group_table = _groups_get_tablename( "group" );
167 - $capability_table = _groups_get_tablename( "capability" );
168 - $group_capability_table = _groups_get_tablename( "group_capability" );
460 + $group_table = _groups_get_tablename( 'group' );
461 + $capability_table = _groups_get_tablename( 'capability' );
462 + $group_capability_table = _groups_get_tablename( 'group_capability' );
169 463
170 - // determine capability id
464 + // determine capability id
171 465 $capability_id = null;
172 466 if ( is_numeric( $capability ) ) {
173 467 $capability_id = Groups_Utility::id( $capability );
174 468 } else if ( is_string( $capability ) ) {
175 469 $capability_id = $wpdb->get_var( $wpdb->prepare(
176 - "SELECT capability_id FROM $capability_table WHERE capability = %s",
470 + "SELECT capability_id FROM $capability_table WHERE capability = %s", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
177 471 $capability
178 472 ) );
179 473 }
180 474
@@ -179,25 +473,25 @@
179 473 }
180 474
181 475 if ( $capability_id !== null ) {
182 476 // check if the group itself can
183 - $result = ( Groups_Group_Capability::read( $this->group->group_id, $capability_id ) !== false );
477 + $result = is_object( $this->group ) ? ( Groups_Group_Capability::read( $this->group->group_id, $capability_id ) !== false ) : null;
184 478 if ( !$result ) {
185 479 // find all parent groups and include in the group's
186 480 // upward hierarchy to see if any of these can
187 - $group_ids = array( $this->group->group_id );
188 - $iterations = 0;
481 + $group_ids = is_object( $this->group ) ? array( $this->group->group_id ) : array();
482 + $iterations = 0;
189 483 $old_group_ids_count = 0;
190 - $all_groups = $wpdb->get_var( "SELECT COUNT(*) FROM $group_table" );
484 + $all_groups = $wpdb->get_var( "SELECT COUNT(*) FROM $group_table" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
191 485 while( ( $iterations < $all_groups ) && ( count( $group_ids ) !== $old_group_ids_count ) ) {
192 486 $iterations++;
193 487 $old_group_ids_count = count( $group_ids );
194 - $id_list = implode( ",", $group_ids );
488 + $id_list = implode( ',', $group_ids );
195 489 $parent_group_ids = $wpdb->get_results(
196 - "SELECT parent_id FROM $group_table WHERE parent_id IS NOT NULL AND group_id IN ($id_list)"
490 + "SELECT parent_id FROM $group_table WHERE parent_id IS NOT NULL AND group_id IN ($id_list)" // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
197 491 );
198 492 if ( $parent_group_ids ) {
199 - foreach( $parent_group_ids as $parent_group_id ) {
493 + foreach ( $parent_group_ids as $parent_group_id ) {
200 494 $parent_group_id = Groups_Utility::id( $parent_group_id->parent_id );
201 495 if ( !in_array( $parent_group_id, $group_ids ) ) {
202 496 $group_ids[] = $parent_group_id;
203 497 }
@@ -204,11 +498,11 @@
204 498 }
205 499 }
206 500 }
207 501 if ( count( $group_ids ) > 0 ) {
208 - $id_list = implode( ",", $group_ids );
502 + $id_list = implode( ',', $group_ids );
209 503 $rows = $wpdb->get_results( $wpdb->prepare(
210 - "SELECT capability_id FROM $group_capability_table WHERE capability_id = %d AND group_id IN ($id_list)",
504 + "SELECT capability_id FROM $group_capability_table WHERE capability_id = %d AND group_id IN ($id_list)", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
211 505 Groups_Utility::id( $capability_id )
212 506 ) );
213 507
214 508 if ( count( $rows ) > 0 ) {
@@ -217,15 +511,49 @@
217 511 }
218 512 }
219 513 }
220 514 }
221 - $result = apply_filters_ref_array( "groups_group_can", array( $result, &$this, $capability ) );
515 + /**
516 + * Filter whether the group has the capability.
517 + *
518 + * @since 3.0.0 $object
519 + * @since 3.0.0 $args
520 + *
521 + * @param boolean $result
522 + * @param Groups_Group $group
523 + * @param string $capability
524 + * @param mixed $object
525 + * @param mixed $args
526 + *
527 + * @return boolean
528 + */
529 + $result = apply_filters_ref_array( 'groups_group_can', array( $result, &$this, $capability, $object, $args ) );
222 530 return $result;
223 531 }
224 532
225 533 /**
534 + * Check if a group with the given ID exists.
535 + *
536 + * @since 2.18.0
537 + *
538 + * @param int $group_id
539 + *
540 + * @return boolean
541 + */
542 + public static function exists( $group_id ) {
543 + $exists = false;
544 + if ( !empty( $group_id ) && is_numeric( $group_id ) ) {
545 + $group_id = Groups_Utility::id( $group_id );
546 + if ( $group_id !== false ) {
547 + $exists = self::read( $group_id ) !== false;
548 + }
549 + }
550 + return $exists;
551 + }
552 +
553 + /**
226 554 * Persist a group.
227 - *
555 + *
228 556 * Parameters:
229 557 * - name (required) - the group's name
230 558 * - creator_id (optional) - defaults to the current user's id
231 559 * - datetime (optional) - defaults to now
@@ -230,35 +558,45 @@
230 558 * - creator_id (optional) - defaults to the current user's id
231 559 * - datetime (optional) - defaults to now
232 560 * - description (optional)
233 561 * - parent_id (optional)
234 - *
562 + *
235 563 * @param array $map attributes
236 - * @return group_id on success, otherwise false
564 + *
565 + * @return int group_id on success, otherwise false
237 566 */
238 567 public static function create( $map ) {
568 +
239 569 global $wpdb;
240 - extract( $map );
570 +
241 571 $result = false;
242 572 $error = false;
243 573
574 + $name = isset( $map['name'] ) ? $map['name'] : null;
575 + $creator_id = isset( $map['creator_id'] ) ? $map['creator_id'] : null;
576 + $datetime = isset( $map['datetime'] ) ? $map['datetime'] : null;
577 + $description = isset( $map['description'] ) ? $map['description'] : null;
578 + $parent_id = isset( $map['parent_id'] ) ? $map['parent_id'] : null;
579 +
244 580 if ( !empty( $name ) ) {
245 581
246 - $group_table = _groups_get_tablename( "group" );
582 + self::writer();
247 583
584 + $group_table = _groups_get_tablename( 'group' );
585 +
248 586 $data = array( 'name' => $name );
249 587 $formats = array( '%s' );
250 - if ( !isset( $creator_id ) ) {
588 + if ( $creator_id === null ) {
251 589 $creator_id = get_current_user_id();
252 590 }
253 - if ( isset( $creator_id ) ) {
591 + if ( $creator_id !== null ) {
254 592 $data['creator_id'] = Groups_Utility::id( $creator_id );
255 593 $formats[] = '%d';
256 594 }
257 - if ( !isset( $datetime ) ) {
258 - $datetime = date( 'Y-m-d H:i:s', time() );
595 + if ( $datetime === null ) {
596 + $datetime = date( 'Y-m-d H:i:s', time() ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
259 597 }
260 - if ( isset( $datetime ) ) {
598 + if ( !empty( $datetime ) ) {
261 599 $data['datetime'] = $datetime;
262 600 $formats[] = '%s';
263 601 }
264 602 if ( !empty( $description ) ) {
@@ -265,18 +603,29 @@
265 603 $data['description'] = $description;
266 604 $formats[] = '%s';
267 605 }
268 606 if ( !empty( $parent_id ) ) {
269 - // only allow to set an existing parent group (that is from the same blog)
270 - $parent_group_id = $wpdb->get_var( $wpdb->prepare(
271 - "SELECT group_id FROM $group_table WHERE group_id = %d",
272 - Groups_Utility::id( $parent_id )
273 - ) );
274 - if ( $parent_group_id === $parent_id ) {
275 - $data['parent_id'] = Groups_Utility::id( $parent_id );
276 - $formats[] = '%d';
277 - } else {
278 - $error = true;
607 + $parent_id = Groups_Utility::id( $parent_id );
608 + if ( $parent_id !== false ) {
609 + // only allow to set an existing parent group (that is from the same blog)
610 + $parent_group_id = $wpdb->get_var(
611 + $wpdb->prepare(
612 + "SELECT group_id FROM $group_table WHERE group_id = %d", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
613 + Groups_Utility::id( $parent_id )
614 + )
615 + );
616 + if ( $parent_group_id !== null ) {
617 + $parent_group_id = intval( $parent_group_id );
618 + }
619 + if (
620 + $parent_group_id !== null &&
621 + $parent_group_id === $parent_id
622 + ) {
623 + $data['parent_id'] = $parent_id;
624 + $formats[] = '%d';
625 + } else {
626 + $error = true;
627 + }
279 628 }
280 629 }
281 630 // no duplicate names
282 631 $duplicate = Groups_Group::read_by_name( $name );
@@ -285,14 +634,21 @@
285 634 }
286 635 if ( !$error ) {
287 636 if ( $wpdb->insert( $group_table, $data, $formats ) ) {
288 637 if ( $result = $wpdb->get_var( "SELECT LAST_INSERT_ID()" ) ) {
289 - // must clear cache for this name in case it has been requested previously as it now exists
290 - Groups_Cache::delete( self::READ_BY_NAME . '_' . $name, self::CACHE_GROUP );
291 - do_action( "groups_created_group", $result );
638 + // purge maps to force update after creating this group
639 + Groups_Cache::delete( self::ID_MAP, self::CACHE_GROUP );
640 + Groups_Cache::delete( self::NAME_MAP, self::CACHE_GROUP );
292 641 }
293 642 }
294 643 }
644 +
645 + self::release();
646 +
647 + if ( $result !== false ) {
648 + do_action( 'groups_created_group', $result );
649 + }
650 +
295 651 }
296 652 return $result;
297 653 }
298 654
@@ -297,24 +653,96 @@
297 653 }
298 654
299 655 /**
300 656 * Retrieve a group.
301 - *
657 + *
302 658 * @param int $group_id group's id
659 + *
303 660 * @return object upon success, otherwise false
304 661 */
305 662 public static function read( $group_id ) {
306 663 global $wpdb;
664 +
665 + $group_id = Groups_Utility::id( $group_id );
666 + if ( $group_id === false ) {
667 + return false;
668 + }
669 +
307 670 $result = false;
308 671
309 - $group_table = _groups_get_tablename( 'group' );
310 - $group = $wpdb->get_row( $wpdb->prepare(
311 - "SELECT * FROM $group_table WHERE group_id = %d",
312 - Groups_Utility::id( $group_id )
313 - ) );
314 - if ( isset( $group->group_id ) ) {
315 - $result = $group;
672 + $max_map = apply_filters( 'groups_group_read_max_map', self::MAX_MAP );
673 + if ( !is_numeric( $max_map ) ) {
674 + $max_map = self::MAX_MAP;
675 + } else {
676 + $max_map = max( 0, intval( $max_map ) );
316 677 }
678 +
679 + $is_locked = self::is_locked();
680 + if ( !$is_locked ) {
681 + self::writer();
682 + }
683 +
684 + $cached = Groups_Cache::get( self::ID_MAP, self::CACHE_GROUP );
685 + if ( $cached !== null ) {
686 + $map = $cached->get_value();
687 + $result = $map[$group_id] ?? false;
688 + if ( $result === false && count( $map ) >= $max_map ) {
689 + // requested is not in map
690 + $group_table = _groups_get_tablename( 'group' );
691 + $group = $wpdb->get_row( $wpdb->prepare(
692 + "SELECT * FROM $group_table WHERE group_id = %d", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
693 + $group_id
694 + ) );
695 + if ( isset( $group->group_id ) ) {
696 + $result = $group;
697 + // push requested to map
698 + $map = array( $group->group_id => $group ) + $map; // numerical key is automatically cast to int
699 + array_pop( $map );
700 + Groups_Cache::set( self::ID_MAP, $map, self::CACHE_GROUP );
701 + }
702 + }
703 + } else {
704 + // map not cached, prime the maps
705 + $map = array();
706 + $name_map = array();
707 + $group_table = _groups_get_tablename( 'group' );
708 + $query = $wpdb->prepare( "SELECT * FROM $group_table LIMIT %d", $max_map ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
709 + $groups = $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
710 + if ( is_array( $groups ) ) {
711 + foreach ( $groups as $group ) {
712 + $map[$group->group_id] = $group; // numerical key is automatically cast to int
713 + $name_map[$group->name] = $group;
714 + }
715 + }
716 + if ( isset( $map[$group_id] ) ) {
717 + $result = $map[$group_id];
718 + } else if ( count( $map ) >= $max_map ) {
719 + // requested is not in map
720 + $group = $wpdb->get_row( $wpdb->prepare(
721 + "SELECT * FROM $group_table WHERE group_id = %d", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
722 + $group_id
723 + ) );
724 + if ( isset( $group->group_id ) ) {
725 + $result = $group;
726 + // push requested to maps
727 + if ( !isset( $map[intval( $group->group_id )] ) ) { // double-check
728 + $map = array( $group->group_id => $group ) + $map; // numerical key is automatically cast to int
729 + array_pop( $map );
730 + }
731 + if ( !isset( $name_map[$group->name] ) ) {
732 + $name_map = array( $group->name => $group ) + $name_map;
733 + array_pop( $name_map );
734 + }
735 + }
736 + }
737 + Groups_Cache::set( self::ID_MAP, $map, self::CACHE_GROUP );
738 + Groups_Cache::set( self::NAME_MAP, $name_map, self::CACHE_GROUP );
739 + }
740 +
741 + if ( !$is_locked ) {
742 + self::release();
743 + }
744 +
317 745 return $result;
318 746 }
319 747
320 748 /**
@@ -320,51 +748,138 @@
320 748 /**
321 749 * Retrieve a group by name.
322 750 *
323 751 * @param string $name the group's name
752 + *
324 753 * @return object upon success, otherwise false
325 754 */
326 755 public static function read_by_name( $name ) {
327 756 global $wpdb;
328 - $cached = Groups_Cache::get( self::READ_BY_NAME . '_' . $name, self::CACHE_GROUP );
757 +
758 + $result = false;
759 +
760 + $max_map = apply_filters( 'groups_group_read_by_name_max_map', self::MAX_MAP );
761 + if ( !is_numeric( $max_map ) ) {
762 + $max_map = self::MAX_MAP;
763 + } else {
764 + $max_map = max( 0, intval( $max_map ) );
765 + }
766 +
767 + $is_locked = self::is_locked();
768 + if ( !$is_locked ) {
769 + self::writer();
770 + }
771 +
772 + $cached = Groups_Cache::get( self::NAME_MAP, self::CACHE_GROUP );
329 773 if ( $cached !== null ) {
330 - $result = $cached->value;
331 - unset( $cached );
774 + $name_map = $cached->get_value();
775 + $result = $name_map[$name] ?? false; // will be false if case does not match
776 + if ( $result === false ) {
777 + // requested not in map
778 + $group_table = _groups_get_tablename( 'group' );
779 + $group = $wpdb->get_row( $wpdb->prepare(
780 + "SELECT * FROM $group_table WHERE name = %s", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
781 + $name
782 + ) );
783 + if ( isset( $group->group_id ) ) {
784 + $result = $group;
785 + // push requested to map
786 + if ( !isset( $name_map[$group->name] ) ) {
787 + $name_map = array( $group->name => $group ) + $name_map;
788 + if ( count( $name_map ) > $max_map ) {
789 + array_pop( $name_map );
790 + }
791 + Groups_Cache::set( self::NAME_MAP, $name_map, self::CACHE_GROUP );
792 + }
793 + // where case insensitive collation yields result also push to map using original $name
794 + // so it can also be retrieved from cached map by $name as key
795 + if ( !isset( $name_map[$name] ) ) {
796 + $name_map = array( $name => $group ) + $name_map;
797 + if ( count( $name_map ) > $max_map ) {
798 + array_pop( $name_map );
799 + }
800 + Groups_Cache::set( self::NAME_MAP, $name_map, self::CACHE_GROUP );
801 + }
802 + }
803 + }
332 804 } else {
333 - $result = false;
805 + $map = array();
806 + $name_map = array();
334 807 $group_table = _groups_get_tablename( 'group' );
335 - $group = $wpdb->get_row( $wpdb->prepare(
336 - "SELECT * FROM $group_table WHERE name = %s",
337 - $name
338 - ) );
339 - if ( isset( $group->group_id ) ) {
340 - $result = $group;
808 + $query = $wpdb->prepare( "SELECT * FROM $group_table LIMIT %d", $max_map ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
809 + $groups = $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
810 + if ( is_array( $groups ) ) {
811 + foreach ( $groups as $group ) {
812 + $map[$group->group_id] = $group; // numerical key is automatically cast to int
813 + $name_map[$group->name] = $group;
814 + }
341 815 }
342 - Groups_Cache::set( self::READ_BY_NAME . '_' . $name, $result, self::CACHE_GROUP );
816 + if ( isset( $name_map[$name] ) ) {
817 + $result = $name_map[$name];
818 + } else {
819 + $group = $wpdb->get_row( $wpdb->prepare(
820 + "SELECT * FROM $group_table WHERE name = %s", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
821 + $name
822 + ) );
823 + if ( isset( $group->group_id ) ) {
824 + $result = $group;
825 + if ( !isset( $map[$group->group_id] ) ) {
826 + $map = array( $group->group_id => $group ) + $map; // numerical key is automatically cast to int
827 + if ( count( $name_map ) > $max_map ) {
828 + array_pop( $map );
829 + }
830 + }
831 + if ( !isset( $name_map[$group->name] ) ) {
832 + $name_map = array( $group->name => $group ) + $name_map;
833 + array_pop( $name_map );
834 + }
835 + if ( !isset( $name_map[$name] ) ) {
836 + $name_map = array( $name => $group ) + $name_map;
837 + if ( count( $name_map ) > $max_map ) {
838 + array_pop( $name_map );
839 + }
840 + }
841 + }
842 + }
843 + Groups_Cache::set( self::ID_MAP, $map, self::CACHE_GROUP );
844 + Groups_Cache::set( self::NAME_MAP, $name_map, self::CACHE_GROUP );
343 845 }
846 +
847 + if ( !$is_locked ) {
848 + self::release();
849 + }
850 +
344 851 return $result;
345 852 }
346 853
347 854 /**
348 855 * Update group.
349 - *
856 + *
350 857 * @param array $map group attribute, must contain group_id
351 - * @return group_id on success, otherwise false
858 + *
859 + * @return int group_id on success, otherwise false
352 860 */
353 861 public static function update( $map ) {
354 862
355 863 global $wpdb;
356 - extract( $map );
864 +
357 865 $result = false;
358 866
867 + $group_id = isset( $map['group_id'] ) ? $map['group_id'] : null;
868 + $name = isset( $map['name'] ) ? $map['name'] : null;
869 + $description = isset( $map['description'] ) ? $map['description'] : null;
870 + $parent_id = isset( $map['parent_id'] ) ? $map['parent_id'] : null;
871 +
359 872 if ( isset( $group_id ) && !empty( $name ) ) {
360 - $old_group = Groups_Group::read( $group_id );
873 +
874 + self::writer();
875 +
361 876 $group_table = _groups_get_tablename( 'group' );
362 877 if ( !isset( $description ) || ( $description === null ) ) {
363 878 $description = '';
364 879 }
365 880 $wpdb->query( $wpdb->prepare(
366 - "UPDATE $group_table SET name = %s, description = %s WHERE group_id = %d",
881 + "UPDATE $group_table SET name = %s, description = %s WHERE group_id = %d", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
367 882 $name,
368 883 $description,
369 884 Groups_Utility::id( $group_id )
370 885 ) );
@@ -369,13 +884,12 @@
369 884 Groups_Utility::id( $group_id )
370 885 ) );
371 886 if ( empty( $parent_id ) ) {
372 887 $wpdb->query( $wpdb->prepare(
373 - "UPDATE $group_table SET parent_id = NULL WHERE group_id = %d",
888 + "UPDATE $group_table SET parent_id = NULL WHERE group_id = %d", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
374 889 Groups_Utility::id( $group_id )
375 890 ) );
376 891 } else {
377 -
378 892 // Prohibit circular dependencies:
379 893 // This group cannot have a parent that is its successor
380 894 // at any level in its successor hierarchy.
381 895 // S(g) : successor of group g
@@ -380,17 +894,17 @@
380 894 // at any level in its successor hierarchy.
381 895 // S(g) : successor of group g
382 896 // S*(g) : successors of group g, any level deep
383 897 // P(g) : parent of g
384 - // ---
898 + // ---
385 899 // It must hold: !( P(g) in S*(g) )
386 900
387 901 // Find all successors of this group
388 - $groups = $wpdb->get_var( "SELECT COUNT(*) FROM $group_table" );
902 + $groups = $wpdb->get_var( "SELECT COUNT(*) FROM $group_table" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
389 903 if ( $groups !== null ) {
390 - $group_ids = array();
391 - $group_ids[] = Groups_Utility::id( $group_id );
392 - $iterations = 0;
904 + $group_ids = array();
905 + $group_ids[] = Groups_Utility::id( $group_id );
906 + $iterations = 0;
393 907 $old_group_ids_count = 0;
394 908 while( ( $iterations < $groups ) && ( count( $group_ids ) > 0 ) && ( count( $group_ids ) !== $old_group_ids_count ) ) {
395 909
396 910 $iterations++;
@@ -395,16 +909,16 @@
395 909
396 910 $iterations++;
397 911 $old_group_ids_count = count( $group_ids );
398 912
399 - $id_list = implode( ",", $group_ids );
913 + $id_list = implode( ',', $group_ids );
400 914 // We can trust ourselves here, no need to use prepare()
401 915 // but careful if this query is modified!
402 916 $successor_group_ids = $wpdb->get_results(
403 - "SELECT group_id FROM $group_table WHERE parent_id IS NOT NULL AND parent_id IN ($id_list)"
917 + "SELECT group_id FROM $group_table WHERE parent_id IS NOT NULL AND parent_id IN ($id_list)" // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
404 918 );
405 919 if ( $successor_group_ids ) {
406 - foreach( $successor_group_ids as $successor_group_id ) {
920 + foreach ( $successor_group_ids as $successor_group_id ) {
407 921 $successor_group_id = Groups_Utility::id( $successor_group_id->group_id );
408 922 if ( !in_array( $successor_group_id, $group_ids ) ) {
409 923 $group_ids[] = $successor_group_id;
410 924 }
@@ -413,9 +927,9 @@
413 927 }
414 928 // only add if condition holds
415 929 if ( !in_array( Groups_Utility::id( $parent_id ), $group_ids ) ) {
416 930 $wpdb->query( $wpdb->prepare(
417 - "UPDATE $group_table SET parent_id = %d WHERE group_id = %d",
931 + "UPDATE $group_table SET parent_id = %d WHERE group_id = %d", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
418 932 Groups_Utility::id( $parent_id),
419 933 Groups_Utility::id( $group_id )
420 934 ) );
421 935 }
@@ -421,15 +935,17 @@
421 935 }
422 936 }
423 937 }
424 938 $result = $group_id;
425 - if ( !empty( $name ) ) {
426 - Groups_Cache::delete( self::READ_BY_NAME . '_' . $name, self::CACHE_GROUP );
939 +
940 + if ( !empty( $group_id ) || !empty( $name ) ) { // @phpstan-ignore empty.variable
941 + Groups_Cache::delete( self::ID_MAP, self::CACHE_GROUP );
942 + Groups_Cache::delete( self::NAME_MAP, self::CACHE_GROUP );
427 943 }
428 - if ( !empty( $old_group ) && !empty( $old_group->name ) ) {
429 - Groups_Cache::delete( self::READ_BY_NAME . '_' . $old_group->name, self::CACHE_GROUP );
430 - }
431 - do_action( "groups_updated_group", $result );
944 +
945 + self::release();
946 +
947 + do_action( 'groups_updated_group', $result );
432 948 }
433 949 return $result;
434 950 }
435 951
@@ -434,11 +950,12 @@
434 950 }
435 951
436 952 /**
437 953 * Remove group and its relations.
438 - *
954 + *
439 955 * @param int $group_id
440 - * @return group_id if successful, false otherwise
956 + *
957 + * @return int group_id if successful, false otherwise
441 958 */
442 959 public static function delete( $group_id ) {
443 960
444 961 global $wpdb;
@@ -443,14 +960,16 @@
443 960
444 961 global $wpdb;
445 962 $result = false;
446 963
964 + self::writer();
965 +
447 966 if ( $group = self::read( $group_id ) ) {
448 967
449 968 // delete group-capabilities
450 969 $group_capability_table = _groups_get_tablename( 'group_capability' );
451 970 $wpdb->query( $wpdb->prepare(
452 - "DELETE FROM $group_capability_table WHERE group_id = %d",
971 + "DELETE FROM $group_capability_table WHERE group_id = %d", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
453 972 Groups_Utility::id( $group->group_id )
454 973 ) );
455 974
456 975 // delete group-users
@@ -455,9 +974,9 @@
455 974
456 975 // delete group-users
457 976 $user_group_table = _groups_get_tablename( 'user_group' );
458 977 $wpdb->query( $wpdb->prepare(
459 - "DELETE FROM $user_group_table WHERE group_id = %d",
978 + "DELETE FROM $user_group_table WHERE group_id = %d", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
460 979 $group->group_id
461 980 ) );
462 981
463 982 // set parent_id to null where this group is parent
@@ -462,30 +981,37 @@
462 981
463 982 // set parent_id to null where this group is parent
464 983 $group_table = _groups_get_tablename( 'group' );
465 984 $wpdb->query( $wpdb->prepare(
466 - "UPDATE $group_table SET parent_id = NULL WHERE parent_id = %d",
985 + "UPDATE $group_table SET parent_id = NULL WHERE parent_id = %d", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
467 986 $group->group_id
468 987 ) );
469 988
470 989 // delete group
471 990 if ( $wpdb->query( $wpdb->prepare(
472 - "DELETE FROM $group_table WHERE group_id = %d",
991 + "DELETE FROM $group_table WHERE group_id = %d", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
473 992 $group->group_id
474 993 ) ) ) {
475 994 $result = $group->group_id;
476 - if ( !empty( $group->name ) ) {
477 - Groups_Cache::delete( self::READ_BY_NAME . '_' . $group->name, self::CACHE_GROUP );
995 + if ( !empty( $group->group_id ) || !empty( $group->name ) ) {
996 + Groups_Cache::delete( self::ID_MAP, self::CACHE_GROUP );
997 + Groups_Cache::delete( self::NAME_MAP, self::CACHE_GROUP );
478 998 }
479 - do_action( "groups_deleted_group", $result );
480 999 }
481 1000 }
1001 +
1002 + self::release();
1003 +
1004 + if ( $result !== false ) {
1005 + do_action( 'groups_deleted_group', $result );
1006 + }
1007 +
482 1008 return $result;
483 1009 }
484 1010
485 1011 /**
486 1012 * Returns an array of group IDs.
487 - *
1013 + *
488 1014 * If no arguments are passed, IDs for all existing groups are returned.
489 1015 *
490 1016 * @param array $args
491 1017 * - ['order_by'] string a Groups_Group property
@@ -513,9 +1039,9 @@
513 1039 }
514 1040
515 1041 /**
516 1042 * Returns an array of database results by querying the group table.
517 - *
1043 + *
518 1044 * @param Array $args
519 1045 * - ['fields'] string with fields to get separated by comma. If empty then get all fields.
520 1046 * - ['order_by'] string a Groups_Group property
521 1047 * - ['order'] string ASC or DESC. Only applied if 'order_by' is set.
@@ -523,25 +1049,32 @@
523 1049 * - ['include'] array|string with one or more IDs of groups to include, separated by comma
524 1050 * - ['include_by_name'] array|string with one ore more group names of groups to include, separated by comma
525 1051 * - ['exclude'] array|string with one or more IDs of groups to exclude, separated by comma
526 1052 * - ['exclude_by_name'] array|string with one ore more group names of groups to exclude, separated by comma
527 - *
528 - * @return array of int with group IDs
529 - *
1053 + *
1054 + * @return array of object with query rows
1055 + *
530 1056 * @since groups 1.4.9
531 1057 */
532 1058 public static function get_groups( $args = array() ) {
533 1059 global $wpdb;
534 1060
535 - extract( $args );
1061 + $fields = isset( $args['fields'] ) ? $args['fields'] : null;
1062 + $order = isset( $args['order'] ) ? $args['order'] : null;
1063 + $order_by = isset( $args['order_by'] ) ? $args['order_by'] : null;
1064 + $parent_id = isset( $args['parent_id'] ) ? $args['parent_id'] : null;
1065 + $include = isset( $args['include'] ) ? $args['include'] : null;
1066 + $include_by_name = isset( $args['include_by_name'] ) ? $args['include_by_name'] : null;
1067 + $exclude = isset( $args['exclude'] ) ? $args['exclude'] : null;
1068 + $exclude_by_name = isset( $args['exclude_by_name'] ) ? $args['exclude_by_name'] : null;
536 1069
537 1070 if ( !isset( $fields ) ) {
538 - $fields = "*";
1071 + $fields = '*';
539 1072 } else {
540 1073 $array_fields = explode( ',', sanitize_text_field( $fields ) );
541 - $fields = "";
1074 + $fields = '';
542 1075 foreach ( $array_fields as $field ) {
543 - switch( trim( $field ) ) {
1076 + switch ( trim( $field ) ) {
544 1077 case 'group_id' :
545 1078 case 'parent_id' :
546 1079 case 'creator_id' :
547 1080 case 'datetime' :
@@ -559,9 +1092,9 @@
559 1092 if ( !isset( $order ) ) {
560 1093 $order = '';
561 1094 } else {
562 1095 $order = strtoupper( sanitize_text_field( trim( $order ) ) );
563 - switch( $order ) {
1096 + switch ( $order ) {
564 1097 case 'ASC' :
565 1098 case 'DESC' :
566 1099 break;
567 1100 default :
@@ -569,12 +1102,12 @@
569 1102 }
570 1103 }
571 1104
572 1105 if ( !isset( $order_by ) ) {
573 - $order_by = "";
1106 + $order_by = '';
574 1107 } else {
575 1108 $order_by = sanitize_text_field( $order_by );
576 - switch( trim( $order_by ) ) {
1109 + switch ( trim( $order_by ) ) {
577 1110 case 'group_id' :
578 1111 case 'parent_id' :
579 1112 case 'creator_id' :
580 1113 case 'datetime' :
@@ -579,9 +1112,9 @@
579 1112 case 'creator_id' :
580 1113 case 'datetime' :
581 1114 case 'name' :
582 1115 case 'description' :
583 - $order_by = $wpdb->prepare( " ORDER BY %s $order ", array( $order_by ) );
1116 + $order_by = " ORDER BY $order_by $order "; // Watch out! This is unescaped but safe within this switch.
584 1117 break;
585 1118 default :
586 1119 $order_by = '';
587 1120 break;
@@ -603,9 +1136,9 @@
603 1136 $include = !empty( $include ) ? $include : null;
604 1137 if ( !empty( $include ) && !is_array( $include ) && is_string( $include ) ) {
605 1138 $include = explode( ',', $include );
606 1139 }
607 - if ( count( $include ) > 0 ) {
1140 + if ( $include !== null && count( $include ) > 0 ) {
608 1141 $include = implode( ',', array_map( 'intval', array_map( 'trim', $include ) ) );
609 1142 if ( strlen( $include ) > 0 ) {
610 1143 $where_include = " group_id IN ($include) ";
611 1144 }
@@ -618,9 +1151,9 @@
618 1151 $include_by_name = !empty( $include_by_name ) ? $include_by_name : null;
619 1152 if ( !empty( $include_by_name ) && !is_array( $include_by_name ) && is_string( $include_by_name ) ) {
620 1153 $include_by_name = explode( ',', $include_by_name );
621 1154 }
622 - if ( count( $include_by_name ) > 0 ) {
1155 + if ( $include_by_name !== null && count( $include_by_name ) > 0 ) {
623 1156 $include_by_name = "'" . implode( "','", array_map( 'esc_sql', array_map( 'trim', $include_by_name ) ) ) . "'";
624 1157 if ( strlen( $include_by_name ) > 0 ) {
625 1158 $where_include_by_name = " name IN ($include_by_name) ";
626 1159 }
@@ -656,9 +1189,9 @@
656 1189 $exclude = !empty( $exclude ) ? $exclude : null;
657 1190 if ( !empty( $exclude ) && !is_array( $exclude ) && is_string( $exclude ) ) {
658 1191 $exclude = explode( ',', $exclude );
659 1192 }
660 - if ( count( $exclude ) > 0 ) {
1193 + if ( $exclude !== null && count( $exclude ) > 0 ) {
661 1194 $exclude = implode( ',', array_map( 'intval', array_map( 'trim', $exclude ) ) );
662 1195 if ( strlen( $exclude ) > 0 ) {
663 1196 if ( empty( $where ) ) {
664 1197 $where = " WHERE group_id NOT IN ($exclude) ";
@@ -674,13 +1207,13 @@
674 1207 $exclude_by_name = !empty( $exclude_by_name ) ? $exclude_by_name : null;
675 1208 if ( !empty( $exclude_by_name ) && !is_array( $exclude_by_name ) && is_string( $exclude_by_name ) ) {
676 1209 $exclude_by_name = explode( ',', $exclude_by_name );
677 1210 }
678 - if ( count( $exclude_by_name ) > 0 ) {
1211 + if ( $exclude_by_name !== null && count( $exclude_by_name ) > 0 ) {
679 1212 $exclude_by_name = "'" . implode( "','", array_map( 'esc_sql', array_map( 'trim', $exclude_by_name ) ) ) . "'";
680 1213 if ( strlen( $exclude_by_name ) > 0 ) {
681 1214 if ( empty( $where ) ) {
682 - $where = " WHERE name NOT IN ($exclude_by_name) ";
1215 + $where = " WHERE name NOT IN ($exclude_by_name) ";
683 1216 } else {
684 1217 $where .= " AND name NOT IN ($exclude_by_name) ";
685 1218 }
686 1219 }
@@ -686,9 +1219,9 @@
686 1219 }
687 1220 }
688 1221
689 1222 $groups_table = _groups_get_tablename( 'group' );
690 - $groups = $wpdb->get_results( "SELECT $fields FROM $groups_table $where $order_by" );
1223 + $groups = $wpdb->get_results( "SELECT $fields FROM $groups_table $where $order_by" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
691 1224
692 1225 return $groups;
693 1226 }
694 1227 }