Completed
Push — master ( 1d71fa...5b2818 )
by J.D.
03:48
created

functions.php ➔ wordpoints_hook_actions_init()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 48
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 3
eloc 24
c 2
b 0
f 0
nc 2
nop 1
dl 0
loc 48
rs 9.125
1
<?php
2
3
/**
4
 * Main functions.
5
 *
6
 * @package wordpoints-hooks-api
7
 * @since 1.0.0
8
 */
9
10
/**
11
 * Initialize the hooks API.
12
 *
13
 * @since 1.0.0
14
 *
15
 * @WordPress\action wordpoints_modules_loaded
16
 */
17
function wordpoints_init_hooks() {
18
19
	$hooks = wordpoints_hooks();
20
21
	// Just accessing this causes it to be initialized. We need to do that so
22
	// the actions will be registered and hooked up. The rest of the API can be
23
	// lazy-loaded as it is needed.
24
	$hooks->get_sub_app( 'actions' );
25
}
26
27
/**
28
 * Register hook reactors when the reactors registry is initialized.
29
 *
30
 * @since 1.0.0
31
 *
32
 * @WordPress\action wordpoints_init_app_registry-hooks-reactors
33
 *
34
 * @param WordPoints_Class_Registry_Persistent $reactors The reactors registry.
35
 */
36
function wordpoints_hook_reactors_init( $reactors ) {
37
38
	$reactors->register( 'points', 'WordPoints_Hook_Reactor_Points' );
39
	$reactors->register( 'points_legacy', 'WordPoints_Hook_Reactor_Points_Legacy' );
40
}
41
42
/**
43
 * Register hook reaction stores when the reaction store registry is initialized.
44
 *
45
 * @since 1.0.0
46
 *
47
 * @WordPress\action wordpoints_init_app_registry-hooks-reaction_stores
48
 *
49
 * @param WordPoints_Class_Registry_Children $reaction_stores The store registry.
50
 */
51
function wordpoints_hook_reaction_stores_init( $reaction_stores ) {
52
53
	$reaction_stores->register(
54
		'standard'
55
		, 'points'
56
		, 'WordPoints_Hook_Reaction_Store_Options'
57
	);
58
59
	if ( is_wordpoints_network_active() ) {
60
		$reaction_stores->register(
61
			'network'
62
			, 'points'
63
			, 'WordPoints_Hook_Reaction_Store_Options_Network'
64
		);
65
	}
66
}
67
68
/**
69
 * Register hook extension when the extension registry is initialized.
70
 *
71
 * @since 1.0.0
72
 *
73
 * @WordPress\action wordpoints_init_app_registry-hooks-extensions
74
 *
75
 * @param WordPoints_Class_Registry_Persistent $extensions The extension registry.
76
 */
77
function wordpoints_hook_extension_init( $extensions ) {
78
79
	$extensions->register( 'blocker', 'WordPoints_Hook_Extension_Blocker' );
80
	$extensions->register( 'repeat_blocker', 'WordPoints_Hook_Extension_Repeat_Blocker' );
81
	$extensions->register( 'reversals', 'WordPoints_Hook_Extension_Reversals' );
82
	$extensions->register( 'reversals_legacy_points', 'WordPoints_Hook_Extension_Reversals_Legacy_Points' );
83
	$extensions->register( 'conditions', 'WordPoints_Hook_Extension_Conditions' );
84
	$extensions->register( 'periods', 'WordPoints_Hook_Extension_Periods' );
85
}
86
87
/**
88
 * Register hook conditions when the conditions registry is initialized.
89
 *
90
 * @since 1.0.0
91
 *
92
 * @WordPress\action wordpoints_init_app_registry-hooks-conditions
93
 *
94
 * @param WordPoints_Class_Registry_Children $conditions The conditions registry.
95
 */
96
function wordpoints_hook_conditions_init( $conditions ) {
97
98
	$conditions->register(
99
		'text'
100
		, 'contains'
101
		, 'WordPoints_Hook_Condition_String_Contains'
102
	);
103
104
	$conditions->register(
105
		'text'
106
		, 'equals'
107
		, 'WordPoints_Hook_Condition_Equals'
108
	);
109
110
	$conditions->register(
111
		'entity'
112
		, 'equals'
113
		, 'WordPoints_Hook_Condition_Equals'
114
	);
115
116
	$conditions->register(
117
		'entity_array'
118
		, 'contains'
119
		, 'WordPoints_Hook_Condition_Entity_Array_Contains'
120
	);
121
}
122
123
/**
124
 * Register hook actions when the action registry is initialized.
125
 *
126
 * @since 1.0.0
127
 *
128
 * @WordPress\action wordpoints_init_app_registry-hooks-actions
129
 *
130
 * @param WordPoints_Hook_Actions $actions The action registry.
131
 */
132
function wordpoints_hook_actions_init( $actions ) {
133
134
	$actions->register(
135
		'user_register'
136
		, 'WordPoints_Hook_Action'
137
		, array(
138
			'action' => 'user_register',
139
			'data'   => array(
140
				'arg_index' => array( 'user' => 0 ),
141
			),
142
		)
143
	);
144
145
	$actions->register(
146
		'user_delete'
147
		, 'WordPoints_Hook_Action'
148
		, array(
149
			'action' => is_multisite() ? 'wpmu_delete_user' : 'delete_user',
150
			'data'   => array(
151
				'arg_index' => array( 'user' => 0 ),
152
			),
153
		)
154
	);
155
156
	$actions->register(
157
		'user_visit'
158
		, 'WordPoints_Hook_Action'
159
		, array(
160
			'action' => 'wp',
161
		)
162
	);
163
164
	// Register actions for all of the public post types.
165
	$post_types = get_post_types( array( 'public' => true ) );
166
167
	/**
168
	 * Filter which post types to register hook actions for.
169
	 *
170
	 * @since 1.0.0
171
	 *
172
	 * @param string[] The post type slugs ("names").
173
	 */
174
	$post_types = apply_filters( 'wordpoints_register_hook_actions_for_post_types', $post_types );
175
176
	foreach ( $post_types as $slug ) {
177
		wordpoints_register_post_type_hook_actions( $slug );
178
	}
179
}
180
181
/**
182
 * Register the hook actions for a post type.
183
 *
184
 * @since 1.0.0
185
 *
186
 * @param string $slug The slug of the post type.
187
 */
188
function wordpoints_register_post_type_hook_actions( $slug ) {
189
190
	$actions = wordpoints_hooks()->get_sub_app( 'actions' );
191
192
	if ( post_type_supports( $slug, 'comments' ) ) {
193
194
		$actions->register(
195
			"comment_approve\\{$slug}"
196
			, 'WordPoints_Hook_Action_Post_Type_Comment'
197
			, array(
198
				'action' => 'transition_comment_status',
199
				'data'   => array(
200
					'arg_index'    => array( "comment\\{$slug}" => 2 ),
201
					'requirements' => array( 0 => 'approved' ),
202
				),
203
			)
204
		);
205
206
		$actions->register(
207
			"comment_new\\{$slug}"
208
			, 'WordPoints_Hook_Action_Comment_New'
209
			, array(
210
				'action' => 'wp_insert_comment',
211
				'data'   => array(
212
					'arg_index' => array( "comment\\{$slug}" => 1 ),
213
				),
214
			)
215
		);
216
217
		$actions->register(
218
			"comment_deapprove\\{$slug}"
219
			, 'WordPoints_Hook_Action_Post_Type_Comment'
220
			, array(
221
				'action' => 'transition_comment_status',
222
				'data'   => array(
223
					'arg_index'    => array( "comment\\{$slug}" => 2 ),
224
					'requirements' => array( 1 => 'approved' ),
225
				),
226
			)
227
		);
228
	}
229
230
	// This works for all post types except attachments.
231
	if ( 'attachment' !== $slug ) {
232
233
		$actions->register(
234
			"post_publish\\{$slug}"
235
			, 'WordPoints_Hook_Action_Post_Type'
236
			, array(
237
				'action' => 'transition_post_status',
238
				'data'   => array(
239
					'arg_index'    => array( "post\\{$slug}" => 2 ),
240
					'requirements' => array( 0 => 'publish' ),
241
				),
242
			)
243
		);
244
245
		$actions->register(
246
			"post_depublish\\{$slug}"
247
			, 'WordPoints_Hook_Action_Post_Type'
248
			, array(
249
				'action' => 'transition_post_status',
250
				'data'   => array(
251
					'arg_index'    => array( "post\\{$slug}" => 2 ),
252
					'requirements' => array( 1 => 'publish' ),
253
				),
254
			)
255
		);
256
257
		$actions->register(
258
			"post_depublish_delete\\{$slug}"
259
			, 'WordPoints_Hook_Action_Post_Depublish_Delete'
260
			, array(
261
				'action' => 'delete_post',
262
				'data'   => array(
263
					'arg_index' => array( "post\\{$slug}" => 0 ),
264
				),
265
			)
266
		);
267
268
	} else {
269
270
		$actions->register(
271
			'add_attachment'
272
			, 'WordPoints_Hook_Action'
273
			, array(
274
				'action' => 'add_attachment',
275
				'data'   => array(
276
					'arg_index' => array( 'post\attachment' => 0 ),
277
				),
278
			)
279
		);
280
281
		$actions->register(
282
			"post_delete\\{$slug}"
283
			, 'WordPoints_Hook_Action_Post_Type'
284
			, array(
285
				'action' => 'delete_post',
286
				'data'   => array(
287
					'arg_index' => array( "post\\{$slug}" => 0 ),
288
				),
289
			)
290
		);
291
	}
292
293
	/**
294
	 * Fires when registering the hook actions for a post type.
295
	 *
296
	 * @since 1.0.0
297
	 *
298
	 * @param string $slug The slug ("name") of the post type.
299
	 */
300
	do_action( 'wordpoints_register_post_type_hook_actions', $slug );
301
}
302
303
/**
304
 * Register hook events when the event registry is initialized.
305
 *
306
 * @since 1.0.0
307
 *
308
 * @WordPress\action wordpoints_init_app_registry-hooks-events
309
 *
310
 * @param WordPoints_Hook_Events $events The event registry.
311
 */
312
function wordpoints_hook_events_init( $events ) {
313
314
	$events->register(
315
		'user_register'
316
		, 'WordPoints_Hook_Event_User_Register'
317
		, array(
318
			'actions' => array(
319
				'toggle_on'  => 'user_register',
320
				'toggle_off' => 'user_delete',
321
			),
322
			'args' => array(
323
				'user' => 'WordPoints_Hook_Arg',
324
			),
325
		)
326
	);
327
328
	$events->register(
329
		'user_visit'
330
		, 'WordPoints_Hook_Event_User_Visit'
331
		, array(
332
			'actions' => array(
333
				'fire' => 'user_visit',
334
			),
335
			'args' => array(
336
				'current:user' => 'WordPoints_Hook_Arg_Current_User',
337
			),
338
		)
339
	);
340
341
	// Register events for all of the public post types.
342
	$post_types = get_post_types( array( 'public' => true ) );
343
344
	/**
345
	 * Filter which post types to register hook events for.
346
	 *
347
	 * @since 1.0.0
348
	 *
349
	 * @param string[] The post type slugs ("names").
350
	 */
351
	$post_types = apply_filters( 'wordpoints_register_hook_events_for_post_types', $post_types );
352
353
	foreach ( $post_types as $slug ) {
354
		wordpoints_register_post_type_hook_events( $slug );
355
	}
356
}
357
358
/**
359
 * Register sub-apps when the Entities app is initialized.
360
 *
361
 * @since 1.0.0
362
 *
363
 * @WordPress\action wordpoints_init_app-entities
364
 *
365
 * @param WordPoints_App_Registry $entities The entities app.
366
 */
367
function wordpoints_entities_app_init( $entities ) {
368
369
	$sub_apps = $entities->sub_apps();
370
	$sub_apps->register( 'children', 'WordPoints_Class_Registry_Children' );
371
	$sub_apps->register( 'contexts', 'WordPoints_Class_Registry' );
372
}
373
374
/**
375
 * Register entity contexts when the registry is initialized.
376
 *
377
 * @since 1.0.0
378
 *
379
 * @WordPress\action wordpoints_init_app_registry-entities-contexts
380
 *
381
 * @param WordPoints_Class_RegistryI $contexts The entity context registry.
382
 */
383
function wordpoints_entity_contexts_init( $contexts ) {
384
385
	$contexts->register( 'network', 'WordPoints_Entity_Context_Network' );
386
	$contexts->register( 'site', 'WordPoints_Entity_Context_Site' );
387
}
388
389
/**
390
 * Register entities when the entities app is initialized.
391
 *
392
 * @since 1.0.0
393
 *
394
 * @WordPress\action wordpoints_init_app_registry-apps-entities
395
 *
396
 * @param WordPoints_App_Registry $entities The entities app.
397
 */
398
function wordpoints_entities_init( $entities ) {
399
400
	$children = $entities->get_sub_app( 'children' );
401
402
	$entities->register( 'user', 'WordPoints_Entity_User' );
403
	$children->register( 'user', 'roles', 'WordPoints_Entity_User_Roles' );
404
405
	$entities->register( 'user_role', 'WordPoints_Entity_User_Role' );
406
407
	// Register entities for all of the public post types.
408
	$post_types = get_post_types( array( 'public' => true ) );
409
410
	/**
411
	 * Filter which post types to register entities for.
412
	 *
413
	 * @since 1.0.0
414
	 *
415
	 * @param string[] The post type slugs ("names").
416
	 */
417
	$post_types = apply_filters( 'wordpoints_register_entities_for_post_types', $post_types );
418
419
	foreach ( $post_types as $slug ) {
420
		wordpoints_register_post_type_entities( $slug );
421
	}
422
423
	// Register entities for all of the public taxonomies.
424
	$taxonomies = get_taxonomies( array( 'public' => true ) );
425
426
	/**
427
	 * Filter which taxonomies to register entities for.
428
	 *
429
	 * @since 1.0.0
430
	 *
431
	 * @param string[] The taxonomy slugs.
432
	 */
433
	$taxonomies = apply_filters( 'wordpoints_register_entities_for_taxonomies', $taxonomies );
434
435
	foreach ( $taxonomies as $slug ) {
436
		wordpoints_register_taxonomy_entities( $slug );
437
	}
438
}
439
440
/**
441
 * Register the entities for a post type.
442
 *
443
 * @since 1.0.0
444
 *
445
 * @param string $slug The slug of the post type.
446
 */
447
function wordpoints_register_post_type_entities( $slug ) {
448
449
	$entities = wordpoints_entities();
450
	$children = $entities->get_sub_app( 'children' );
451
452
	$entities->register( "post\\{$slug}", 'WordPoints_Entity_Post' );
453
	$children->register( "post\\{$slug}", 'author', 'WordPoints_Entity_Post_Author' );
454
455
	$supports = get_all_post_type_supports( $slug );
456
457
	if ( isset( $supports['editor'] ) ) {
458
		$children->register( "post\\{$slug}", 'content', 'WordPoints_Entity_Post_Content' );
459
	}
460
461
	if ( isset( $supports['comments'] ) ) {
462
		$entities->register( "comment\\{$slug}", 'WordPoints_Entity_Comment' );
463
		$children->register( "comment\\{$slug}", "post\\{$slug}", 'WordPoints_Entity_Comment_Post' );
464
		$children->register( "comment\\{$slug}", 'author', 'WordPoints_Entity_Comment_Author' );
465
	}
466
467
	foreach ( get_object_taxonomies( $slug ) as $taxonomy_slug ) {
468
		$children->register( "post\\{$slug}", "terms\\{$taxonomy_slug}", 'WordPoints_Entity_Post_Terms' );
469
	}
470
471
	/**
472
	 * Fired when registering the entities for a post type.
473
	 *
474
	 * @since 1.0.0
475
	 *
476
	 * @param string $slug The slug ("name") of the post type.
477
	 */
478
	do_action( 'wordpoints_register_post_type_entities', $slug );
479
}
480
481
/**
482
 * Register the hook events for a post type.
483
 *
484
 * @since 1.0.0
485
 *
486
 * @param string $slug The slug of the post type.
487
 */
488
function wordpoints_register_post_type_hook_events( $slug ) {
489
490
	$events = wordpoints_hooks()->get_sub_app( 'events' );
491
492
	if ( 'attachment' === $slug ) {
493
494
		$events->register(
495
			'media_upload'
496
			, 'WordPoints_Hook_Event_Media_Upload'
497
			, array(
498
				'actions' => array(
499
					'toggle_on'  => 'add_attachment',
500
					'toggle_off' => "post_delete\\{$slug}",
501
				),
502
				'args'    => array(
503
					"post\\{$slug}" => 'WordPoints_Hook_Arg',
504
				),
505
			)
506
		);
507
508 View Code Duplication
	} else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
509
510
		$events->register(
511
			"post_publish\\{$slug}"
512
			, 'WordPoints_Hook_Event_Post_Publish'
513
			, array(
514
				'actions' => array(
515
					'toggle_on'  => "post_publish\\{$slug}",
516
					'toggle_off' => array(
517
						"post_depublish\\{$slug}",
518
						"post_depublish_delete\\{$slug}",
519
					),
520
				),
521
				'args'    => array(
522
					"post\\{$slug}" => 'WordPoints_Hook_Arg',
523
				),
524
			)
525
		);
526
	}
527
528 View Code Duplication
	if ( post_type_supports( $slug, 'comments' ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
529
530
		$events->register(
531
			"comment_leave\\{$slug}"
532
			, 'WordPoints_Hook_Event_Comment_Leave'
533
			, array(
534
				'actions' => array(
535
					'toggle_on'  => array(
536
						"comment_approve\\{$slug}",
537
						"comment_new\\{$slug}",
538
					),
539
					'toggle_off' => "comment_deapprove\\{$slug}",
540
				),
541
				'args' => array(
542
					"comment\\{$slug}" => 'WordPoints_Hook_Arg',
543
				),
544
			)
545
		);
546
	}
547
548
	/**
549
	 * Fires when registering the hook events for a post type.
550
	 *
551
	 * @since 1.0.0
552
	 *
553
	 * @param string $slug The slug ("name") of the post type.
554
	 */
555
	do_action( 'wordpoints_register_post_type_hook_events', $slug );
556
}
557
558
/**
559
 * Register the entities for a taxonomy.
560
 *
561
 * @since 1.0.0
562
 *
563
 * @param string $slug The slug of the taxonomy.
564
 */
565
function wordpoints_register_taxonomy_entities( $slug ) {
566
567
	$entities = wordpoints_entities();
568
	$children = $entities->get_sub_app( 'children' );
569
570
	$entities->register( "term\\{$slug}", 'WordPoints_Entity_Term' );
571
	$children->register( "term\\{$slug}", 'id', 'WordPoints_Entity_Term_Id' );
572
573
	/**
574
	 * Fired when registering the entities for a taxonomy.
575
	 *
576
	 * @since 1.0.0
577
	 *
578
	 * @param string $slug The taxonomy's slug.
579
	 */
580
	do_action( 'wordpoints_register_taxonomy_entities', $slug );
581
}
582
583
/**
584
 * Register the data types with the data types registry is initialized.
585
 *
586
 * @since 1.0.0
587
 *
588
 * @WordPress\action wordpoints_init_app_registry-apps-data_types
589
 *
590
 * @param WordPoints_Class_RegistryI $data_types The data types registry.
591
 */
592
function wordpoints_data_types_init( $data_types ) {
593
594
	$data_types->register( 'integer', 'WordPoints_Data_Type_Integer' );
595
	$data_types->register( 'text', 'WordPoints_Data_Type_Text' );
596
}
597
598
/**
599
 * Check whether a user can view a points log.
600
 *
601
 * @since 1.0.0
602
 *
603
 * @WordPress\filter wordpoints_user_can_view_points_log
604
 *
605
 * @param bool   $can_view Whether the user can view the points log.
606
 * @param object $log      The points log's data.
607
 *
608
 * @return bool Whether the user can view the points log.
609
 */
610
function wordpoints_hooks_user_can_view_points_log( $can_view, $log ) {
611
612
	if ( ! $can_view ) {
613
		return $can_view;
614
	}
615
616
	$user_id = get_current_user_id();
617
618
	$event_slug = $log->log_type;
619
620
	/** @var WordPoints_Hook_ArgI $arg */
621
	foreach ( wordpoints_hooks()->get_sub_app( 'events' )->get_sub_app( 'args' )->get_children( $event_slug ) as $slug => $arg ) {
622
623
		$value = wordpoints_get_points_log_meta( $log->id, $slug, true );
624
625
		if ( ! $value ) {
626
			continue;
627
		}
628
629
		$can_view = wordpoints_entity_user_can_view(
630
			$user_id
631
			, $arg->get_entity_slug()
632
			, $value
633
		);
634
635
		if ( ! $can_view ) {
636
			break;
637
		}
638
	}
639
640
	return $can_view;
641
}
642
643
/**
644
 * Check whether a user can view an entity.
645
 *
646
 * @since 1.0.0
647
 *
648
 * @param int    $user_id     The user ID.
649
 * @param string $entity_slug The slug of the entity type.
650
 * @param mixed  $entity_id   The entity ID.
651
 *
652
 * @return bool Whether the user can view this entity.
653
 */
654
function wordpoints_entity_user_can_view( $user_id, $entity_slug, $entity_id ) {
655
656
	$entity = wordpoints_entities()->get( $entity_slug );
657
658
	// If this entity type is not found, we have no way of determining whether it is
659
	// safe for the user to view it.
660
	if ( ! ( $entity instanceof WordPoints_Entity ) ) {
661
		return false;
662
	}
663
664
	$can_view = true;
665
666
	if ( $entity instanceof WordPoints_Entity_Restricted_VisibilityI ) {
667
		$can_view = $entity->user_can_view( $user_id, $entity_id );
668
	}
669
670
	/**
671
	 * Filter whether a user can view an entity.
672
	 *
673
	 * @since 1.0.0
674
	 *
675
	 * @param bool              $can_view  Whether the user can view the entity.
676
	 * @param int               $user_id   The user ID.
677
	 * @param int               $entity_id The entity ID.
678
	 * @param WordPoints_Entity $entity    The entity object.
679
	 */
680
	return apply_filters(
681
		'wordpoints_entity_user_can_view'
682
		, $can_view
683
		, $user_id
684
		, $entity_id
685
		, $entity
686
	);
687
}
688
689
/**
690
 * Get the main WordPoints app.
691
 *
692
 * @since 1.0.0
693
 *
694
 * @return WordPoints_App The main WordPoints app.
695
 */
696
function wordpoints_apps() {
697
698
	if ( ! isset( WordPoints_App::$main ) ) {
699
		WordPoints_App::$main = new WordPoints_App( 'apps' );
700
	}
701
702
	return WordPoints_App::$main;
703
}
704
705
/**
706
 * Get the hooks app.
707
 *
708
 * @since 1.0.0
709
 *
710
 * @return WordPoints_Hooks The hooks app.
711
 */
712
function wordpoints_hooks() {
713
714
	if ( ! isset( WordPoints_App::$main ) ) {
715
		wordpoints_apps();
716
	}
717
718
	return WordPoints_App::$main->get_sub_app( 'hooks' );
719
}
720
721
/**
722
 * Get the entities app.
723
 *
724
 * @since 1.0.0
725
 *
726
 * @return WordPoints_App_Registry The hooks app.
727
 */
728
function wordpoints_entities() {
729
730
	if ( ! isset( WordPoints_App::$main ) ) {
731
		wordpoints_apps();
732
	}
733
734
	return WordPoints_App::$main->get_sub_app( 'entities' );
735
}
736
737
/**
738
 * Register sub apps when the apps app is initialized.
739
 *
740
 * @since 1.0.0
741
 *
742
 * @WordPress\action wordpoints_init_app-apps
743
 *
744
 * @param WordPoints_App $app The main apps app.
745
 */
746
function wordpoints_apps_init( $app ) {
747
748
	$apps = $app->sub_apps();
749
750
	$apps->register( 'hooks', 'WordPoints_Hooks' );
751
	$apps->register( 'entities', 'WordPoints_App_Registry' );
752
	$apps->register( 'data_types', 'WordPoints_Class_Registry' );
753
}
754
755
/**
756
 * Construct a class with a variable number of args.
757
 *
758
 * @since 1.0.0
759
 *
760
 * @param string $class_name The name of the class to construct.
761
 * @param array  $args       Up to 4 args to pass to the constructor.
762
 *
763
 * @return object|false The constructed object, or false if to many args were passed.
764
 */
765
function wordpoints_construct_class_with_args( $class_name, array $args ) {
766
767
	switch ( count( $args ) ) {
768
		case 0:
769
			return new $class_name();
770
		case 1:
771
			return new $class_name( $args[0] );
772
		case 2:
773
			return new $class_name( $args[0], $args[1] );
774
		case 3:
775
			return new $class_name( $args[0], $args[1], $args[2] );
776
		case 4:
777
			return new $class_name( $args[0], $args[1], $args[2], $args[3] );
778
		default:
779
			return false;
780
	}
781
}
782
783
/**
784
 * Parse a dynamic slug into the dynamic and generic components.
785
 *
786
 * In the hooks and entities APIs, we have a convention of using dynamic slugs when
787
 * certain elements are registered dynamically. Such slugs are of the following
788
 * format: <generic part>\<dynamic part>. In other words, the generic and dynamic
789
 * parts are separated by a backslash. This function provides a canonical method of
790
 * parsing a slug into its constituent parts.
791
 *
792
 * @since 1.0.0
793
 *
794
 * @param string $slug A slug (for an entity or hook event, for example).
795
 *
796
 * @return array The slug parsed into the 'generic' and 'dynamic' portions. If the
797
 *               slug is not dynamic, the value of each of those keys will be false.
798
 */
799
function wordpoints_parse_dynamic_slug( $slug ) {
800
801
	$parsed = array( 'dynamic' => false, 'generic' => false );
802
803
	$parts = explode( '\\', $slug, 2 );
804
805
	if ( isset( $parts[1] ) ) {
806
		$parsed['dynamic'] = $parts[1];
807
		$parsed['generic'] = $parts[0];
808
	}
809
810
	return $parsed;
811
}
812
813
/**
814
 * Get the GUID of the current entity context.
815
 *
816
 * Most entities exist only in the context of a specific site on the network (in
817
 * multisite—when not on multisite they are just global to the install). An
818
 * example of this would be a Post: a post on one site with the ID 5 is different
819
 * than a post with that same ID on another site. To get the ID of such an entity's
820
 * context, you would pass 'site' as the value of the `$slug` arg, and the IDs for
821
 * both the 'site' and 'network' contexts would be returned.
822
 *
823
 * Some entities exist in the context of the network itself, not any particular
824
 * site. You can get the ID for the context of such an entity by passing 'network'
825
 * as the value of `$slug`.
826
 *
827
 * Still other entities are global to the install, existing across all networks even
828
 * on a multi-network installation. An example of this would be a User: the user with
829
 * the ID 3 is the same on every site on the network, and every network in the
830
 * install.
831
 *
832
 * Some entities might exist in other contexts entirely.
833
 *
834
 * The context IDs are returned in ascending hierarchical order.
835
 *
836
 * @since 1.0.0
837
 *
838
 * @param string $slug The slug of the context you want to get the current GUID of.
839
 *
840
 * @return array|false The ID of the context you passed in and the IDs of its parent
841
 *                     contexts, indexed by context slug, or false if any of the
842
 *                     contexts isn't current.
843
 */
844
function wordpoints_entities_get_current_context_id( $slug ) {
845
846
	$current_context = array();
847
848
	/** @var WordPoints_Class_Registry $contexts */
849
	$contexts = wordpoints_entities()->get_sub_app( 'contexts' );
850
851
	while ( $slug ) {
852
853
		$context = $contexts->get( $slug );
854
855
		if ( ! $context instanceof WordPoints_Entity_Context ) {
856
			return false;
857
		}
858
859
		$id = $context->get_current_id();
860
861
		if ( false === $id ) {
862
			return false;
863
		}
864
865
		$current_context[ $slug ] = $id;
866
867
		$slug = $context->get_parent_slug();
868
	}
869
870
	return $current_context;
871
}
872
873
/**
874
 * Checks if we are in network context.
875
 *
876
 * There are times on multisite when we are in the context of the network as a whole,
877
 * and not in the context of any particular site. This includes the network admin
878
 * screens, and Ajax requests that originate from them.
879
 *
880
 * @since 1.0.0
881
 *
882
 * @return bool Whether we are in network context.
883
 */
884
function wordpoints_is_network_context() {
885
886
	if ( ! is_multisite() ) {
887
		return false;
888
	}
889
890
	if ( is_network_admin() ) {
891
		return true;
892
	}
893
894
	// See https://core.trac.wordpress.org/ticket/22589
895
	if (
896
		defined( 'DOING_AJAX' )
897
		&& DOING_AJAX
898
		&& isset( $_SERVER['HTTP_REFERER'] )
899
		&& preg_match(
900
			'#^' . preg_quote( network_admin_url(), '#' ) . '#i'
901
			, esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) )
902
		)
903
	) {
904
		return true;
905
	}
906
907
	/**
908
	 * Filter whether we are currently in network context.
909
	 *
910
	 * @since 1.0.0
911
	 *
912
	 * @param bool $in_network_context Whether we are in network context.
913
	 */
914
	return apply_filters( 'wordpoints_is_network_context', false );
915
}
916
917
/**
918
 * Get the GUID of the primary arg of an event, serialized as JSON.
919
 *
920
 * If the event does not have a primary arg, an empty string will be returned.
921
 *
922
 * @since 1.0.0
923
 *
924
 * @param WordPoints_Hook_Event_Args $event_args The event args.
925
 *
926
 * @return string The primary arg's GUID, JSON encoded.
927
 */
928
function wordpoints_hooks_get_event_primary_arg_guid_json( WordPoints_Hook_Event_Args $event_args ) {
929
930
	$entity = $event_args->get_primary_arg();
931
932
	if ( ! $entity ) {
933
		return '';
934
	}
935
936
	$the_guid = $entity->get_the_guid();
937
938
	if ( ! $the_guid ) {
939
		return '';
940
	}
941
942
	return wp_json_encode( $the_guid );
943
}
944
945
/**
946
 * Register the global cache groups.
947
 *
948
 * @since 1.0.0
949
 *
950
 * @WordPress\action init 5 Earlier than the default so that the groups will be
951
 *                          registered before any other code runs.
952
 */
953
function wordpoints_hooks_api_add_global_cache_groups() {
954
955
	if ( function_exists( 'wp_cache_add_global_groups' ) ) {
956
957
		wp_cache_add_global_groups(
958
			array(
959
				'wordpoints_hook_periods',
960
				'wordpoints_hook_period_ids_by_reaction',
961
			)
962
		);
963
	}
964
}
965
966
/**
967
 * Escape a MySQL identifier.
968
 *
969
 * Quotes the identifier with backticks and escapes any backticks within it by
970
 * doubling them.
971
 *
972
 * @since 1.0.0
973
 *
974
 * @link https://dev.mysql.com/doc/refman/5.7/en/identifiers.html#idm139700789409120
975
 *
976
 * @param string $identifier The identifier (column, table, alias, etc.).
977
 *
978
 * @return string The escaped identifier. Already quoted, do not place within
979
 *                backticks.
980
 */
981
function wordpoints_escape_mysql_identifier( $identifier ) {
982
	return '`' . str_replace( '`', '``', $identifier ) . '`';
983
}
984
985
986
/**
987
 * Get an option or network option that must be an array.
988
 *
989
 * This is a wrapper for {@see wordpoints_get_maybe_network_option()} that will force
990
 * the return value to be an array.
991
 *
992
 * @since 1.0.0
993
 *
994
 * @param string $option The name of the option to get.
995
 * @param bool   $network Whether to retrieve a network option, or a regular option.
996
 *                        By default a regular option will be retrieved, unless
997
 *                        WordPoints is network active, in which case a network
998
 *                        option will be retrieved.
999
 *
1000
 * @return array The option value if it is an array, or an empty array if not.
1001
 */
1002
function wordpoints_get_maybe_network_array_option( $option, $network = null ) {
1003
1004
	$value = wordpoints_get_maybe_network_option( $option, $network );
1005
1006
	if ( ! is_array( $value ) ) {
1007
		$value = array();
1008
	}
1009
1010
	return $value;
1011
}
1012
1013
/**
1014
 * Get an option or network option from the database.
1015
 *
1016
 * @since 1.0.0
1017
 *
1018
 * @param string $option  The name of the option to get.
1019
 * @param bool   $network Whether to retrieve a network option, or a regular option.
1020
 *                        By default a regular option will be retrieved, unless
1021
 *                        WordPoints is network active, in which case a network
1022
 *                        option will be retrieved.
1023
 * @param mixed  $default A default value to return if the option isn't found.
1024
 *
1025
 * @return mixed The option value if it exists, or $default (false by default).
1026
 */
1027
function wordpoints_get_maybe_network_option( $option, $network = null, $default = false ) {
1028
1029
	if ( $network || ( null === $network && is_wordpoints_network_active() ) ) {
1030
		return get_site_option( $option, $default );
1031
	} else {
1032
		return get_option( $option, $default );
1033
	}
1034
}
1035
1036
/**
1037
 * Add an option or network option.
1038
 *
1039
 * @since 1.0.0
1040
 *
1041
 * @param string $option   The name of the option to add.
1042
 * @param mixed  $value    The value for the option.
1043
 * @param bool   $network  Whether to add a network option, or a regular option. By
1044
 *                         default a regular option will be added, unless WordPoints
1045
 *                         is network active, in which case a network option will be
1046
 *                         added.
1047
 * @param string $autoload Whether to automatically load the option. 'yes' (default)
1048
 *                         or 'no'. Does not apply if WordPoints is network active.
1049
 *
1050
 * @return bool Whether the option was added successfully.
1051
 */
1052
function wordpoints_add_maybe_network_option( $option, $value, $network = null, $autoload = 'yes' ) {
1053
1054 View Code Duplication
	if ( $network || ( null === $network && is_wordpoints_network_active() ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1055
		return add_site_option( $option, $value );
1056
	} else {
1057
		return add_option( $option, $value, '', $autoload );
1058
	}
1059
}
1060
1061
/**
1062
 * Update an option or network option.
1063
 *
1064
 * @since 1.0.0
1065
 *
1066
 * @param string $option  The name of the option to update.
1067
 * @param mixed  $value   The new value for the option.
1068
 * @param bool   $network Whether to update a network option, or a regular option.
1069
 *                        By default a regular option will be updated, unless
1070
 *                        WordPoints is network active, in which case a network
1071
 *                        option will be updated.
1072
 *
1073
 * @return bool Whether the option was updated successfully.
1074
 */
1075
function wordpoints_update_maybe_network_option( $option, $value, $network = null ) {
1076
1077 View Code Duplication
	if ( $network || ( null === $network && is_wordpoints_network_active() ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1078
		return update_site_option( $option, $value );
1079
	} else {
1080
		return update_option( $option, $value );
1081
	}
1082
}
1083
1084
/**
1085
 * Delete an option or network option.
1086
 *
1087
 * @since 1.0.0
1088
 *
1089
 * @param string $option  The name of the option to delete.
1090
 * @param bool   $network Whether to delete a network option, or a regular option.
1091
 *                        By default a regular option will be deleted, unless
1092
 *                        WordPoints is network active, in which case a network
1093
 *                        option will be deleted.
1094
 *
1095
 * @return bool Whether the option was successfully deleted.
1096
 */
1097
function wordpoints_delete_maybe_network_option( $option, $network = null ) {
1098
1099
	if ( $network || ( null === $network && is_wordpoints_network_active() ) ) {
1100
		return delete_site_option( $option );
1101
	} else {
1102
		return delete_option( $option );
1103
	}
1104
}
1105
1106
// EOF
1107