Skip to:
Content

BuddyPress.org

Ticket #7226: 7226.ray.03.patch

File 7226.ray.03.patch, 18.1 KB (added by r-a-y, 3 years ago)
  • src/bp-core/classes/class-bp-button.php

     
    1414 * API to create BuddyPress buttons.
    1515 *
    1616 * @since 1.2.6
     17 * @since 2.7.0 Introduced $parent_element, $parent_attr, $button_element, $button_attr as
     18 *              $args parameters. Deprecated $wrapper, $wrapper_id, $wrapper_class,
     19 *              $link_href, $link_class, $link_id, $link_rel, $link_title as $args params.
    1720 *
    1821 * @param array $args {
    1922 *     Array of arguments.
    2023 *
    2124 *     @type string      $id                String describing the button type.
    22  *     @type string      $component         The name of the component the button belongs to.
    23  *                                          Default: 'core'.
    24  *     @type bool        $must_be_logged_in Optional. Does the user need to be logged
    25  *                                          in to see this button? Default: true.
    26  *     @type bool        $block_self        Optional. True if the button should be hidden
    27  *                                          when a user is viewing his own profile.
    28  *                                          Default: true.
    29  *     @type string|bool $wrapper           Optional. HTML element type that should wrap
    30  *                                          the button: 'div', 'span', 'p', or 'li'.
    31  *                                          False for no wrapper at all. Default: 'div'.
    32  *     @type string      $wrapper_id        Optional. DOM ID of the button wrapper element.
    33  *                                          Default: ''.
    34  *     @type string      $wrapper_class     Optional. DOM class of the button wrapper
    35  *                                          element. Default: ''.
    36  *     @type string      $link_href         Optional. Destination link of the button.
    37  *                                          Default: ''.
    38  *     @type string      $link_class        Optional. DOM class of the button. Default: ''.
    39  *     @type string      $link_id           Optional. DOM ID of the button. Default: ''.
    40  *     @type string      $link_rel          Optional. DOM 'rel' attribute of the button.
    41  *                                          Default: ''.
    42  *     @type string      $link_title        Optional. Title attribute of the button.
    43  *                                          Default: ''.
    44  *     @type string      $link_text         Optional. Text to appear on the button.
    45  *                                          Default: ''.
     25 *     @type string      $component         The name of the component the button belongs to. Default: 'core'.
     26 *     @type bool        $must_be_logged_in Optional. Does the user need to be logged in to see this button? Default:
     27 *                                          true.
     28 *     @type bool        $block_self        Optional. True if the button should be hidden when a user is viewing his
     29 *                                          own profile. Default: true.
     30 *     @type string      $parent_element    Optional. Parent element to wrap button around. Default: 'div'.
     31 *     @type array       $parent_attr       Optional. Element attributes for parent element. Set whatever attributes
     32 *                                          like 'id', 'class' as array keys.
     33 *     @type string      $button_element    Optional. Button element. Default: 'a'.
     34 *     @type array       $button_attr       Optional. Button attributes. Set whatever attributes like 'id', 'class' as
     35 *                                          array keys.
     36 *     @type string      $link_text         Optional. Text to appear on the button. Default: ''.
     37 *     @type string|bool $wrapper           Deprecated. Use $parent_element instead.
     38 *     @type string      $wrapper_id        Deprecated. Use $parent_attr and set 'id' as array key.
     39 *     @type string      $wrapper_class     Deprecated. Use $parent_attr and set 'class' as array key.
     40 *     @type string      $link_href         Deprecated. Use $button_attr and set 'href' as array key.
     41 *     @type string      $link_class        Deprecated. Use $button_attr and set 'class' as array key.
     42 *     @type string      $link_id           Deprecated. Use $button_attr and set 'id' as array key.
     43 *     @type string      $link_rel          Deprecated. Use $button_attr and set 'rel' as array key.
     44 *     @type string      $link_title        Deprecated. Use $button_attr and set 'title' as array key.
    4645 * }
    4746 */
    4847class BP_Button {
     
    8079        /** Wrapper ***************************************************************/
    8180
    8281        /**
     82         * Parent element to wrap button around.
     83         *
     84         * @since 2.7.0
     85         *
     86         * @var string Default: 'div'.
     87         */
     88        public $parent_element = 'div';
     89
     90        /**
     91         * Element attributes for parent element.
     92         *
     93         * @since 2.7.0
     94         *
     95         * @var array Set whatever attributes like 'id', 'class' as array key.
     96         */
     97        public $parent_attr = array();
     98
     99        /** Button ****************************************************************/
     100
     101        /**
     102         * Button element.
     103         *
     104         * @since 2.7.0
     105         *
     106         * @var string Default: 'a'.
     107         */
     108        public $button_element = 'a';
     109
     110        /**
     111         * Button attributes.
     112         *
     113         * @since 2.7.0
     114         *
     115         * @var array Set whatever attributes like 'id', 'href' as array key.
     116         */
     117        public $button_attr = array();
     118
     119        /**
     120         * The contents of the button link.
     121         *
     122         * @var string
     123         */
     124        public $link_text = '';
     125
     126        /** HTML result
     127         *
     128         * @var string
     129         */
     130        public $contents = '';
     131
     132        /** Deprecated ***********************************************************/
     133
     134        /**
    83135         * The type of DOM element to use for a wrapper.
    84136         *
    85          * @var string|bool 'div', 'span', 'p', 'li', or false for no wrapper.
     137         * @deprecated 2.7.0 Use $parent_element instead.
     138         *
     139         * @var string|bool
    86140         */
    87         public $wrapper = 'div';
     141        public $wrapper = '';
    88142
    89143        /**
    90144         * The DOM class of the button wrapper.
    91145         *
     146         * @deprecated 2.7.0 Set 'class' key in $parent_attr instead.
     147         *
    92148         * @var string
    93149         */
    94150        public $wrapper_class = '';
     
    96152        /**
    97153         * The DOM ID of the button wrapper.
    98154         *
     155         * @deprecated 2.7.0 Set 'id' key in $parent_attr instead.
     156         *
    99157         * @var string
    100158         */
    101159        public $wrapper_id = '';
    102160
    103         /** Button ****************************************************************/
    104 
    105161        /**
    106162         * The destination link of the button.
    107163         *
     164         * @deprecated 2.7.0 Set 'href' key in $button_attr instead.
     165         *
    108166         * @var string
    109167         */
    110168        public $link_href = '';
     
    112170        /**
    113171         * The DOM class of the button link.
    114172         *
     173         * @deprecated 2.7.0 Set 'class' key in $button_attr instead.
     174         *
    115175         * @var string
    116176         */
    117177        public $link_class = '';
     
    119179        /**
    120180         * The DOM ID of the button link.
    121181         *
     182         * @deprecated 2.7.0 Set 'id' key in $button_attr instead.
     183         *
    122184         * @var string
    123185         */
    124186        public $link_id = '';
     
    126188        /**
    127189         * The DOM rel value of the button link.
    128190         *
     191         * @deprecated 2.7.0 Set 'rel' key in $button_attr instead.
     192         *
    129193         * @var string
    130194         */
    131195        public $link_rel = '';
     
    133197        /**
    134198         * Title of the button link.
    135199         *
    136          * @var string
    137          */
    138         public $link_title = '';
    139 
    140         /**
    141          * The contents of the button link.
    142          *
    143          * @var string
    144          */
    145         public $link_text = '';
    146 
    147         /** HTML result
     200         * @deprecated 2.7.0 Set 'title' key in $button_attr instead.
    148201         *
    149202         * @var string
    150203         */
    151         public $contents = '';
     204        public $link_title = '';
    152205
    153206        /** Methods ***************************************************************/
    154207
     
    163216
    164217                $r = wp_parse_args( $args, get_class_vars( __CLASS__ ) );
    165218
     219                // Backward compatibility with deprecated parameters.
     220                $r = $this->backward_compatibility_args( $r );
     221
     222                // Deprecated. Subject to removal in a future release.
     223                $this->wrapper = $r['wrapper'];
     224                if ( !empty( $r['link_id']    ) ) $this->link_id    = ' id="' .    $r['link_id']    . '"';
     225                if ( !empty( $r['link_href']  ) ) $this->link_href  = ' href="' .  $r['link_href']  . '"';
     226                if ( !empty( $r['link_title'] ) ) $this->link_title = ' title="' . $r['link_title'] . '"';
     227                if ( !empty( $r['link_rel']   ) ) $this->link_rel   = ' rel="' .   $r['link_rel']   . '"';
     228                if ( !empty( $r['link_class'] ) ) $this->link_class = ' class="' . $r['link_class'] . '"';
     229                if ( !empty( $r['link_text']  ) ) $this->link_text  =              $r['link_text'];
     230
    166231                // Required button properties.
    167232                $this->id                = $r['id'];
    168233                $this->component         = $r['component'];
    169234                $this->must_be_logged_in = (bool) $r['must_be_logged_in'];
    170235                $this->block_self        = (bool) $r['block_self'];
    171                 $this->wrapper           = $r['wrapper'];
    172 
    173                 // $id and $component are required
    174                 if ( empty( $r['id'] ) || empty( $r['component'] ) )
    175                         return false;
    176236
    177                 // No button if component is not active.
    178                 if ( ! bp_is_active( $this->component ) )
     237                // $id and $component are required and component must be active.
     238                if ( empty( $r['id'] ) || empty( $r['component'] ) || ! bp_is_active( $this->component ) ) {
    179239                        return false;
     240                }
    180241
    181242                // No button for guests if must be logged in.
    182                 if ( true == $this->must_be_logged_in && ! is_user_logged_in() )
     243                if ( true == $this->must_be_logged_in && ! is_user_logged_in() ) {
    183244                        return false;
     245                }
    184246
    185247                // The block_self property.
    186248                if ( true == $this->block_self ) {
    187                         // No button if you are the current user in a members loop
    188                         // This condition takes precedence, because members loops
    189                         // can be found on user profiles.
     249                        /*
     250                         * No button if you are the current user in a members loop.
     251                         *
     252                         * This condition takes precedence, because members loops can be found on user
     253                         * profiles.
     254                         */
    190255                        if ( bp_get_member_user_id() ) {
    191256                                if ( is_user_logged_in() && bp_loggedin_user_id() == bp_get_member_user_id() ) {
    192257                                        return false;
    193258                                }
    194259
    195                         // No button if viewing your own profile (and not in
    196                         // a members loop).
     260                        // No button if viewing your own profile (and not in a members loop).
    197261                        } elseif ( bp_is_my_profile() ) {
    198262                                return false;
    199263                        }
    200264                }
    201265
    202                 // Wrapper properties.
    203                 if ( false !== $this->wrapper ) {
     266                // Should we use a parent element?
     267                $parent_elem = sanitize_html_class( $r['parent_element'] );
     268                if ( ! empty( $parent_elem ) ) {
     269                        if ( ! isset( $r['parent_attr']['class'] ) ) {
     270                                $r['parent_attr']['class'] = '';
     271                        }
    204272
    205                         // Wrapper ID.
    206                         if ( !empty( $r['wrapper_id'] ) ) {
    207                                 $this->wrapper_id    = ' id="' . $r['wrapper_id'] . '"';
     273                        // Always add 'generic-button' class.
     274                        if ( false === strpos( $r['parent_attr']['class'], 'generic-button' ) ) {
     275                                if ( ! empty( $r['parent_attr']['class'] ) ) {
     276                                        $r['parent_attr']['class'] .= ' ';
     277                                }
     278                                $r['parent_attr']['class'] .= 'generic-button';
    208279                        }
    209280
    210                         // Wrapper class.
    211                         if ( !empty( $r['wrapper_class'] ) ) {
    212                                 $this->wrapper_class = ' class="generic-button ' . $r['wrapper_class'] . '"';
    213                         } else {
    214                                 $this->wrapper_class = ' class="generic-button"';
     281                        // Render parent element attributes.
     282                        $parent_attr = '';
     283                        foreach( $r['parent_attr'] as $attr => $val ) {
     284                                $parent_attr .= sprintf( '%s="%s" ', sanitize_html_class( $attr ), esc_attr( $val ) );
    215285                        }
    216286
    217287                        // Set before and after.
    218                         $before = '<' . $r['wrapper'] . $this->wrapper_class . $this->wrapper_id . '>';
    219                         $after  = '</' . $r['wrapper'] . '>';
     288                        $before = sprintf( '<%1$s %2$s>', $parent_elem, $parent_attr );
     289                        $after  = sprintf( '</%s>', $parent_elem );
    220290
    221                 // No wrapper.
     291                // No parent element.
    222292                } else {
    223293                        $before = $after = '';
    224294                }
    225295
    226                 // Link properties.
    227                 if ( !empty( $r['link_id']    ) ) $this->link_id    = ' id="' .    $r['link_id']    . '"';
    228                 if ( !empty( $r['link_href']  ) ) $this->link_href  = ' href="' .  $r['link_href']  . '"';
    229                 if ( !empty( $r['link_title'] ) ) $this->link_title = ' title="' . $r['link_title'] . '"';
    230                 if ( !empty( $r['link_rel']   ) ) $this->link_rel   = ' rel="' .   $r['link_rel']   . '"';
    231                 if ( !empty( $r['link_class'] ) ) $this->link_class = ' class="' . $r['link_class'] . '"';
    232                 if ( !empty( $r['link_text']  ) ) $this->link_text  =              $r['link_text'];
     296                // Button properties.
     297                $button = '';
     298                $button_elem = sanitize_html_class( $r['button_element'] );
     299                if ( ! empty( $button_elem ) ) {
     300                        // Render button attributes.
     301                        $button_attr = '';
     302                        foreach( $r['button_attr'] as $attr => $val ) {
     303                                if ( 'href' === $attr || 'formaction' === $attr || 'src' === $attr ) {
     304                                        $val = esc_url( $val );
     305                                } else {
     306                                        $val = esc_attr( $val );
     307                                }
     308
     309                                $button_attr .= sprintf( '%s="%s" ', sanitize_html_class( $attr ), $val );
     310                        }
     311
     312                        // <input> / <img> is self-closing.
     313                        if ( 'input' === $button_elem || 'img' === $button_elem ) {
     314                                $button = sprintf( '<%1$s %2$s />',
     315                                        $button_elem,
     316                                        $button_attr
     317                                );
     318
     319                        // All other elements.
     320                        } else {
     321                                $button = sprintf( '<%1$s %2$s>%3$s</%1$s>',
     322                                        $button_elem,
     323                                        $button_attr,
     324                                        ! empty( $r['link_text'] ) ? $r['link_text'] : ''
     325                                );
     326                        }
     327                }
    233328
    234329                // Build the button.
    235                 $this->contents = $before . '<a'. $this->link_href . $this->link_title . $this->link_id . $this->link_rel . $this->link_class . '>' . $this->link_text . '</a>' . $after;
     330                $this->contents = $before . $button . $after;
    236331
    237332                /**
    238333                 * Filters the button based on class parameters.
     
    241336                 * allows button to be manipulated externally.
    242337                 *
    243338                 * @since 1.2.6
     339                 * @since 2.7.0 Added $r as a parameter.
    244340                 *
    245341                 * @param string    $contents HTML being used for the button.
    246342                 * @param BP_Button $this     Current BP_Button instance.
    247343                 * @param string    $before   HTML appended before the actual button.
    248344                 * @param string    $after    HTML appended after the actual button.
     345                 * @param array     $r        Parsed button arguments.
    249346                 */
    250                 $this->contents = apply_filters( 'bp_button_' . $this->component . '_' . $this->id, $this->contents, $this, $before, $after );
     347                $this->contents = apply_filters( 'bp_button_' . $this->component . '_' . $this->id, $this->contents, $this, $before, $after, $r );
     348        }
     349
     350        /**
     351         * Provide backward compatibility for deprecated button arguments.
     352         *
     353         * @since 2.7.0.
     354         *
     355         * @param  array $r See {@link BP_Button} class for full documentation.
     356         * @return array
     357         */
     358        protected function backward_compatibility_args( $r = array() ) {
     359                // Array of deprecated arguments.
     360                $backpat_args = array(
     361                        'wrapper', 'wrapper_class', 'wrapper_id',
     362                        'link_href', 'link_class', 'link_id', 'link_rel', 'link_title'
     363                );
     364
     365                foreach ( $backpat_args as $prop ) {
     366                        if ( empty( $r[ $prop ] ) ) {
     367                                continue;
     368                        }
     369
     370                        $parent = $child = false;
     371                        $sep    = strpos( $prop, '_' );
     372
     373                        // Check if this is an attribute.
     374                        if ( false !== $sep ) {
     375                                $child  = true;
     376                                $parent = substr( $prop, 0, $sep );
     377                        } else {
     378                                $parent = $prop;
     379                        }
     380
     381                        if ( 'wrapper' === $parent ) {
     382                                $parent = 'parent';
     383                        } else {
     384                                $parent = 'button';
     385                        }
     386
     387                        // Set element.
     388                        if ( false === $child ) {
     389                                $r[ "{$parent}_element" ] = $r[ $prop ];
     390
     391                        // Set attributes.
     392                        } elseif ( true === $child ) {
     393                                $new_prop = substr( $prop, strpos( $prop, '_' ) +1 );
     394                                if ( empty( $r[ "{$parent}_attr" ] ) ) {
     395                                        $r[ "{$parent}_attr" ] = array();
     396                                }
     397
     398                                if ( empty( $r[ "{$parent}_attr" ][ $new_prop ] ) ) {
     399                                        $r[ "{$parent}_attr" ][ $new_prop ] = $r[ $prop ];
     400                                }
     401                        }
     402                }
     403
     404                return $r;
    251405        }
    252406
    253407        /**
  • tests/phpunit/testcases/core/class-bp-button.php

     
    162162                // clean up
    163163                $GLOBALS['members_template'] = null;
    164164        }
     165
     166        /**
     167         * @ticket BP7226
     168         */
     169        public function test_bp_button_new_args() {
     170                $b = new BP_Button( array(
     171                        'id' => 'foo',
     172                        'component' => 'members',
     173                        'block_self' => false,
     174                        'must_be_logged_in' => false,
     175                        'parent_element' => 'section',
     176                        'parent_attr' => array(
     177                                'class' => 'section-class',
     178                                'id' => 'section-id',
     179                                'data-parent' => 'foo',
     180                        ),
     181                        'button_element' => 'button',
     182                        'button_attr' => array(
     183                                'autofocus' => 'autofocus',
     184                                'type' => 'submit',
     185                                'name' => 'my-button'
     186                        )
     187                ) );
     188
     189                $this->assertNotFalse( strpos( $b->contents, '<section ' ) );
     190                $this->assertNotFalse( strpos( $b->contents, 'class="section-class ' ) );
     191                $this->assertNotFalse( strpos( $b->contents, 'id="section-id"' ) );
     192                $this->assertNotFalse( strpos( $b->contents, 'data-parent="foo"' ) );
     193                $this->assertNotFalse( strpos( $b->contents, '<button ' ) );
     194                $this->assertNotFalse( strpos( $b->contents, 'autofocus="autofocus"' ) );
     195                $this->assertNotFalse( strpos( $b->contents, 'type="submit"' ) );
     196                $this->assertNotFalse( strpos( $b->contents, 'name="my-button"' ) );
     197        }
     198
     199        /**
     200         * @ticket BP7226
     201         */
     202        public function test_bp_button_deprecated_args_should_still_render() {
     203                $b = new BP_Button( array(
     204                        'id' => 'foo',
     205                        'component' => 'members',
     206                        'block_self' => false,
     207                        'must_be_logged_in' => false,
     208                        'wrapper' => 'section',
     209                        'wrapper_class' => 'section-class',
     210                        'wrapper_id' => 'section-id',
     211                        'link_href' => 'http://example.com',
     212                        'link_class' => 'link-class',
     213                        'link_id' => 'link-id',
     214                        'link_rel' => 'nofollow',
     215                        'link_title' => 'link-title'
     216                ) );
     217
     218                $this->assertNotFalse( strpos( $b->contents, '<section ' ) );
     219                $this->assertNotFalse( strpos( $b->contents, 'class="section-class ' ) );
     220                $this->assertNotFalse( strpos( $b->contents, 'id="section-id"' ) );
     221                $this->assertNotFalse( strpos( $b->contents, 'href="http://example.com"' ) );
     222                $this->assertNotFalse( strpos( $b->contents, 'class="link-class"' ) );
     223                $this->assertNotFalse( strpos( $b->contents, 'id="link-id"' ) );
     224                $this->assertNotFalse( strpos( $b->contents, 'rel="nofollow"' ) );
     225                $this->assertNotFalse( strpos( $b->contents, 'title="link-title"' ) );
     226        }
     227
     228        /**
     229         * @ticket BP7226
     230         */
     231        public function test_bp_button_new_element_attrs_have_precedence_over_deprecated_element_attrs() {
     232                $b = new BP_Button( array(
     233                        'id' => 'foo',
     234                        'component' => 'members',
     235                        'block_self' => false,
     236                        'must_be_logged_in' => false,
     237                        'button_element' => 'button',
     238                        'button_attr' => array(
     239                                'class' => 'new-class',
     240                        ),
     241                        'link_class' => 'old-class'
     242                ) );
     243
     244                $this->assertNotFalse( strpos( $b->contents, '<button class="new-class"' ) );
     245        }
    165246}