Funciones obsoletas en una clase de complemento

8

Estoy actualizando uno de mis complementos y estoy un poco atascado con las funciones obsoletas.

Originalmente, mi complemento tenía una variable global y la clase principal del complemento se instanciaba y almacenaba en la variable global. De esta forma, los usuarios podrían usar las funciones globales para acceder a la clase de complemento.

$GLOBALS['my_custom_plugin'] = new my_custom_plugin();

Luego, por ejemplo, en mis preguntas frecuentes tuve un código que mostraba cómo eliminar una de las funciones de mi clase de un enlace específico y agregarlo a un enlace diferente:

function move_input(){ 
    global $my_custom_plugin;
    remove_action( 'before_main_content', array( $my_custom_plugin, 'display_input') );
    add_action( 'after_main_content', array( $my_custom_plugin, 'display_input' ) );
}
add_action( 'wp_head' , 'move_input' );

Ahora, en mi actualización, la display_input()función se ha movido a otra clase y quiero que las personas sepan cómo acceder a ella. Intenté reemplazar la función original (en la clase de complemento principal) con el siguiente aviso de desaprobación:

public function display_input() { 
    _deprecated_function( 'display_price', '2.0', 'my_custom_plugin()->display->display_input' );
    return $this->display->display_input();
}

Sin embargo, las funciones add_actiony remove_actionno parecen activar el aviso de desaprobación. Extrañamente, eliminar completamente la función no causa un error, aunque array( $my_custom_plugin, 'display_input')no exista.

Si alguien intenta acceder a la función directamente:

$my_custom_plugin->display_input();

Entonces veo los avisos de depuración. ¿Es este el resultado esperado para _deprecated_function()? ¿O me estoy perdiendo algo? ¿Es posible mostrar un aviso de depuración cuando alguien intenta eliminar o agregar una acción usando una función obsoleta?

Actualizar

Me di cuenta de que simplemente no estaba viendo el mensaje de depuración, add_actionya que lo estaba agregando bastante bajo en la página. #facepalm! Sin embargo, todavía no veo ningún aviso de depuración para el remove_action.

helgatheviking
fuente
Interesante call_user_func(function(){trigger_error('hello?');});funciona, pero falla en una devolución de llamada registrada por add_action.
fuxia
Preparándose para facepalm, pero ¿es eso una pregunta o una declaración?
helgatheviking
Solo un resultado de prueba. Yo también estoy sorprendido.
fuxia
Ok, entonces realmente no he pasado por alto nada, ¿así es exactamente ?
helgatheviking
2
Oh, Query Monitor ha ocultado el mensaje en mi configuración. El mensaje para add_action()estaba realmente allí. remove_action()no se puede manejar así.
fuxia

Respuestas:

2

Callbacks no existentes

Una de las cosas buenas es decir, que ni do_action(), ni apply_filters()hacer gatillo un error si una devolución de llamada no está presente. Esto significa que es la forma más segura de insertar datos de complementos en las plantillas: si un complemento está desactivado y do_action()/ apply_filters()no encuentra la devolución de llamada en la $wp_filtersmatriz global , no sucede nada.

Salida de error

Ahora, cuando está llamando remove_filter()a la función / método que originalmente enganchó la devolución de llamada, la devolución de llamada simplemente se eliminará de la matriz global, lo que significa que la devolución de llamada nunca se ejecutará ya que ya no está registrada.

La solución es simple: elimine la devolución de llamada después de que se activó, eliminándola desde la propia devolución de llamada.

Eliminar devoluciones de llamada

Todos sabemos que el complemento WPs "API" es un problema cuando se trata de eliminar. El problema es principalmente la extraña construcción de agregar nombres "únicos" a las claves de la global $wp_filter;matriz. Una solución muy simple es usar __METHOD__y llamar a los filtros que desea eliminar en un contexto estático:

class FOoooo
{
    public function __construct()
    {
        add_filter( 'hook', array( __CLASS__, 'bar' ) );
    }
    public static function bar( $baz )
    {
        remove_filter( current_filter(), __METHOD__ );

        return $baz;
    }
}

Si bien esto no es bueno, es ... una especie de solución para algunos casos de uso. Pero ni se te ocurra quitar un cierre.

Lo anterior simplemente elimina la devolución de llamada, aún la ejecuta. Aún así puedes ir más allá y usar remove_all_actions()(o remove_all_filters()).

// Check if a callback is attached and tell about the deprecated stuff
if ( has_action( 'before_main_content' ) )
    _deprecated_function( 'display_price', '2.0', 'my_custom_plugin()->display->display_input' );
// Remove the callback
remove_all_actions( 'before_main_content' );

Tal vez incluso podría ir más allá, extraer la devolución de llamada de la matriz de filtros globales y volver a conectarla al nuevo enlace / filtro (si son compatibles).

emperador
fuente
Gracias Kaiser! Esta es una respuesta asombrosa y detallada. Intentaré probarlo mañana.
helgatheviking