Plugin Directory

source: simply-show-hooks/trunk/index.php @ 3106767

Last change on this file since 3106767 was 3106767, checked in by frantorres, 5 weeks ago

PRT Revert Changes

File size: 15.6 KB
Line 
1<?php
2/*
3Plugin Name: Simply Show Hooks
4Plugin URI: http://www.calyxagency.com/#plugins
5Description: Simply Show Hooks helps theme or plugin developers to quickly see where all the action and filter hooks are on any WordPress page.
6Version: 1.2.1
7Contributors: stuartobrien, cxthemes
8Author: Stuart O'Brien, cxThemes
9Author URI: http://www.calyxagency.com/?utm_medium=plugins%20page%20view%20details&utm_campaign=free%20plugin%20upsell&utm_source=send%20emails#plugins
10License: GPLv2 or later
11Text Domain: simply-show-hooks
12Domain Path: /localization/
13*/
14
15defined( 'ABSPATH' ) or die( 'No Trespassing!' ); // Security
16
17class CX_Simply_Show_Hooks {
18       
19        private $status;
20       
21        private $all_hooks = array();
22       
23        private $recent_hooks = array();
24       
25        private $ignore_hooks = array();
26       
27        private $doing = 'collect';
28       
29
30        /**
31        *  Instantiator
32        */
33        public static function get_instance() {
34               
35                static $instance = null;
36               
37                if ( null === $instance ) {
38                        $instance = new self();
39                        $instance->init();
40                }
41               
42                return $instance;
43        }
44       
45        /**
46         * Construct and initialize the main plugin class
47         */
48       
49        public function __construct() {}
50       
51        function init() {
52               
53                // Use this to set any tags known to cause display problems.
54                // Will be display in sidebar.
55                $this->ignore_hooks = apply_filters( 'simply_show_hooks_ignore_hooks', array(
56                        'attribute_escape',
57                        'body_class',
58                        'the_post',
59                        'post_edit_form_tag',
60                        //'gettext',
61                ) );
62
63                // Translations
64                add_action( 'plugins_loaded', array( $this, 'load_translation' ) );
65               
66                // Set autive status property.
67                $this->set_active_status();
68               
69                // Attach the hooks as on plugin init.
70                $this->attach_hooks();
71               
72                // Init the plugin.
73                add_action( 'init', array( $this, 'plugin_init' ) );
74        }
75       
76        /**
77         * Helper function that sets the active status of the hooks displaying.
78         */
79        public function set_active_status() {
80               
81                if ( ! isset( $this->status ) ) {
82                       
83                        if ( ! isset( $_COOKIE['cxssh_status'] ) ) {
84                                setcookie( 'cxssh_status', 'off', time()+3600*24*100, '/' );
85                        }
86                       
87                        if ( isset( $_REQUEST['cxssh-hooks'] ) ) {
88                                setcookie( 'cxssh_status', $_REQUEST['cxssh-hooks'], time()+3600*24*100, '/' );
89                                $this->status = $_REQUEST['cxssh-hooks'];
90                        }
91                        elseif ( isset( $_COOKIE['cxssh_status'] ) ) {
92                                $this->status = $_COOKIE['cxssh_status'];
93                        }
94                        else{
95                                $this->status = 'off';
96                        }
97                }
98        }
99       
100        /**
101         * Helper function to attach the filter that render all the hook labels.
102         */
103        public function attach_hooks() {
104               
105                if ( $this->status == 'show-action-hooks' || $this->status == 'show-filter-hooks' ) {
106                       
107                        add_filter( 'all', array( $this, 'hook_all_hooks' ), 100 );
108                        add_action( 'shutdown', array( $this, 'notification_switch' ) );
109                        add_action( 'shutdown', array( $this, 'filter_hooks_panel' ) );
110                }
111        }
112       
113        /**
114         * Helper function to detach the filter that render all the hook labels.
115         */
116        public function detach_hooks() {
117               
118                remove_filter( 'all', array( $this, 'hook_all_hooks' ), 100 );
119                remove_action( 'shutdown', array( $this, 'notification_switch' ) );
120                remove_action( 'shutdown', array( $this, 'filter_hooks_panel' ) );
121        }
122       
123       
124        /*
125         * Admin Menu top bar
126         */
127        function admin_bar_menu( $wp_admin_bar ) {
128               
129                // Suspend the hooks rendering.
130                $this->detach_hooks();
131               
132                // Setup a base URL and clear it of the intial `cxssh-hooks` arg.
133                $url = remove_query_arg( 'cxssh-hooks' );
134               
135                if ( 'show-action-hooks' == $this->status ) {
136                       
137                        $title  = __( 'Stop Showing Action Hooks' , 'simply-show-hooks' );
138                        $href   = add_query_arg( 'cxssh-hooks', 'off', $url );
139                        $css    = 'cxssh-hooks-on cxssh-hooks-normal';
140                }
141                else {
142                       
143                        $title  = __( 'Show Action Hooks' , 'simply-show-hooks' );
144                        $href   = add_query_arg( 'cxssh-hooks', 'show-action-hooks', $url );
145                        $css    = '';
146                }
147               
148                $wp_admin_bar->add_menu( array(
149                        'title'         => '<span class="ab-icon"></span><span class="ab-label">' . __( 'Simply Show Hooks' , 'simply-show-hooks' ) . '</span>',
150                        'id'            => 'cxssh-main-menu',
151                        'parent'        => false,
152                        'href'          => $href,
153                ) );
154               
155                $wp_admin_bar->add_menu( array(
156                        'title'         => $title,
157                        'id'            => 'cxssh-simply-show-hooks',
158                        'parent'        => 'cxssh-main-menu',
159                        'href'          => $href,
160                        'meta'          => array( 'class' => $css ),
161                ) );
162               
163               
164                if ( $this->status=="show-filter-hooks" ) {
165                       
166                        $title  = __( 'Stop Showing Action & Filter Hooks' , 'simply-show-hooks' );
167                        $href   = add_query_arg( 'cxssh-hooks', 'off', $url );
168                        $css    = 'cxssh-hooks-on cxssh-hooks-sidebar';
169                }
170                else {
171                       
172                        $title  = __( 'Show Action & Filter Hooks' , 'simply-show-hooks' );
173                        $href   = add_query_arg( 'cxssh-hooks', 'show-filter-hooks', $url );
174                        $css    = '';
175                }
176               
177                $wp_admin_bar->add_menu( array(
178                        'title'         => $title,
179                        'id'            => 'cxssh-show-all-hooks',
180                        'parent'        => 'cxssh-main-menu',
181                        'href'          => $href,
182                        'meta'          => array( 'class' => $css ),
183                ) );
184               
185                // De-suspend the hooks rendering.
186                $this->attach_hooks();
187        }
188       
189        // Custom css to add icon to admin bar edit button.
190        function add_builder_edit_button_css() {
191                ?>
192                <style>
193                #wp-admin-bar-cxssh-main-menu .ab-icon:before{
194                        font-family: "dashicons" !important;
195                        content: "\f323" !important;
196                        font-size: 16px !important;
197                }
198                </style>
199                <?php
200        }
201
202        /*
203         * Notification Switch
204         * Displays notification interface that will alway display
205         * even if the interface is corrupted in other places.
206         */
207        function notification_switch() {
208               
209                // Suspend the hooks rendering.
210                $this->detach_hooks();
211               
212                // Setup a base URL and clear it of the intial `cxssh-hooks` arg.
213                $url = add_query_arg( 'cxssh-hooks', 'off' );
214                ?>
215                <a class="cxssh-notification-switch" href="<?php echo esc_url( $url ); ?>">
216                        <span class="cxssh-notification-indicator"></span>
217                        <?php echo _e( 'Stop Showing Hooks' , 'simply-show-hooks' ); ?>
218                </a>
219                <?php
220               
221                // De-suspend the hooks rendering.
222                $this->attach_hooks();
223        }
224       
225        function plugin_init() {
226               
227                if (
228                                ! current_user_can( 'manage_options' ) || // Restrict use to Admins only
229                                ! $this->plugin_active() // Allow filters to deactivate.
230                        ) {
231                        $this->status = 'off';
232                        return;
233                }
234               
235                // Enqueue Scripts/Styles - in head of admin
236                add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_script' ) );
237                add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_script' ) );
238                add_action( 'login_enqueue_scripts', array( $this, 'enqueue_script' ) );
239               
240                // Top Admin Bar
241                add_action( 'admin_bar_menu', array( $this, 'admin_bar_menu'), 90 );
242                // Top Admin Bar Styles
243                add_action( 'wp_print_styles', array( $this, 'add_builder_edit_button_css' ) );
244                add_action( 'admin_print_styles', array( $this, 'add_builder_edit_button_css' ) );
245               
246                if ( $this->status == 'show-action-hooks' || $this->status == 'show-filter-hooks' ) {
247                       
248                        //Final hook - render the nested action array
249                        add_action( 'admin_head', array( $this, 'render_head_hooks'), 100 ); // Back-end - Admin
250                        add_action( 'wp_head', array( $this, 'render_head_hooks'), 100 ); // Front-end
251                        add_action( 'login_head', array( $this, 'render_head_hooks'), 100 ); // Login
252                        add_action( 'customize_controls_print_scripts', array( $this, 'render_head_hooks'), 100 ); // Customizer
253                }
254        }
255       
256        /**
257         * Enqueue Scripts
258         */
259       
260        public function enqueue_script() {
261                global $wp_scripts, $current_screen;
262               
263                // Main Styles
264                wp_register_style( 'cxssh-main-css', plugins_url( basename( plugin_dir_path( __FILE__ ) ) . '/assets/css/cxssh-main.css', basename( __FILE__ ) ), '', '1.1.0', 'screen' );
265                wp_enqueue_style( 'cxssh-main-css' );
266
267                // Main Scripts
268                /*
269                wp_register_script( 'cxssh-main-js', plugins_url( basename( plugin_dir_path( __FILE__ ) ) . '/assets/js/cxssh-main.js', basename( __FILE__ ) ), array('jquery'), '1.1.0' );
270                wp_enqueue_script( 'cxssh-main-js' );
271                wp_localize_script('cxssh-main-js', 'cxssh-main-js', array(
272                        'home_url' => get_home_url(),
273                        'admin_url' => admin_url(),
274                        'ajaxurl' => admin_url('admin-ajax.php')
275                ));
276                */
277        }
278       
279        /**
280         * Localization
281         */
282       
283        public function load_translation() {
284                load_plugin_textdomain( 'simply-show-hooks', false, dirname( plugin_basename( __FILE__ ) ) . '/localization/' );
285        }
286       
287        /**
288         * Render Head Hooks
289         */
290        function render_head_hooks() {
291               
292                // Render all the hooks so far
293                $this->render_hooks();
294               
295                // Add header marker to hooks collection
296                // $this->all_hooks[] = array( 'End Header. Start Body', false, 'marker' );
297               
298                // Change to doing 'write' which will write the hook as it happens
299                $this->doing = 'write';
300        }
301       
302        /**
303         * Render all hooks already in the collection
304         */
305        function render_hooks() {
306               
307                foreach ( $this->all_hooks as $nested_value ) {
308                       
309                        if ( 'action' == $nested_value['type'] ) {
310                               
311                                $this->render_action( $nested_value );
312                        }
313                }
314        }
315       
316        /**
317         * Hook all hooks
318         */
319       
320        public function hook_all_hooks( $hook ) {
321                global $wp_actions, $wp_filter;
322               
323                if ( ! in_array( $hook, $this->recent_hooks ) ) {
324                       
325                        if ( isset( $wp_actions[$hook] ) ) {
326                               
327                                // Action
328                                $this->all_hooks[] = array(
329                                        'ID'       => $hook,
330                                        'callback' => false,
331                                        'type'     => 'action',
332                                );
333                        }
334                        else {
335                               
336                                // Filter
337                                $this->all_hooks[] = array(
338                                        'ID'       => $hook,
339                                        'callback' => false,
340                                        'type'     => 'filter',
341                                );
342                        }
343                }
344               
345                // if ( isset( $wp_actions[$hook] ) && $wp_actions[$hook] == 1 && !in_array( $hook, $this->ignore_hooks ) ) {
346                // if (  ( isset( $wp_actions[$hook] ) || isset( $wp_filter[$hook] ) ) && !in_array( $hook, $this->ignore_hooks ) ) {
347                if ( isset( $wp_actions[$hook] ) && !in_array( $hook, $this->recent_hooks ) && !in_array( $hook, $this->ignore_hooks ) ) {
348                       
349                        // @TODO - caller function testing.
350                        $callers = false; // @param $callers Array | false for debug_backtrace()
351                       
352                        if ( 'write' == $this->doing ) {
353                                $this->render_action( end( $this->all_hooks ) );
354                        }
355                }
356                else{
357                        // s('(skiped-hook!)');
358                        // $this->render_action( $hook );
359                }
360               
361                // Discarded functionality: if the hook was
362                // run recently then don't show it again.
363                // Better to use the once run or always run theory.
364               
365                $this->recent_hooks[] = $hook;
366               
367                if ( count( $this->recent_hooks ) > 100 ) {
368                        array_shift( $this->recent_hooks );
369                }
370        }
371       
372        /**
373         *
374         * Render action
375         */
376        function render_action( $args = array() ) {
377                global $wp_filter;
378               
379                // Get all the nested hooks
380                $nested_hooks = ( isset( $wp_filter[ $args['ID'] ] ) ) ? $wp_filter[ $args['ID'] ] : false ;
381               
382                // Count the number of functions on this hook
383                $nested_hooks_count = 0;
384                if ( $nested_hooks ) {
385                        foreach ($nested_hooks as $key => $value) {
386                                $nested_hooks_count += count($value);
387                        }
388                }
389                ?>
390                <span style="display:none;" class="cxssh-hook cxssh-hook-<?php echo $args['type'] ?> <?php echo ( $nested_hooks ) ? 'cxssh-hook-has-hooks' : '' ; ?>" >
391                       
392                        <?php
393                        if ( 'action' == $args['type'] ) {
394                                ?>
395                                <span class="cxssh-hook-type cxssh-hook-type">A</span>
396                                <?php
397                        }
398                        else if ( 'filter' == $args['type'] ) {
399                                ?>
400                                <span class="cxssh-hook-type cxssh-hook-type">F</span>
401                                <?php
402                        }
403                        ?>
404                       
405                        <?php
406                       
407                        // Main - Write the action hook name.
408                        //echo esc_html( $args['ID'] );
409                        echo $args['ID'];
410                       
411                        // @TODO - Caller function testing.
412                        if ( isset( $extra_data[1] ) && FALSE !== $extra_data[1] ) {
413                                foreach ( $extra_data as $extra_data_key => $extra_data_value ) {
414                                        echo '<br />';
415                                        echo $extra_data_value['function'];
416                                }
417                        }
418                       
419                        // Write the count number if any function are hooked.
420                        if ( $nested_hooks_count ) {
421                                ?>
422                                <span class="cxssh-hook-count">
423                                        <?php echo $nested_hooks_count ?>
424                                </span>
425                                <?php
426                        }
427                       
428                        // Write out list of all the function hooked to an action.
429                        if ( isset( $wp_filter[$args['ID']] ) ):
430                               
431                                $nested_hooks = $wp_filter[$args['ID']];
432                               
433                                if ( $nested_hooks ):
434                                        ?>
435                                        <ul class="cxssh-hook-dropdown">
436                                               
437                                                <li class="cxssh-hook-heading">
438                                                        <strong><?php echo $args['type'] ?>:</strong> <?php echo $args['ID']; ?>
439                                                </li>
440                                               
441                                                <?php
442                                                foreach ( $nested_hooks as $nested_key => $nested_value ) :
443                                                       
444                                                        // Show the priority number if the following hooked functions
445                                                        ?>
446                                                        <li class="cxssh-priority">
447                                                                <span class="cxssh-priority-label"><strong><?php echo 'Priority:'; /* _e('Priority', 'simply-show-hooks') */ ?></strong> <?php echo $nested_key ?></span>
448                                                        </li>
449                                                        <?php
450                                                       
451                                                        foreach ( $nested_value as $nested_inner_key => $nested_inner_value ) :
452                                                               
453                                                                // Show all teh functions hooked to this priority of this hook
454                                                                ?>
455                                                                <li>
456                                                                        <?php
457                                                                        if ( $nested_inner_value['function'] && is_array( $nested_inner_value['function'] ) && count( $nested_inner_value['function'] ) > 1 ):
458                                                                               
459                                                                                // Hooked function ( of type object->method() )
460                                                                                ?>
461                                                                                <span class="cxssh-function-string">
462                                                                                        <?php
463                                                                                        $classname = false;
464                                                                                       
465                                                                                        if ( is_object( $nested_inner_value['function'][0] ) || is_string( $nested_inner_value['function'][0] ) ) {
466                                                                                               
467                                                                                                if ( is_object( $nested_inner_value['function'][0] ) ) {
468                                                                                                        $classname = get_class($nested_inner_value['function'][0] );
469                                                                                                }
470                                                                                               
471                                                                                                if ( is_string( $nested_inner_value['function'][0] ) ) {
472                                                                                                        $classname = $nested_inner_value['function'][0];
473                                                                                                }
474                                                                                               
475                                                                                                if ( $classname ) {
476                                                                                                        ?><?php echo $classname ?>&ndash;&gt;<?php
477                                                                                                }
478                                                                                        }
479                                                                                        ?><?php echo $nested_inner_value['function'][1] ?>
480                                                                                </span>
481                                                                                <?php
482                                                                        else :
483                                                                               
484                                                                                // Hooked function ( of type function() )
485                                                                                ?>
486                                                                                <span class="cxssh-function-string">
487                                                                                        <?php echo $nested_inner_key ?>
488                                                                                </span>
489                                                                                <?php
490                                                                        endif;
491                                                                        ?>
492                                                                       
493                                                                </li>
494                                                                <?php
495                                                               
496                                                        endforeach;
497                                                       
498                                                endforeach;
499                                                ?>
500                                               
501                                        </ul>
502                                        <?php
503                                endif;
504                               
505                        endif;
506                        ?>
507                </span>
508                <?php
509        }
510       
511        /*
512         * Filter Hooks Panel
513         */
514        function filter_hooks_panel() {
515                global $wp_filter, $wp_actions;
516                ?>
517                <div class="cxssh-nested-hooks-block <?php echo ( 'show-filter-hooks' == $this->status ) ? 'cxssh-active' : '' ; ?> ">
518                        <?php
519                        foreach ( $this->all_hooks as $va_nested_value ) {
520                               
521                                if ( 'action' == $va_nested_value['type'] || 'filter' == $va_nested_value['type'] ) {
522                                        $this->render_action( $va_nested_value );
523                                }
524                                else{
525                                        ?>
526                                        <div class="cxssh-collection-divider">
527                                                <?php echo $va_nested_value['ID'] ?>
528                                        </div>
529                                        <?php
530                                }
531                               
532                                /*
533                                ?>
534                                <div class="va-action">
535                                        <?php echo $va_nested_value ?>
536                                </div>
537                                <?php
538                                */
539                        }
540                        ?>
541                </div>
542                <?php
543        }
544       
545        function plugin_active() {
546               
547                // Filters to deactivate our plugin - backend, frontend or sitewide.
548                // add_filter( 'simply_show_hooks_active', '__return_false' );
549                // add_filter( 'simply_show_hooks_backend_active', '__return_false' );
550                // add_filter( 'simply_show_hooks_frontend_active', '__return_false' );
551               
552                if ( ! apply_filters( 'simply_show_hooks_active', TRUE ) ) {
553                       
554                        // Sitewide.
555                        return FALSE;
556                }
557               
558                if ( is_admin() ) {
559                       
560                        // Backend.
561                        if ( ! apply_filters( 'simply_show_hooks_backend_active', TRUE ) ) return FALSE;
562                }
563                else {
564                       
565                        // Frontend.
566                        if ( ! apply_filters( 'simply_show_hooks_frontend_active', TRUE ) ) return FALSE;
567                }
568               
569                return TRUE;
570        }
571}
572
573CX_Simply_Show_Hooks::get_instance();
Note: See TracBrowser for help on using the repository browser.