Skip to content

Instantly share code, notes, and snippets.

@david-binda
Last active October 19, 2018 11:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save david-binda/b7620996369dbe130d66da3c8894488d to your computer and use it in GitHub Desktop.
Save david-binda/b7620996369dbe130d66da3c8894488d to your computer and use it in GitHub Desktop.
A must-use plugin for WordPress developers figuring out what filter callback changes a value passed to the `apply_filters` function
<?php
/*
Plugin Name: Apply Filters debug
Description: A debug function for figuring out what filter's callback changed the value
Version: 0.1
Author: Automattic, david-binda
Author URI: http://www.automattic.com/
*/
/* This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
# Installation
Copy this file to your WordPress installation's mu-plugins directory (located in wp-content/mu-plugins)
# Usage
Call the `swpd_apply_filters_debug` function right before the code which is calling the `apply_filters`.
It collects the data and outputs the logging to PHP Error log or directly to stdout in case
it's used via WP CLI - eg. in wp shell
Example of figuring out what callback changes the scheme of a home URL:
```
$ wp shell
wp> swpd_apply_filters_debug( 'set_url_scheme', true );
wp> home_url();
```
Example logging output:
```
[24-Mar-2017 12:33:50 UTC] Initial value: 'https://vip.wordpress.com'
[24-Mar-2017 12:33:50 UTC] array (
'value' => '\'http://vip.wordpress.com\'',
'idx' => '\'wpcom_only_use_https_with_valid_ssl_cert\'',
'the_' => 'array (
\'function\' => \'wpcom_only_use_https_with_valid_ssl_cert\',
\'accepted_args\' => 3,
)',
'priority' => 10,
)
```
*/
/**
* @param $filter_to_debug What filter is being debugged
* @param bool|false $only_changed Whether to log only filters which change the value or all. Defaults to all.
*
* @return void
*/
function swpd_apply_filters_debug( $filter_to_debug, $only_changed = false ) {
new SWPD_apply_filters( $filter_to_debug, $only_changed );
}
class SWPD_apply_filters {
private $filter_to_debug = null;
private $only_changed = false;
private $swpd_filter_prev_value = null;
public function __construct( $filter, $only_changed = false ) {
$this->filter_to_debug = $filter;
$this->only_changed = $only_changed;
add_filter( 'all', array( $this, 'filter_all' ), 10, 2 );
}
public function filter_all( $action, $value = null ) {
if ( current_filter() === $this->filter_to_debug ) {
$this->add_debugging( $value );
}
return $value;
}
public function add_debugging( $value ) {
global $wp_filter;
$this->log( 'Initial value:', $value );
$this->swpd_filter_prev_value = $value;
if ( true === array_key_exists( $this->filter_to_debug, $wp_filter ) ) {
$filters = $wp_filter[$this->filter_to_debug]->callbacks;
$wp_filter[$this->filter_to_debug]->callbacks = array();
$i = 0;
foreach( $filters as $priority => $thes_ ) {
foreach( $thes_ as $idx => $the_ ) {
$wp_filter[$this->filter_to_debug]->callbacks[$priority][$idx] = $the_;
$wp_filter[$this->filter_to_debug]->callbacks[$priority][ _wp_filter_build_unique_id( $this->filter_to_debug, array( $this, 'debug' ), $priority ) . $i++ ] = array(
'function' => function( $value ) use ( $idx, $priority, $the_ ) { $this->debug( $value, $idx, $the_, $priority ); return $value; },
'accepted_args' => 1,
);
}
}
}
}
public function debug( $value, $idx, $the_, $priority ) {
if ( false === $this->only_changed || $this->swpd_filter_prev_value !== $value ) {
$this->log( '', array(
'value' => $value,
'idx' => $idx,
'the_' => $the_,
'defined_in' => $this->defined_in( $the_ ),
'priority' => $priority
) );
}
$this->swpd_filter_prev_value = $value;
return $value;
}
public function defined_in( $the_ ) {
$return = 'N/A';
// Handle function and closures.
if ( true === is_string( $the_['function'] ) || true === is_a( $the_['function'], '\Closure' ) ) {
$the_reflection = new ReflectionFunction( $the_['function'] );
$return = $the_reflection->getFileName() . '#L' . $the_reflection->getStartLine();
}
// Handle class' methods
if ( true === is_array( $the_['function'] ) ) {
$the_reflection = new ReflectionMethod( $the_['function'][0], $the_['function'][1] );
$return = $the_reflection->getFileName() . '#L' . $the_reflection->getStartLine();
}
return $return;
}
public function log( $message, $data ) {
error_log( $message . ' ' . var_export( $data, true ) );
if ( true === defined( 'WP_CLI' ) && true === WP_CLI ) {
WP_CLI::Line( $message . ' ' . var_export( $data, true ) );
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment