• Resolved Beda

    (@bedas)


    According to https://developer.wordpress.org/reference/functions/add_shortcode/:

    $callback callable Required
    The callback function to run when the shortcode is found.
    Every shortcode callback is passed three parameters by default, including an array of attributes ($atts), the shortcode content or null if not set ($content), and finally the shortcode tag itself ($shortcode_tag), in that order.

    However, this part including an array of attributes ($atts) is not always true:
    if the shortcode is used without any attributes, then $atts is an empty string.

    This is also “proven” by looking at https://developer.wordpress.org/reference/functions/shortcode_atts/ source code which actually typcasts $atts to array. This would not be necessary, would $atts indeed be always an array.

    Now, this causes issues in a more complex programming scenario where we assume $atts to be an array (as stated by the documentation). I will not delve into details, but it is related to type hinting in methods, and also when you want to validate the $atts before it gets sent to shortcode_atts
    (this might be unconventional, but it is my choice to NOT process the $atts before they are not validated and sanitised (I am aware I could do that after shortcode_atts has merged the atts…).
    We’ve to do cumbersome checks or type cast $atts… which really should not be necessary. And type hinting still would not be possible in our callback.

    So I wanted to at least get a discussion going on trac, because IMO it should be ensured that $atts passed to $callback is always an array – empty or not.
    Yet, to do that, I wanted to do some debug first and… I just can’t figure out where $atts is actually passed to the callback, respectively where it is defined and populated, in the source code.

    Can anyone point me to where this is handled?
    I would imagine all it need is a type cast on that line of code that actually populates and then passes $atts to the callback.

    • This topic was modified 9 months, 4 weeks ago by Beda.
    • This topic was modified 9 months, 4 weeks ago by Beda. Reason: Darn autocorrect

    The page I need help with: [log in to see the link]

Viewing 2 replies - 1 through 2 (of 2 total)
  • Moderator bcworkz

    (@bcworkz)

    Hiya Beda!

    I think the line you want is 395 of /wp-includes/shortcode.php

    You can see at line 363 the passed $attr comes from shortcode_parse_atts() (declared at line 571 in the same file). I suppose we could type cast the returned value where it’s called, but I think it is more logically handled within shortcode_parse_atts() itself. It appears $atts is initialized as an empty array all right. Apparently the ltrim() at line 601 is where it becomes a string?

    Unconfirmed though, just what I see on initial read. Making it a string seems intentional. I wonder what the reasoning would be.

    Thread Starter Beda

    (@bedas)

    Indeed, this is exactly it.

    Thank you so much @bcworkz!

    And yes, I also do wonder why the conversion to string using ltrim.
    The whole thing is a bit weird.
    The Docbloc states that:

    * @return array|string Array of attribute values keyed by attribute name.
    * Returns empty array if there are no attributes.
    * Returns the original arguments string if it cannot be parsed.

    Why return a string of original arguments if they cannot be parsed?
    It should just ignore the “incompatible” stuff and return a solid, consistent type, in this case, array.
    This way, dependent code would not have to struggle.

    I opened an issue here https://core.trac.wordpress.org/ticket/59613

    Thanks again for your help on this.

Viewing 2 replies - 1 through 2 (of 2 total)
  • The topic ‘$atts passed to $callback of add_shortcode() is not always an array’ is closed to new replies.