WordPress shortcode is not generating output as expected

Here is my shortcode

function feature_shortcode( $atts, $content ) {

    $atts = shortcode_atts( array(
        'main_content' => !empty($content) ? $content : "Add a feature.",
        'width' => '',
        'screen' => array( 
                            'large' => 'col-lg',
                            'medium' => 'col-md',
                            'small' => 'col-sm',
                            'smaller' => 'col-xs',),
        'class' => ' feature',
        'icon' => '',
        'link' => '',
        'title' => ''


    ), $atts );

    extract($atts);


    return '<div class="'. $screen.$width.$class .'">
            <span class="round"><i class="fa fa-'. $icon .'"></i></span>
            <h4>'. $title .'</h4>
            <p>'. $main_content .'
            <a href="'. $link .'">
            learn more <i class="fa fa-long-arrow-right">
            </i></a></p></div>';

}
add_shortcode( 'feature', 'feature_shortcode' );

Here is the shortcode in action

Read More
[feature screen="medium" width="3" icon="moon-o" title="Creative" link="https://codex.wordpress.org/Shortcode_API"]Lorem ipsum eu suspendisse, sem curabitur elit malesuada.
[/feature]

It returns

<div class="medium3 feature"> else is working fine.....</div>

But I want to return “col-md-” while using ‘medium’ as screen key. That should generate

<div class="col-md-3 feature"> else is working fine.....</div>

what should I do if I want to return

<div class="col-sm-3 col-md-3 feature"> else is working fine.....</div>

Related posts

2 comments

  1. First, decide how you want your user to list multiple screen and width values.

    For example you may want them to be listed sequentially, separated by spaces, and matching pairs of screen and width values in order of appearance, or fallback to some default width.

    [shortcode screen="long small medium" width="2 4"]
    

    could generate:

    <div class="col-lg-2 col-sm-4 col-md-3 feature">
    

    where the default width is 3.

    Next, as per Harsh Pandya’s suggestion, create an array that maps all screen values to the respective Bootstrap classes.

    $screens_map = array(
        'large' => 'col-lg-',
        'medium' => 'col-md-',
        'small' => 'col-sm-',
        'smaller' => 'col-xs-',
    );
    

    Then in your feature_shortcode function, use explode to extract the individual user-supplied values from the screen and width attributes and store them in arrays.

    $user_screens = explode(' ', $screen);
    $user_widths = explode(' ', $width);
    

    $user_screens and $user_widths will look like

    array(
       0 => 'long',
       1 => 'small',
       2 => 'medium'
    );
    

    and

    array(
       0 => '2',
       1 => '4'
    );
    

    Next, iterate through the user-supplied screen values. For each value, append a matching class to your final output. Also, if there is a matching width value – append it; otherwise, fallback to some default width.

    $default_width = '3';
    $bootstrap_class = '';
    
    foreach( $user_screens as $i => $screen_value ) :
        // match the user screen value to the bootstrap class, and append it
        $bootstrap_class .= $screens_map[ $screen_value ];
        if ( $i < count($user_widths) ) :       // if there is a matching width
            $bootstrap_class .= $user_widths[$i];     // append it to the class
        else :                                  // otherwise,
            $bootstrap_class .= $default_width;     // fallback to the default width
        endif;
    endforeach;
    

    Finally, return the $boostrap_class in your output:

    return '<div class="'. $bootstrap_class.$class .'">';
    

    Here is the complete solution:

    function feature_shortcode( $atts, $content ) {
    
        $atts = shortcode_atts( array(
            'main_content' => !empty($content) ? $content : "Add a feature.",
            'width' => '',
            'screen' => 'medium'
            'class' => ' feature',
            'icon' => '',
            'link' => '',
            'title' => ''
        ), $atts );
    
        extract($atts);
    
        // let's map the user-supplied screen values to bootstrap classes
        $screens_map = array(
            'large' => 'col-lg-',
            'medium' => 'col-md-',
            'small' => 'col-sm-',
            'smaller' => 'col-xs-'
        );
    
        // extract the individual screen and width values, and place them in arrays
        $user_screens = explode(' ', $screen);
        $user_widths = explode(' ', $width);
    
        // default width and bootstrap class value
        $default_width = '3';
        $bootstrap_class = '';
    
        // iterate over the user screens, attaching the respective bootstrap class
        foreach( $user_screens as $i => $screen_value ) :
    
            $bootstrap_class .= $screens_map[ $screen_value ];
    
            if ( $i < count($user_widths) ) :
                $bootstrap_class .= $user_widths[$i];
            else :
                $bootstrap_class .= $default_width;
            endif;
        endforeach;
    
        return '<div class="'. $bootstrap_class.$class .'">
                <span class="round"><i class="fa fa-'. $icon .'"></i></span>
                <h4>'. $title .'</h4>
                <p>'. $main_content .'
                <a href="'. $link .'">
                learn more <i class="fa fa-long-arrow-right">
                </i></a></p></div>';
    }
    add_shortcode( 'feature', 'feature_shortcode' );
    
  2. If you are giving values to screen parameter then it will replace the default array with that value so make changes in your code like this.

    $atts = shortcode_atts( array(
            'main_content' => !empty($content) ? $content : "Add a feature.",
            'width' => '',
            'screen' => 'col-md-',
            'class' => ' feature',
            'icon' => '',
            'link' => '',
            'title' => ''
    
    
    ), $atts );
    
    extract($atts);
    $all_screens =  array(
                    'large' => 'col-lg-',
                    'medium' => 'col-md-',
                    'small' => 'col-sm-',
                    'smaller' => 'col-xs-');
    
    if (array_key_exists($screen, $all_screens)) {
        $screen = $all_screens[$screen];
    }
    return '<div class="'. $screen.$width.$class .'">
            <span class="round"><i class="fa fa-'. $icon .'"></i></span>
            <h4>'. $title .'</h4>
            <p>'. $main_content .'
            <a href="'. $link .'">
            learn more <i class="fa fa-long-arrow-right">
            </i></a></p></div>';
    

Comments are closed.