PHP function called twice, funny warning message

FINAL EDIT: I’ve summarized and simplified this crazy question into a new question, so we can close this Q or whatever is necessary to mark it resolved. Thanks again!

NEW:

Read More

Can you tell me your opinion of this, and possibly see if you can recreate it:

Currently, the $post->post_content variable contains:

"before <img src="/path/to/valid_img.gif" /> after"

This code placed at the top of the theme header.php…

------ Code --------
    1: $str = $post->post_content;
    2: assert( isset( $str ) );
    3: assert( is_string( $str ) );
    4: echo $str;
    5: $str = 'before <img src="/path/to/nonexistant.gif" /> after';
    6: assert( isset( $str ) );
    7: echo $str;
--------------------

Outputs this…

------ Output ------
before <img src="/path/to/valid_img.gif" /> after
before <img src="/path/to/nonexistant.gif" /> after
--------------------

With these warnings…

--- PHP Warnings ---
PHP Warning:  assert() [<a href='function.assert'>function.assert</a>]: Assertion
failed in /path/to/header.php on line 2
PHP Warning:  assert() [<a href='function.assert'>function.assert</a>]: Assertion
failed in /path/to/header.php on line 3
--------------------

Why would line 4 properly echo the $str if assert() fails twice when I KNOW 100% it should succeed?

What does a broken image src have to do with setting or unsetting the variable $str? WordPress bug/oddity?

Now the crazy part…

When lines 5-7 are commented out, thus eliminating the nonexistant.gif, the assert() warning does NOT appear and the output STILL properly produces this…

------ Output ------
before <img src="/path/to/valid_img.gif" /> after
--------------------

Any chance you can reproduce this and tell me what you think? I’m new to PHP, but I’m pretty sure this is crazyness. 🙂

OLD:

I’m relatively new to PHP and I have this code:

$str = $post->post_content; // hi -- [hw] -- bye <img src="foobar.png" />
$str = core_wp( 'foo_shortcode', $str );
echo $str; // return $str; produces the same warning message
// If there is no echo or return, the warning message is not produced.
// The warning disappears when I statically set (as object) the initial $str to
// "hi -- [hw] -- bye <img src="foobar.png" />".

When I run the above code, it works fine (foo-shortcode is doing it’s job). The output is:

hi -- Hello World -- bye <img src="foobar.png" />

However I always get this warning message, telling me that foo-shortcode seems to be trying to run itself a second time, except the second time around, $str does not exist.

And the catch… I only get this warning message when $str contains an HTML img tag pointing to a non-existant src.

PHP Warning:  Missing argument 1 for foo_shortcode() in ...

And here is core-wp() and foo-shortcode():

function core_wp( $function, $a = NULL, $b = NULL )
{
    $wrap = array
    (
        'foo_shortcode'             => 'foo_shortcode',
    );
    $args = array();
    if ( isset( $a ) ) $args[] = $a;
    if ( isset( $b ) ) $args[] = $b;

    return call_user_func_array( $wrap[ $function ], $args );
}

function foo_shortcode( $content ) {
    return str_replace( '[hw]', 'Hello World', $content );
}

First, why would the code work fine, and then simultaneously seem to try to run itself a second time?

And regarding the $str containing an invalid img, I suspect this has something to do with the way WordPress generates $post->post_content.

EDIT 1 (Weds, July 22 @ 8:55am)

I added error-log() per your instructions like this:

error_log( 'done1' );
$str = $post->post_content;
error_log( 'done2' );
$str = core_wp( 'foo_shortcode', $str );
error_log( 'done3' );

… and it produced this in my error log:

[22-Jul-2009 08:52:49] done1
[22-Jul-2009 08:52:49] done2
[22-Jul-2009 08:52:49] PHP Warning:  Missing argument 1 for foo_shortcode() in
/home/path/to/header.php on line 23
[22-Jul-2009 08:52:49] done3

… and the output sent to the browser (correctly) was:

hi -- Hello World -- bye <img src="foobar.png" />

… but the warning message was still produced.

EDIT 2 (Weds, July 22 @ 9:18am)

I then tried this assertion:

59: $str = $post->post_content;
60: assert( isset( $str ) );
61: $str = core_wp( 'foo_shortcode', $str );
62: assert( isset( $str ) );

… and the PHP log shows:

[22-Jul-2009 09:16:55] PHP Warning:  assert() [<a 
href='function.assert'>function.assert</a>]: Assertion failed in
/home/path/to/header.php on line 60
[22-Jul-2009 09:16:55] PHP Warning:  Missing argument 1 for foo_shortcode() in
/home/path/to/header.php on line 23

… but again, the output is correct, yet the warning is still issued.

It seems to me that PHP is initially not setting $str = $post->post-content, then it runs core-wp( ‘foo-shortcode’, $str ) and says to itself “oh! I really need to set $str = $post->post-content…” goes back and sets it, and then outputs the correct data.

Related posts

Leave a Reply

2 comments

  1. If instead of

    $str = $post->post_content;
    

    You temporarilly put:

    $str = 'some string you believe to trigger the error';
    

    Does the error still occur? If so, that leads us to look at core_wp() for certain. If not, $post->post_content may be the culprit.

    EDIT: To determine if $post->post_content is NULL, add the following lines:

    echo "post_content:";
    var_dump($post->post_content);
    $str = $post->post_content;
    

    Let us know if it’s NULL when the error occurs.

    EDIT2: Since you’re sure $post->post_content is not NULL, try an error_log("done"); immediately after the code as you’ve posted it. Does the warning show up before or after “done”? Also, add error_log() statements to the top of all functions in question stating “called functionname” and that will help you determine if they’re being called twice.

  2. I would try to initialize $args to array() just like you do with wrap.
    This shoud solve your issue.

    function core_wp( $function, $a = NULL, $b = NULL )
    {
      $wrap = array
      (
        'do_shortcode'                          => 'do_shortcode',
      );
    
      $args=array();
      if ( isset( $a ) ) $args[] = $a;
      if ( isset( $b ) ) $args[] = $b;
    
      return call_user_func_array( $wrap[ $function ], $args );
    }
    

    I can’t say anything regarding the double execution: the code you post is not responsible for that.