[wp-trac] [WordPress Trac] #59613: Ensure $atts passed to $callback of add_shortcode() is always an array

WordPress Trac noreply at wordpress.org
Fri Oct 13 10:42:11 UTC 2023


#59613: Ensure $atts passed to $callback of add_shortcode() is always an array
-------------------------------------+-------------------------------------
 Reporter:  bedas                    |      Owner:  (none)
     Type:  defect (bug)             |     Status:  new
 Priority:  normal                   |  Milestone:  Awaiting Review
Component:  Shortcodes               |    Version:
 Severity:  normal                   |   Keywords:  has-patch 2nd-opinion
  Focuses:  docs, performance,       |  dev-feedback
  sustainability, php-compatibility  |
-------------------------------------+-------------------------------------
 == Problem

 According to
 [https://developer.wordpress.org/reference/functions/add_shortcode/ the
 documentation]:

 > `$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
 actually an empty string.
 - apparently (according to code docbloc) it would also be a string of
 original arguments if it could not be parsed.

 This discrepancy causes other dependant code to always fumble with the
 type of `$atts`, for example the
 [https://developer.wordpress.org/reference/functions/shortcode_atts/
 source code of shortcode_atts] has to typecasts `$atts` to array.
 **This would not be necessary, would `$atts` indeed be always an array
 from the start.**

 Further, in more complex programming scenarios where we assume `$atts` to
 be an array (as stated by the documentation), again we have to fumble with
 `$atts`, and in some cases, we cannot do anything but just accept that it
 may or may not be an array.
 ''You can read more on that [https://wordpress.org/support/topic/callback-
 of-add_shortcode-is-not-always-an-array/ here]''

 == Cause

 Thanks to the kind help of [https://wordpress.org/support/users/bcworkz/
 @bcworkz] and further testing, I can confirm that the issue is within
 `shortcode_parse_atts` function - to be precise in the `else` statement
 [https://core.trac.wordpress.org/browser/tags/6.3/src/wp-
 includes/shortcodes.php?marks=395-395#L601 here].
 If the checks for `if ( preg_match_all( $pattern, $text, $match,
 PREG_SET_ORDER ) ) ` fail, `$atts` is transformed to string using `ltrim`.

 This makes thus poor sense to me:
 1. First of all, the documentation mentions that `$atts` **is an array**.
 It never mentions other possible types.
 2. It seem quite clear to me that `$atts` is always supposed and intended
 to be an ''array'' - never a string.
 3. Even if the docblock for `shortcode_parse_atts` states that the
 returned value can be array ''or'' string (and if string, then the
 `original arguments string if it cannot be parsed`)... I do not see the
 actual reason or justification for this.

 What is the usefulness of returning a string of arguments if it cannot be
 parsed or is empty?
 It should then safely fail into an empty ''array'', to keep consistency
 and not force dependant code to typecast `$atts`.

 == Proposal

 Simply remove the `else` block in `shortcode_parse_atts`.
 It is redundant and creates issues in particular coding structures + clear
 discrepancies in documentation.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/59613>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list