Using variable from one filter in another filter

This is probably a good case for a global variable. Just make sure it is set to an array before you add to it and also when to attempt to output the content. Convert the array to a string before adding to content.

Also, make sure the meta data exists before adding to the array — that way you’re not adding empty copyright values.

GLOBAL VERSION

function wpse_get_full_size_gallery_images($gallery, $post, $galleries) {

    // reference the global variable
    global $copyright;

    // make sure it's set
    if( ! isset($copyright)) $copyright = array();

    // grab the IDS
    $ids = explode(',', $galleries[ 'include' ]);

    foreach($ids as $id) {
       // get the possible meta
       $meta = get_post_meta($id, 'wiki_copyright', true);

       // add them to the copyright array   
       // make sure to only add if it exists
       if( !empty($meta)) $copyright[] = $meta;
    }

    return $gallery;
}

add_filter('shortcode_atts_gallery', 'wpse_get_full_size_gallery_images', 10, 3);

function my_the_content_filter($content) {

    // reference the global variable
    global $copyright;

    // add copyright array converted to string if we have content
    if( ! empty($copyright)) $content .= implode(',', $copyright);

    return $content;
}

add_filter('the_content', 'my_the_content_filter', 20);

STATIC VERSION

If you don’t like to use globals, for whatever reason, then consider a static as an alternate variable scope in PHP.

Another important feature of variable scoping is the static variable. A static variable exists only in a local function scope, but it does not lose its value when program execution leaves this scope.

Since the persistent variable is tied to a single function scope we’ll need to create the function outside any loops then reuse it for adding values in addition to retrieving those values.

If you pass a new value; add it. If you don’t pass a value; get all values.

if( ! function_exists('copyrights')) {
    function copyrights($value="") {

        // only this function has access to $_copyrights
        static $_copyrights;

        // expressions can't be assigned as defaults
        // but we still want to initialize the value
        if( ! isset($_copyrights)) {
            $_copyrights = array();
        }

        // if we're passing new values then add them
        if( ! empty($value)) {
            $_copyrights[] = $value;

            return true; // success
        }
        else {
            // otherwise return uniques
            $unique_list = array_unique($_copyrights);

            // convert to string before they leave
            return implode(", ", $unique_list);
        }
    }
}

add_filter('shortcode_atts_gallery', function($gallery, $post, $galleries) {
    $ids = explode(',', $galleries[ 'include' ]);
    foreach($ids as $id) 
        if( ! empty($meta = get_post_meta($id, 'wiki_copyright', true)))
            copyrights($meta);

    return $gallery;
}, 10, 3);

add_filter('the_content', function($content) {
    return $content . copyrights();
}, 20);

TESTING

copyrights ( 123 );
copyrights ( 223 );
copyrights ( 333 );
copyrights ( 123 );
copyrights ( 111 );
copyrights ( 111 );
copyrights ( 111 );

echo ( copyrights() ); // 123, 223, 333, 111

SINGLETON VERSION

I actually never use globals because a Singleton Pattern is my preferred method.

The idea is that you put all your methods on an instance of a class but only access it through a static method. By doing so, the class ensures there is only ever one single instance created.

if( ! class_exists('Copyrights')) {
    class Copyrights {

        private        $copyrights;
        private static $instance;

        // PRIVATE CONSTRUCTOR

        private function __construct() {

            // initialize the array
            $this->copyrights = array();
        }

        // STATIC SINGLETON

        public static function getInstance() {
            if(is_null(self::$instance)) {
                self::$instance = new self();
            }

            return self::$instance;
        }

        // PUBLIC METHODS

        public function toString() {
            $unique_list = array_unique($this->copyrights);

            return implode(", ", $unique_list);
        }

        public function add($value="") {
            if( ! empty($value)) {
                $this->copyrights[] = $value;
            }
        }
    }
}

add_filter('shortcode_atts_gallery', function($gallery, $post, $galleries) {

    $ids = explode(',', $galleries[ 'include' ]);

    foreach($ids as $id)
        if( ! empty($meta = get_post_meta($id, 'wiki_copyright', true))) 
            Copyrights::getInstance()->add($meta);

    return $gallery;
}, 10, 3);

add_filter('the_content', function($content) {
    return $content . Copyrights::getInstance()->toString();
}, 20);

TESTING

Copyrights::getInstance()->add ( 123 );
Copyrights::getInstance()->add ( 223 );
Copyrights::getInstance()->add ( 333 );
Copyrights::getInstance()->add ( 123 );
Copyrights::getInstance()->add ( 111 );
Copyrights::getInstance()->add ( 111 );
Copyrights::getInstance()->add ( 111 );

echo Copyrights::getInstance()->toString(); // 123, 223, 333, 111

SINGLETON PER POST VERSION

Maybe the single most important aspect that has been overlooked in the debate of global vs. the sky is falling is the solution above (and alternates proposed) only cater to a single post. If you wanted to add your copyrights in a loop you would be screwed because all posts would be added to a single array.

With the singleton class, adding a per ID singleton is cake and arguably the best possible option.

if( ! class_exists('Copyrights')) {
    class Copyrights {

        private static $instance;
        private        $copyrights;
        public         $post_id;

        // PRIVATE CONSTRUCTOR

        private function __construct($post_id) {

            // save the id
            $this->post_id = $post_id;

            // initialize the array
            $this->copyrights = array();
        }

        // SINGLETON

        public static function getInstance($post_id = 'NO ID') {
            if(is_null(self::$instance)) self::$instance = array();
            if(is_null(self::$instance[ $post_id ])) {
                self::$instance[ $post_id ] = new self($post_id);
            }

            return self::$instance[ $post_id ];
        }

        // PUBLIC METHODS

        public function toString() {
            $unique_list = array_unique($this->copyrights);

            return implode(", ", $unique_list);
        }

        public function add($value="") {
            if( ! empty($value)) {
                $this->copyrights[] = $value;
            }
        }
    }
}

add_filter('shortcode_atts_gallery', function($gallery, $post, $galleries) {

    $ids = explode(',', $galleries[ 'include' ]);

    foreach($ids as $id)
        if( ! empty($meta = get_post_meta($id, 'wiki_copyright', true)))
            Copyrights::getInstance($post->ID)->add($meta);

    return $gallery;
}, 10, 3);

add_filter('the_content', function($content) {
    global $post;
    return $content . Copyrights::getInstance($post->ID)->toString();
}, 20);

TESTING

As you can see, having the the option to use ID as a key keeps things flexible.

Copyrights::getInstance( 1 )->add ( 123 );
Copyrights::getInstance( 1 )->add ( 223 );
Copyrights::getInstance( 2 )->add ( 333 );
Copyrights::getInstance( 2 )->add ( 123 );
Copyrights::getInstance( 2 )->add ( 111 );
Copyrights::getInstance( 2 )->add ( 111 );
Copyrights::getInstance( 2 )->add ( 111 );
Copyrights::getInstance()->add ( 111 );
Copyrights::getInstance()->add ( 444 );
Copyrights::getInstance()->add ( 555 );
Copyrights::getInstance()->add ( 888 );

echo Copyrights::getInstance( 1 )->toString(); // 123, 223
echo Copyrights::getInstance( 2 )->toString(); // 333, 123, 111
echo Copyrights::getInstance()->toString(); // 111, 444, 555, 888

At the point that someone thinks it’s a good idea to store a temporary value in the database because they don’t understand PHP then it’s a good time to rethink the problem.


UPDATE

I solved the question using a global variable but rethinking the issue you can do away with a lot of complexities by justing using the content filter hook alone — which keeps the issue localized.

In this case, when the_content runs, we check for all galleries and output only the relevant data.

No need for globals, statics, singletons, options or extra functions.

Best of all, this will work in a loop without complication.

add_filter('the_content', 'add_copyright_to_content');

function add_copyright_to_content($content) {

    //  pull all galleries from the post
    $galleries = get_post_galleries(get_post(), false);

    //  no gallery? then let's get out of here
    if(empty($galleries)) return $content;

    $all="";

    //  gather all ids
    foreach($galleries as $gallery) $all .= $gallery[ 'ids' ] . ',';

    //  convert them to an array with unique ids
    $all = array_unique(array_filter(explode(',', $all)));

    //  replace id for copyright info on the image meta
    foreach($all as $key => $id) $all [ $key ] = get_post_meta($id, 'wiki_copyright', true);

    //  return non-empty values to the end of the content
    return $content . implode(', ', array_filter($all));
}

Leave a Comment