PluginProbe ʕ •ᴥ•ʔ
Advanced Ads – Ad Manager & AdSense / 2.0.26
Advanced Ads – Ad Manager & AdSense v2.0.26
2.0.26 2.0.25 2.0.24 2.0.23 2.0.22 2.0.21 1.38.0 1.39.0 1.39.1 1.39.2 1.39.3 1.39.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.40.0 1.40.1 1.40.2 1.41.0 1.42.0 1.42.1 1.42.2 1.43.0 1.44.0 1.44.1 1.45.0 1.45.1 1.46.0 1.47.0 1.47.1 1.47.2 1.47.3 1.47.4 1.47.5 1.48.0 1.48.1 1.49.0 1.5.0 1.5.0.1 1.5.1 1.5.2 1.5.2.1 1.5.4 1.5.4.1 1.5.5 1.50.0 1.51.0 1.51.1 1.51.2 1.51.3 1.52.0 1.52.1 1.52.2 1.52.3 1.52.4 1.53.0 1.53.1 1.53.2 1.54.0 1.54.1 1.55.0 1.56.0 1.56.1 1.56.2 1.56.3 1.56.4 1.6 1.6.1 1.6.10 1.6.10.1 1.6.10.2 1.6.11 1.6.11.1 1.6.12 1.6.13 1.6.14 1.6.15 1.6.16 1.6.17 1.6.17.1 1.6.17.2 1.6.2 1.6.2.1 1.6.3 1.6.4 1.6.4.1 1.6.5 1.6.6 1.6.6.1 1.6.7 1.6.7.1 1.6.8 1.6.8.1 1.6.8.2 1.6.8.3 1.6.9 1.6.9.1 1.6.9.2 1.6.9.3 1.6.9.4 1.7 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.1.1 1.7.1.2 1.7.1.3 1.7.1.4 1.7.1.5 1.7.10 trunk 1.7.11 1.0.1 1.7.12 1.0.2 1.7.13 1.0.3 1.7.14 1.1.0 1.7.15 1.1.1 1.7.16 1.1.2 1.7.17 1.1.3 1.7.18 1.10 1.7.19 1.10.1 1.7.2 1.10.10 1.7.2.1 1.10.11 1.7.20 1.10.12 1.7.21 1.10.2 1.7.22 1.10.3 1.7.23 1.10.4 1.7.24 1.10.5 1.7.25 1.10.6 1.7.3 1.10.7 1.7.4 1.10.8 1.7.4.1 1.10.9 1.7.4.2 1.11 1.7.4.3 1.11.1 1.7.4.4 1.11.2 1.7.4.5 1.12 1.7.5 1.13 1.7.5.1 1.13.1 1.7.6 1.13.2 1.7.7 1.13.3 1.7.8 1.13.4 1.7.9 1.13.5 1.7.9.1 1.13.6 1.7.9.2 1.13.7 1.7.9.3 1.13.8 1.8 1.14 1.8.1 1.14.1 1.8.10 1.14.10 1.8.11 1.14.11 1.8.12 1.14.2 1.8.13 1.14.3 1.8.14 1.14.4 1.8.15 1.14.5 1.8.16 1.14.6 1.8.17 1.14.7 1.8.18 1.14.8 1.8.19 1.14.9 1.8.2 1.15 1.8.20 1.16 1.8.21 1.16.1 1.8.22 1.17 1.8.23 1.17.1 1.8.24 1.17.10 1.8.25 1.17.10-rc.1 1.8.26 1.17.11 1.8.27 1.17.12 1.8.28 1.17.12-rc.1 1.8.29 1.17.2 1.8.3 1.17.3 1.8.30 1.17.4 1.8.4 1.17.5 1.8.5 1.17.6 1.8.6 1.17.7 1.8.7 1.17.8 1.8.8 1.17.9 1.8.9 1.17.9-beta.1 1.9 1.18.0 2.0.0 1.19.0 2.0.1 1.19.1 2.0.10 1.2 2.0.11 1.2.1 2.0.12 1.2.2 2.0.13 1.2.3 2.0.14 1.2.4 2.0.15 1.2.5 2.0.16 1.2.6 2.0.17 1.2.7 2.0.18 1.20.0 2.0.19 1.20.0-rc.1 2.0.2 1.20.0-rc.2 2.0.20 1.20.1 2.0.3 1.20.2 2.0.4 1.20.3 2.0.5 1.21.0 2.0.6 1.21.1 2.0.7 1.22.0 2.0.8 1.22.1 2.0.9 1.22.2 1.23.0 1.23.1 1.23.2 1.24.0 1.24.1 1.24.2 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.29.0 1.29.1 1.3 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.14 1.3.15 1.3.16 1.3.17 1.3.18 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.30.0 1.30.1 1.30.2 1.30.2-rc.1 1.30.3 1.30.4 1.30.4-rc.1 1.30.5 1.31.0 1.31.1 1.32.0 1.32.0-rc.1 1.33.0 1.33.1 1.33.2 1.34.0 1.35.0 1.35.1 1.36.0 1.36.1 1.36.2 1.36.3 1.37.0 1.37.1 1.37.2
advanced-ads / includes / groups / class-group-repository.php
advanced-ads / includes / groups Last commit date
types 3 weeks ago class-group-ad-relation.php 3 weeks ago class-group-factory.php 3 weeks ago class-group-ordered.php 1 year ago class-group-repository.php 3 weeks ago class-group-slider.php 3 weeks ago class-group-standard.php 1 year ago class-group-types.php 1 month ago class-groups.php 1 month ago index.php 1 year ago
class-group-repository.php
487 lines
1 <?php
2 /**
3 * Group Repository.
4 *
5 * @package AdvancedAds
6 * @author Advanced Ads <info@wpadvancedads.com>
7 * @since 1.48.0
8 */
9
10 namespace AdvancedAds\Groups;
11
12 use AdvancedAds\Abstracts\Group;
13 use AdvancedAds\Constants;
14 use AdvancedAds\Framework\Utilities\Formatting;
15 use AdvancedAds\Traits\Repository_Helpers;
16 use AdvancedAds\Utilities\Cache;
17 use Exception;
18
19 defined( 'ABSPATH' ) || exit;
20
21 /**
22 * Group Repository.
23 */
24 class Group_Repository {
25 use Repository_Helpers;
26
27 /**
28 * Group options metakey
29 *
30 * @var string
31 */
32 const OPTION_METAKEY = 'advanced_ads_group_options';
33
34 /**
35 * Group type metakey
36 *
37 * @var string
38 */
39 const TYPE_METAKEY = '_advads_group_type';
40
41 /* CRUD Methods ------------------- */
42
43 /**
44 * Create a new group in the database.
45 *
46 * @param Group $group Group object.
47 *
48 * @throws Exception If the group could not be created.
49 *
50 * @return Group
51 */
52 public function create( &$group ): Group {
53 apply_filters( 'advanced-ads-group-pre-save', $group );
54
55 $ids = wp_insert_term(
56 $group->get_title(),
57 Constants::TAXONOMY_GROUP,
58 [
59 'description' => $group->get_content(),
60 'slug' => $group->get_slug(),
61 ]
62 );
63
64 if ( ! $ids || is_wp_error( $ids ) ) {
65 throw new Exception( esc_html__( 'Unable to create group.', 'advanced-ads' ) );
66 }
67
68 $group->set_id( $ids['term_id'] );
69 $this->update_term_meta( $group );
70 $group->apply_changes();
71
72 return $group;
73 }
74
75 /**
76 * Read an group from the database.
77 *
78 * @param Group $group Group object.
79 * @throws Exception If invalid group.
80 *
81 * @return void
82 */
83 public function read( &$group ): void {
84 $group->set_defaults();
85 $term_object = get_term( $group->get_id(), Constants::TAXONOMY_GROUP );
86
87 if ( null === $term_object || is_wp_error( $term_object ) ) {
88 throw new Exception( esc_html__( 'Invalid group.', 'advanced-ads' ) );
89 }
90
91 $group->set_title( $term_object->name );
92 $group->set_slug( $term_object->slug );
93 $group->set_content( $term_object->description );
94
95 $this->read_group_data( $group );
96 $group->set_object_read( true );
97 }
98
99 /**
100 * Update an existing group in the database.
101 *
102 * @param Group $group Group object.
103 *
104 * @return void
105 */
106 public function update( &$group ): void {
107 apply_filters( 'advanced-ads-group-pre-save', $group );
108
109 $changed = array_keys( $group->get_changes() );
110
111 $term_args = [];
112
113 if ( in_array( 'title', $changed, true ) ) {
114 $term_args['name'] = $group->get_title( 'edit' );
115 }
116
117 if ( in_array( 'slug', $changed, true ) ) {
118 $term_args['slug'] = $group->get_slug( 'edit' );
119 }
120
121 if ( in_array( 'content', $changed, true ) ) {
122 $term_args['description'] = $group->get_content( 'edit' );
123 }
124
125 if ( ! empty( $term_args ) ) {
126 wp_update_term( $group->get_id(), Constants::TAXONOMY_GROUP, $term_args );
127 }
128
129 // Only update weights when there is a change.
130 if ( in_array( 'ad_weights', $changed, true ) ) {
131 ( new Group_Ad_Relation() )->relate( $group );
132 }
133
134 $this->update_term_meta( $group );
135 $group->apply_changes();
136 }
137
138 /**
139 * Delete an group from the database.
140 *
141 * @param Group $group Group object or Id.
142 * @param bool $force_delete Unused; taxonomy terms are always deleted permanently.
143 *
144 * @return void
145 */
146 public function delete( &$group, $force_delete = false ): void {
147 // Early bail!!
148 if ( ! $group || ! $group->get_id() ) {
149 return;
150 }
151
152 wp_delete_term( $group->get_id(), Constants::TAXONOMY_GROUP );
153
154 $group->set_id( 0 );
155 $group->set_status( 'trash' );
156 }
157
158 /* Finder Methods ------------------- */
159
160 /**
161 * Get all groups object.
162 *
163 * @deprecated 2.0.24 Use get_group_summaries() or get_groups_by_ids() instead.
164 *
165 * @return Group[]
166 */
167 public function get_all_groups(): array {
168 return $this->hydrate_groups( array_keys( $this->get_group_summaries() ) );
169 }
170
171 /**
172 * Get lightweight group summaries for list UIs (cached cross-request).
173 *
174 * @return array<int, array{id: int, title: string, slug: string, type: string, ad_weights: array<int, int>, publish_date: string, modified_date: string}>
175 */
176 public function get_group_summaries(): array {
177 $summaries = Cache::get( Cache::PREFIX_GROUPS, Cache::KEY_SUMMARIES );
178
179 if ( null === $summaries ) {
180 $summaries = $this->query_group_summaries();
181 Cache::set( Cache::PREFIX_GROUPS, Cache::KEY_SUMMARIES, $summaries );
182 }
183
184 return $summaries;
185 }
186
187 /**
188 * Get all group as dropdown (ID => title), derived from cached summaries.
189 *
190 * @return array<int, string>
191 */
192 public function get_groups_dropdown(): array {
193 return $this->summaries_to_dropdown( $this->get_group_summaries() );
194 }
195
196 /**
197 * Get ads belonging to a group in the requested shape.
198 *
199 * @param int $group_id Group term ID.
200 * @param string $output OBJECT for hydrated ads, 'ids' for ad IDs, 'summaries' for cached ad rows.
201 *
202 * @return Ad[]|int[]|array<int, array{id: int, title: string, type: string, status: string, author_id: int, expiry_date: int}>
203 */
204 public function get_ads_by_group_id( int $group_id, $output = OBJECT ): array {
205 $ad_weights = $this->get_ad_weights_by_group_id( $group_id );
206
207 if ( empty( $ad_weights ) ) {
208 return [];
209 }
210
211 $ad_ids = array_map( 'absint', array_keys( $ad_weights ) );
212
213 if ( 'ids' === $output ) {
214 return $ad_ids;
215 }
216
217 if ( 'summaries' === $output ) {
218 return array_intersect_key( wp_advads_get_ad_summaries(), array_flip( $ad_ids ) );
219 }
220
221 $ads = wp_advads_get_ads_by_ids( $ad_ids );
222
223 foreach ( $ads as $ad_id => $ad ) {
224 $ad->set_prop( 'weight', $ad_weights[ $ad_id ] );
225 }
226
227 return $ads;
228 }
229
230 /**
231 * Get ad weights for a group from cached summaries.
232 *
233 * @param int $group_id Group term ID.
234 *
235 * @return array<int, int>
236 */
237 private function get_ad_weights_by_group_id( int $group_id ): array {
238 $summaries = $this->get_group_summaries();
239
240 if ( ! isset( $summaries[ $group_id ] ) ) {
241 return [];
242 }
243
244 return $summaries[ $group_id ]['ad_weights'] ?? [];
245 }
246
247 /**
248 * Query lightweight group summaries without hydrating Group objects.
249 *
250 * @return array<int, array{id: int, title: string, slug: string, type: string, ad_weights: array<int, int>, publish_date: string, modified_date: string}>
251 */
252 private function query_group_summaries(): array {
253 $terms = get_terms(
254 [
255 'taxonomy' => Constants::TAXONOMY_GROUP,
256 'hide_empty' => false,
257 'number' => 0,
258 'orderby' => 'name',
259 'update_term_meta_cache' => false,
260 'suppress_filters' => defined( 'ICL_SITEPRESS_VERSION' ) ? true : false, // Suppress filters if WPML is present.
261 ]
262 );
263
264 if ( empty( $terms ) || is_wp_error( $terms ) ) {
265 return [];
266 }
267
268 $term_ids = wp_list_pluck( $terms, 'term_id' );
269 update_termmeta_cache( $term_ids );
270
271 $summaries = [];
272 foreach ( $terms as $term ) {
273 $type = get_term_meta( $term->term_id, self::TYPE_METAKEY, true );
274 $meta_values = get_term_meta( $term->term_id, self::OPTION_METAKEY, true );
275
276 if ( ! $type ) {
277 $type = is_array( $meta_values ) ? ( $meta_values['type'] ?? 'default' ) : 'default';
278 }
279
280 $type = self::normalize_group_type( $type );
281
282 $summaries[ (int) $term->term_id ] = [
283 'id' => (int) $term->term_id,
284 'title' => $term->name,
285 'slug' => $term->slug,
286 'type' => $type,
287 'ad_weights' => $this->extract_ad_weights_from_meta( $meta_values, $type ),
288 'publish_date' => (string) get_term_meta( $term->term_id, 'publish_date', true ),
289 'modified_date' => (string) get_term_meta( $term->term_id, 'modified_date', true ),
290 ];
291 }
292
293 return $summaries;
294 }
295
296 /**
297 * Extract ad weights from stored group term meta.
298 *
299 * @param mixed $meta_values Group option meta values.
300 * @param string $type Resolved group type.
301 *
302 * @return array<int, int>
303 */
304 private function extract_ad_weights_from_meta( $meta_values, $type ): array {
305 if ( ! is_array( $meta_values ) ) {
306 return [];
307 }
308
309 $meta_values = $this->merge_group_options_meta( $meta_values, $type );
310
311 $ad_weights = $meta_values['ad_weights'] ?? [];
312
313 return is_array( $ad_weights ) ? $ad_weights : [];
314 }
315
316 /**
317 * Hydrate group objects for the given term IDs.
318 *
319 * @param int[] $term_ids Group term IDs.
320 *
321 * @return Group[]
322 */
323 private function hydrate_groups( array $term_ids ): array {
324 $term_ids = $this->normalize_entity_ids( $term_ids );
325
326 if ( ! empty( $term_ids ) ) {
327 if ( function_exists( 'wp_prime_term_caches' ) ) {
328 wp_prime_term_caches( $term_ids, Constants::TAXONOMY_GROUP );
329 } else {
330 foreach ( $term_ids as $term_id ) {
331 get_term( $term_id, Constants::TAXONOMY_GROUP );
332 }
333 }
334
335 update_termmeta_cache( $term_ids );
336 }
337
338 $groups = [];
339 foreach ( $term_ids as $term_id ) {
340 $group = wp_advads_get_group( $term_id );
341
342 if ( $group ) {
343 $groups[ $term_id ] = $group;
344 }
345 }
346
347 return $groups;
348 }
349
350 /**
351 * Get groups associated with a given ad id.
352 *
353 * @param int $ad_id The ID of the ad.
354 *
355 * @return Group[] Groups array
356 */
357 public function get_groups_by_ad_id( $ad_id ) {
358 $ad_id = absint( $ad_id );
359
360 if ( ! $ad_id ) {
361 return [];
362 }
363
364 $group_ids = get_post_meta( $ad_id, Constants::AD_META_GROUP_IDS, true );
365
366 if ( ! is_array( $group_ids ) || empty( $group_ids ) ) {
367 return [];
368 }
369
370 return $this->hydrate_groups( $group_ids );
371 }
372
373 /**
374 * Hydrate group objects for the given term IDs.
375 *
376 * @param int[] $term_ids Group term IDs.
377 *
378 * @return array<int, Group>
379 */
380 public function get_groups_by_ids( array $term_ids ): array {
381 return $this->hydrate_groups( $term_ids );
382 }
383
384 /* Additional Methods ------------------- */
385
386 /**
387 * Read group data. Can be overridden by child classes to load other props.
388 *
389 * @param Group $group Group object.
390 *
391 * @return void
392 */
393 private function read_group_data( &$group ): void {
394 $type = get_term_meta( $group->get_id(), self::TYPE_METAKEY, true );
395 $meta_values = get_term_meta( $group->get_id(), self::OPTION_METAKEY, true );
396 $publish_date = get_term_meta( $group->get_id(), 'publish_date', true );
397 $modified_date = get_term_meta( $group->get_id(), 'modified_date', true );
398
399 if ( ! is_array( $meta_values ) ) {
400 $meta_values = [];
401 }
402
403 $type = self::normalize_group_type( $type ? $type : ( $meta_values['type'] ?? 'default' ) );
404 $meta_values = $this->merge_group_options_meta( $meta_values, $type );
405
406 $meta_values['type'] = $type;
407 $meta_values['publish_date'] = $publish_date ?? '';
408 $meta_values['modified_date'] = $modified_date ?? '';
409
410 $group->set_props( $meta_values );
411
412 foreach ( [ 'random', 'enabled' ] as $prop ) {
413 if ( array_key_exists( $prop, $meta_values ) ) {
414 $value = $meta_values[ $prop ];
415 $value = Formatting::string_to_bool( $value );
416 $group->set_prop( $prop, $value );
417 }
418 }
419 }
420
421 /**
422 * Update group data. Can be overridden by child classes to load other props.
423 *
424 * @param Group $group Group object.
425 *
426 * @return void
427 */
428 private function update_term_meta( &$group ): void {
429 $current_date = current_time( 'mysql', true );
430 $meta_values = [
431 'type' => $group->get_type(),
432 'ad_count' => $group->get_ad_count(),
433 'options' => $group->get_options(),
434 'ad_weights' => $group->get_ad_weights(),
435 ];
436
437 update_term_meta( $group->get_id(), self::TYPE_METAKEY, $group->get_type() );
438 update_term_meta( $group->get_id(), self::OPTION_METAKEY, $meta_values );
439
440 update_term_meta( $group->get_id(), 'modified_date', $current_date );
441 if ( empty( $group->get_publish_date() ) ) {
442 update_term_meta( $group->get_id(), 'publish_date', $current_date );
443 }
444 }
445
446 /**
447 * Normalize stored group type to a registered type slug.
448 *
449 * @param mixed $type Raw type from meta or legacy storage.
450 *
451 * @return string
452 */
453 public static function normalize_group_type( $type ): string {
454 if ( empty( $type ) || 'refresh' === $type ) {
455 return 'default';
456 }
457
458 return (string) $type;
459 }
460
461 /**
462 * Merge per-type options from stored group meta.
463 *
464 * @param array<string, mixed> $meta_values Group option meta values.
465 * @param string $type Normalized group type.
466 *
467 * @return array<string, mixed>
468 */
469 private function merge_group_options_meta( array $meta_values, string $type ): array {
470 if ( ! isset( $meta_values['options'] ) || ! is_array( $meta_values['options'] ) ) {
471 return $meta_values;
472 }
473
474 $bucket = $type;
475
476 if ( ! isset( $meta_values['options'][ $bucket ] ) && 'default' === $type && isset( $meta_values['options']['refresh'] ) ) {
477 $bucket = 'refresh';
478 }
479
480 if ( isset( $meta_values['options'][ $bucket ] ) && is_array( $meta_values['options'][ $bucket ] ) ) {
481 return array_merge( $meta_values['options'][ $bucket ], $meta_values );
482 }
483
484 return $meta_values;
485 }
486 }
487