Question

I'd like to call a function Y($arg) when the hook X is fired.

Alternative: catch the return value from function Y(), which is called via add_action('X', 'Y'); in function W, which contains the add_action() statement.

How do I do that?

My use case:

I have a function createMainPanel() that returns a string $ret to be displayed.

I only have access to the post meta info after the "template_redirect" hook, e.g. get_post() and the like only have sensible values after that hook. Thus, I want to add an add_action('redirect_template', retrievePostInfo') with the currently prepared string for output ($ret)) and let that function build the rest and print the page with echo.

An alternative thought was somehow to retrieve the return of retrievePostInfo() and append it to the string of createMainPanel().

However, I can't see a working way to implement either of these possibilities.

EDIT

I solved my problem in a way unrelated to the question, but here's the code:

ERRONEOUS CODE:

function showPostMetaInfo()
{
    $id = get_the_ID();

    $string.= "<table id='meta-info'>"
            . "<thead>"
            . "<tr>"
            . "<th> Meta Type </th>"
            . "<th> Value"
            . "</tr>"
            . "</thead>"
            . "<tbody>"
            . "<tr>"
            . "<td> Title </td>"
            . "<td>".get_the_title($id)."</td>"
            . "</tr>"
            . "<tr>"
            . "<td> Author </td>"
            . "<td>".get_the_author($id)."</td>"
            . "</tr>"
            . "<tr>"
            . "<td> Published </td>"
            . "<td>".get_the_date("", $id)."</td>"
            . "</tr>"
            . "<tr>"
            . "<td> Last Modified </td>"
            . "<td>".get_the_modified_date("", $id)."</td>"
            . "</tr>"
            . "<tr>"
            . "<td> Categories </td>"
            . "<td>".listCategories($id)."</td>"
            . "</tr>"
            . "<tr>"
            . "<td> Tags </td>"
            . "<td>".listTags($id)."</td>"
            . "</tr>"
            . "</tbody>"
            . "</table>";

    return $string;
}

CORRECT CODE:

function showPostMetaInfo()
{
    $id = get_queried_object_id();

    $string.= "<table id='meta-info'>"
            . "<thead>"
            . "<tr>"
            . "<th> Meta Type </th>"
            . "<th> Value"
            . "</tr>"
            . "</thead>"
            . "<tbody>"
            . "<tr>"
            . "<td> Title </td>"
            . "<td>".get_the_title($id)."</td>"
            . "</tr>"
            . "<tr>"
            . "<td> Author </td>"
            . "<td>".get_the_author($id)."</td>"
            . "</tr>"
            . "<tr>"
            . "<td> Published </td>"
            . "<td>".get_the_date("", $id)."</td>"
            . "</tr>"
            . "<tr>"
            . "<td> Last Modified </td>"
            . "<td>".get_the_modified_date("", $id)."</td>"
            . "</tr>"
            . "<tr>"
            . "<td> Categories </td>"
            . "<td>".listCategories($id)."</td>"
            . "</tr>"
            . "<tr>"
            . "<td> Tags </td>"
            . "<td>".listTags($id)."</td>"
            . "</tr>"
            . "</tbody>"
            . "</table>";

    return $string;
}
Was it helpful?

Solution

It's possible to use functions in a way that allow for one action to pass variables to the next. In this case, I've waited till the wp_head event to add the_content filter. And it will be using the queried_object_id when appending content with showPostMetaInfo.

This makes your function a little more OOP friendly.

// Wait till the head
add_action( 'wp_head', function() {

    // Get the queried ID for use with `the_content`
    $queried_id = get_queried_object_id();

    add_filter( 'the_content', function( $content ) use ( $queried_id ) {

        // append post meta info to content
        return $content . showPostMetaInfo( $queried_id );
    } );
} );

function showPostMetaInfo( $id = null ) {

    if ( empty( $id ) ) {
        return '';
    }

    ob_start();

    ?>
    <table id='meta-info'>
    <thead>
    <tr>
        <th> Meta Type</th>
        <th> Value
    </tr>
    </thead>
    <tbody>
    <tr>
        <td> Title</td>
        <td><?php echo get_the_title( $id ); ?></td>
    </tr>
    <tr>
        <td> Author</td>
        <td><?php echo get_the_author( $id ); ?></td>
    </tr>
    <tr>
        <td> Published</td>
        <td><?php echo get_the_date( "", $id ); ?></td>
    </tr>
    <tr>
        <td> Last Modified</td>
        <td><?php echo get_the_modified_date( "", $id ); ?></td>
    </tr>
    <tr>
        <td> Categories</td>
        <td><?php echo listCategories( $id ); ?></td>
    </tr>
    <tr>
        <td> Tags</td>
        <td><?php echo listTags( $id ); ?></td>
    </tr>
    </tbody>
    </table><?php

    return ob_get_clean();
}

function listCategories( $id ) { return 'listCategories: ' . $id; };
function listTags( $id ) { return 'listTags: ' . $id; };

Note: This won't work with all versions of PHP.


Option 2

Taking this a step further, you could create a class that allows for dynamic data (including methods) and route your functions through it using magic methods.

if ( ! class_exists( 'FunctionProxy' ) ):

    class FunctionProxy {

        private $s = array ();

        // properties
        function __set( $k, $c ) { $this->s[ $k ] = $c; }
        function __get( $k ) { return isset($this->s[ $k ]) ? $this->s[ $k ] : null; }

        // methods
        public function __call( $method, $args ) {
            if ( isset($this->s[ $method ]) && is_callable( $this->s[ $method ] ) ) {
                return call_user_func_array( $this->s[ $method ], func_get_args() );
            } else {
                echo "unknown method " . $method;
                return false;
            }
        }

        // backtrace caller
        static function get_backtrace_object( $depth = 3 ) {
            $trace  = debug_backtrace();
            return isset( $trace[ $depth ][ 'object' ] ) ? $trace[ $depth ][ 'object' ] : null;
        }
    }

endif;

Using the FunctionProxy dynamic object you can make methods and properties on the fly.

// Wait till the head
add_action( 'wp_head', function() {

    // create our dynamic object
    $func = new FunctionProxy();

    // Get the queried ID for use with `the_content`
    $func->queried_id = get_queried_object_id();

    // Create a method on the object
    $func->filter_the_content = function( $content ) {

        // Find the callee of this function
        $caller = FunctionProxy::get_backtrace_object();

        // Return content plus post meta from our caller object
        return $content . showPostMetaInfo( $caller->queried_id );
    };

    // add content filer
    add_filter( 'the_content', array ( $func, 'filter_the_content' ) );
} );

Reference

OTHER TIPS

You can't get anything back from add_action() -- it always returns true.

Reference

Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top