PluginProbe
Tag Groups is the Advanced Way to Display Your Taxonomy Terms / trunk
Tag Groups is the Advanced Way to Display Your Taxonomy Terms vtrunk
2.2.2 2.2.1 2.2.0 trunk 1.40.0 1.40.2 1.41.0 1.42.1 1.43.0 1.43.1 1.43.10 1.43.10.1 1.43.2 1.43.3 1.43.4 1.43.5 1.43.6 1.43.7 1.43.9 1.44.0 1.44.1 1.44.3 1.44.3.1 2.0.0 2.0.1 All 36 releases
tag-groups / include / helpers / class.hooks.php

class.hooks.php in Tag Groups is the Advanced Way to Display Your Taxonomy Terms trunk, at include/helpers/class.hooks.php

443 lines 17.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * @package Tag Groups
5 *
6 * @author Christoph Amthor
7 * @copyright 2020 Christoph Amthor (@ Chatty Mango, chattymango.com)
8 * @license GPL-3.0+
9 */
10
11 // phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace, Squiz.Classes.ValidClassName.NotCamelCaps, PSR1.Methods.CamelCapsMethodName.NotCamelCaps
12 if (!class_exists('TagGroups_Hooks')) {
13 /**
14 *
15 */
16 class TagGroups_Hooks
17 {
18 /**
19 * does all initialization
20 *
21 * @var object
22 */
23 private $loader ;
24 /**
25 * enqueues js and css
26 *
27 * @var object
28 */
29 private $enqueue ;
30 /**
31 * Array of registered hooks for temporary removal
32 *
33 * @var array
34 */
35 private $hooks ;
36 /**
37 * constructor
38 *
39 * @param object $loader
40 */
41 public function __construct($loader = null)
42 {
43 if (!empty($loader)) {
44 $this->loader = $loader;
45 }
46 $this->enqueue = new TagGroups_Enqueue();
47 }
48
49 /**
50 * Runs when plugin is launched
51 *
52 * @return void
53 */
54 public function root_all()
55 {
56 global $tag_group_terms ;
57 /**
58 * enable internationalization
59 */
60 if (!empty($this->loader)) {
61 add_action('init', array( $this->loader, 'register_textdomain' ));
62 }
63 /**
64 * Filter that allows to modify the term query and search for terms that have tags in the specified tag groups
65 *
66 * @param array arguments for WP Term Query
67 * @param array|int|string Tag Group IDs (array of integers or comma-separated list of integers)
68 * @param string Logic relation between the Tag Group IDs (AND|OR)
69 * @return array arguments for WP Term Query
70 */
71 add_filter(
72 'tag_groups_modify_term_query_args',
73 array( $tag_group_terms, 'modify_query_args' ),
74 10,
75 3
76 );
77 }
78
79 /**
80 * Runs when plugin is launched and is_admin()
81 *
82 * @return void
83 */
84 public function is_admin()
85 {
86 add_action('admin_init', array( $this, 'admin_init' ));
87 add_action('admin_menu', array( 'TagGroups_Admin', 'register_menus' ));
88 add_action('admin_menu', array( 'TagGroups_Admin', 'remove_submenus' ), 1000000000);
89 add_action('admin_enqueue_scripts', array( $this->enqueue, 'admin_enqueue_scripts' ));
90 /**
91 * Display any admin notices from the queue
92 */
93 add_action('admin_notices', array( 'TagGroups_Admin_Notice', 'display' ));
94 add_action('admin_post_tag_groups_download_export', array( 'TagGroups_Export', 'download_file' ));
95 /**
96 * Add own category to Gutenberg
97 */
98 add_filter('block_categories_all', array( 'TagGroups_Gutenberg', 'block_categories' ));
99 /**
100 * Processing routines in chunks with process bar
101 */
102 add_action('wp_ajax_tg_free_ajax_process', array( 'TagGroups_Process', 'tg_ajax_process' ));
103 /**
104 * #### Terms
105 */
106 /**
107 * After a term has changed its groups, we must update the array of terms per group.
108 */
109 add_action('tag_groups_groups_of_term_saved', array( 'TagGroups_Group_Save_Handlers', 'schedule_clear_tag_groups_group_terms' ), 11);
110 /**
111 * After a term has been deleted, we might have to update the object cache
112 */
113 add_action('delete_term', array( 'TagGroups_Group_Save_Handlers', 'schedule_clear_tag_groups_group_terms' ), 20);
114 /**
115 * After a term has been edited, we need to refresh some transients
116 */
117 add_action('edited_term', array( 'TagGroups_Transients', 'clear_transients_for_frontend_features' ), 20);
118 if (TagGroups_Options::get_option('tag_group_multilingual_sync_groups', 1)) {
119 /**
120 * After a term has beend edited, we may have to sync the groups of all translations
121 */
122 add_action(
123 'edited_term',
124 array( 'TagGroups_WPML', 'sync_groups' ),
125 20,
126 3
127 );
128 }
129 /**
130 * Plugin: Simple Custom Post Order
131 */
132 /**
133 * After the term order has been changed, we need to refresh some transients
134 */
135 add_action('scp_update_menu_order_tags', array( 'TagGroups_Transients', 'clear_transients_for_frontend_features' ), 20);
136 /**
137 * Plugin: Custom Taxonomy Order
138 */
139 /**
140 * After the term order has been changed, we need to refresh some transients
141 */
142 add_action('customtaxorder_update_order', array( 'TagGroups_Transients', 'clear_transients_for_frontend_features' ), 20);
143 /**
144 * #### Groups
145 */
146 /**
147 * After a term group order has possibly been changed, we should sort the groups in the term meta
148 */
149 add_action('term_group_saved', array( 'TagGroups_Term_Meta_Tools', 'sort_groups' ));
150 /**
151 * After a term group has been deleted, we must update the tag meta with the groups.
152 */
153 add_action('tag_groups_term_group_deleted', array( 'TagGroups_Term_Meta_Tools', 'remove_missing_groups' ));
154 /**
155 * #### Taxonomies
156 */
157 /**
158 * After the taxonomies have been changed, we check if we must migrate all newly enabled tags.
159 */
160 add_action('tag_groups_taxonomies_saved', array( 'TagGroups_Cron_Handlers', 'maybe_schedule_term_migration' ), 10);
161 /**
162 * Rendering a shortcode for the Gutenberg block editor
163 */
164 // phpcs:ignore Squiz.PHP.CommentedOutCode.Found
165 // add_action('wp_ajax_tg_render_shortcode', array('TagGroups_Shortcode_Common', 'render'));
166 }
167
168 /**
169 * Runs when plugin is launched and ! is_admin()
170 *
171 * @return void
172 */
173 public function not_is_admin()
174 {
175 // frontend stuff
176 add_action('wp_enqueue_scripts', array( $this->enqueue, 'wp_enqueue_scripts' ));
177 add_action('init', array( 'TagGroups_Shortcode_Statics', 'maybe_do_shortcode_in_widgets' ));
178 }
179
180 /**
181 * Runs if is_admin() && on admin_init
182 *
183 * @return void
184 */
185 public function admin_init()
186 {
187 $enabled_taxonomies = TagGroups_Taxonomy::get_enabled_taxonomies();
188 $tag_group_role_edit_tags = 'edit_pages';
189 $tag_group_role_edit_groups = 'edit_pages';
190 if (TagGroups_Utilities::is_premium_plan()) {
191 $tag_group_role_edit_tags = TagGroups_Options::get_option('tag_group_role_edit_tags', 'edit_pages');
192 $tag_group_role_edit_groups = TagGroups_Options::get_option('tag_group_role_edit_groups', 'edit_pages');
193 }
194
195 if (current_user_can($tag_group_role_edit_tags)) {
196 $this->user_can_tag_group_role_edit_tags($enabled_taxonomies);
197 }
198 /**
199 * extra columns on tags page
200 */
201 foreach ($enabled_taxonomies as $taxonomy) {
202 add_filter("manage_edit-{$taxonomy}_columns", array( 'TagGroups_Admin', 'add_taxonomy_columns' ));
203 add_filter(
204 "manage_{$taxonomy}_custom_column",
205 array( 'TagGroups_Admin', 'add_taxonomy_column_content' ),
206 10,
207 3
208 );
209 }
210 add_action('admin_head', array( 'TagGroups_Admin', 'add_tag_page_styling' ));
211 /**
212 * sorting on tags page
213 */
214 add_filter(
215 'terms_clauses',
216 array( 'TagGroups_Admin', 'sort_taxonomy_columns' ),
217 10,
218 3
219 );
220 /**
221 * filtering on tags page
222 */
223 add_action('load-edit-tags.php', array( 'TagGroups_Admin', 'do_filter_tags' ));
224 add_action('admin_footer-edit-tags.php', array( 'TagGroups_Admin', 'filter_admin_footer' ));
225 /**
226 * Process data submitted from settings forms
227 */
228 add_action('in_admin_header', array( 'TagGroups_Settings', 'settings_page_actions' ));
229 /**
230 * Process data submitted from setup wizard forms
231 */
232 add_action('in_admin_header', array( 'TagGroups_Setup_Wizard', 'settings_page_actions_wizard' ));
233 if (current_user_can($tag_group_role_edit_groups)) {
234 $this->user_can_tag_group_role_edit_groups();
235 }
236 /**
237 * Add link on Plugins page
238 */
239 add_filter("plugin_action_links_" . TAG_GROUPS_PLUGIN_BASENAME, array( 'TagGroups_Admin', 'add_plugin_settings_link' ));
240 /**
241 * Add post filter
242 */
243 add_action('restrict_manage_posts', array( 'TagGroups_Admin', 'add_post_filter' ));
244 add_filter('parse_query', array( 'TagGroups_Admin', 'apply_post_filter' ));
245 /**
246 * Register Ajax handler for development feed
247 */
248 add_action('wp_ajax_tg_ajax_get_feed', array( 'TagGroups_Admin', 'ajax_get_feed' ));
249 /**
250 * Maybe add message about language-related recommendation
251 */
252 add_action('admin_notices', array( 'TagGroups_Admin', 'add_language_notice' ));
253 /**
254 * Add fall-back button to reset the group filter for tags
255 */
256 add_filter('admin_footer_text', array( 'TagGroups_Admin', 'add_admin_footer_text' ), 100);
257
258 /**
259 * Add the request to rate the plugin
260 */
261 add_filter('admin_footer_text', array( 'TagGroups_Admin', 'add_admin_footer_rating_text' ), 101);
262
263 /**
264 * Add the script for the jQuery tooltip plugin
265 */
266 add_filter('admin_footer_text', array( 'TagGroups_Admin', 'add_admin_footer_tooltip_script' ), 102);
267 }
268
269 /**
270 * Functions that require permission tag_group_role_edit_tags
271 *
272 * @param array $enabled_taxonomies
273 * @return void
274 */
275 private function user_can_tag_group_role_edit_tags($enabled_taxonomies)
276 {
277 /**
278 * Add group menus when creating and editing tags
279 */
280 foreach ($enabled_taxonomies as $taxonomy) {
281 add_action("{$taxonomy}_edit_form_fields", array( 'TagGroups_Admin', 'render_edit_tag_menu' ));
282 add_action("{$taxonomy}_add_form_fields", array( 'TagGroups_Admin', 'render_new_tag_menu' ));
283 add_filter(
284 "{$taxonomy}_row_actions",
285 array( 'TagGroups_Admin', 'expand_quick_edit_link' ),
286 10,
287 2
288 );
289 }
290 add_action(
291 'quick_edit_custom_box',
292 array( 'TagGroups_Admin', 'quick_edit_tag' ),
293 10,
294 3
295 );
296 /**
297 * Adding tag group menu to quick edit on Tags page
298 */
299 add_action('admin_footer-edit-tags.php', array( 'TagGroups_Admin', 'render_quick_edit_javascript' ));
300 /**
301 * Footer of bulk admin
302 */
303 add_action('admin_footer-edit-tags.php', array( 'TagGroups_Admin', 'bulk_admin_footer' ));
304 /**
305 * Processing bulk actions for tags
306 */
307 add_action('load-edit-tags.php', array( 'TagGroups_Admin', 'do_bulk_action' ));
308 /**
309 * If using WPML and translation not available, copies tag name to translation
310 */
311 add_action('create_term', array( 'TagGroups_Term_Save_Handlers', 'maybe_copy_term_group_to_translation' ), 20);
312 /**
313 * Saves the tag group; other tag info saved anyway
314 */
315 add_action('create_term', array( 'TagGroups_Term_Save_Handlers', 'save_term_group_without_tag_info' ));
316 /**
317 * Saves the tag group; need to save also other tag info
318 */
319 add_action('edit_term', array( 'TagGroups_Term_Save_Handlers', 'save_term_group_with_tag_info' ));
320 }
321
322 /**
323 * Functions that require permission tag_group_role_edit_groups
324 *
325 * @return void
326 */
327 private function user_can_tag_group_role_edit_groups()
328 {
329 /**
330 * Registers Ajax handlers to manage groups on Tag Group Admin page
331 */
332 add_action('wp_ajax_tg_ajax_manage_groups', array( 'TagGroups_Group_Admin', 'ajax_manage_groups' ));
333 add_action('wp_ajax_tg_ajax_benchmark', array( 'TagGroups_Settings_Ajax', 'ajax_benchmark' ));
334 }
335
336 /**
337 * Wrapper for remove_all_filters(), returning previously registered functions
338 *
339 * @param array|string $hook_names (array of comma-separated list)
340 * @return void
341 */
342 public function remove_all_filters($hook_names)
343 {
344 if (empty($hook_names)) {
345 return array();
346 }
347 if (!is_array($hook_names)) {
348 $hook_names = array_map('trim', explode(',', $hook_names));
349 }
350 $this->hooks = array();
351 foreach ($hook_names as $hook_name) {
352 $this->hooks[] = array(
353 'name' => $hook_name,
354 'subscribers' => $this->get_all_hooks($hook_name),
355 );
356 remove_all_filters($hook_name);
357 }
358 }
359
360 /**
361 * Restores all hook from remove_all_filters()
362 *
363 * @param array $hook_array
364 * @return void
365 */
366 public function restore_hooks()
367 {
368 if (empty($this->hooks)) {
369 return;
370 }
371 foreach ($this->hooks as $hooks) {
372 foreach ($hooks['subscribers'] as $subscriber) {
373 add_filter(
374 $hooks['name'],
375 $subscriber['function'],
376 $subscriber['priority'],
377 $subscriber['accepted_args']
378 );
379 }
380 }
381 }
382
383 /**
384 * List all hooks
385 *
386 * https://stackoverflow.com/a/26680808
387 *
388 * @param string $hook
389 * @return array
390 */
391 public function get_all_hooks($hook = '')
392 {
393 global $wp_filter ;
394 $hooks = array();
395
396 if (isset($wp_filter[$hook]->callbacks)) {
397 array_walk($wp_filter[$hook]->callbacks, function ($callbacks, $priority) use (&$hooks) {
398 foreach ($callbacks as $id => $callback) {
399 $hooks[] = array_merge([
400 'id' => $id,
401 'priority' => $priority,
402 ], $callback);
403 }
404 });
405 } else {
406 return [];
407 }
408
409 foreach ($hooks as &$item) {
410 /**
411 * skip if callback does not exist
412 *
413 */
414 if (!is_callable($item['function'])) {
415 continue;
416 }
417 /**
418 * function name as string or static class method eg. 'Foo::Bar'
419 *
420 */
421
422 if (is_string($item['function'])) {
423 $ref = ( strpos($item['function'], '::') ? new ReflectionClass(strstr($item['function'], '::', true)) : new ReflectionFunction($item['function']) );
424 $item['file'] = $ref->getFileName();
425 $item['line'] = ( get_class($ref) == 'ReflectionFunction' ? $ref->getStartLine() : $ref->getMethod(substr($item['function'], strpos($item['function'], '::') + 2))->getStartLine() );
426 } elseif (is_array($item['function'])) {
427 $ref = new ReflectionClass($item['function'][0]);
428 // $item['function'][0] is a reference to existing object
429 $item['function'] = array( $item['function'][0], $item['function'][1] );
430 $item['file'] = $ref->getFileName();
431 $item['line'] = ( strpos($item['function'][1], '::') ? $ref->getParentClass()->getMethod(substr($item['function'][1], strpos($item['function'][1], '::') + 2))->getStartLine() : $ref->getMethod($item['function'][1])->getStartLine() );
432 // closures
433 } elseif (is_callable($item['function'])) {
434 $ref = new ReflectionFunction($item['function']);
435 $item['file'] = $ref->getFileName();
436 $item['line'] = $ref->getStartLine();
437 }
438 }
439 return $hooks;
440 }
441 }
442 }
443