1

I working with nested elements wp bakery . i am trying uses classes and public function .

But could not get it working . its not registering . I think its may be an issue because i used class . please find whats wrong with . i dont need a work around . i know how to work it with out member functions. but i need to do it using member functions

                <?php
            /*
             *  Element Description: Featured Block
             */
                //featured block container
                if ( class_exists( 'WPBakeryShortCodesContainer' ) ) {
                    class protechsaasFeaturedBlock extends WPBakeryShortCodesContainer {

                        // Element Init
                        function __construct() {
                            add_action( 'init', array( $this, 'protechsaas_featured_block_mapping' ) );
                            add_shortcode( 'feature_container', array( $this, 'protechsaas_featured_block_html' ) );
                        }
                        // Element Mapping
                        public function protechsaas_featured_block_mapping() {

                            // Stop all if VC is not enabled
                            if ( !defined( 'WPB_VC_VERSION' ) ) {
                                return;
                            }

                             //Register "container" content element. It will hold all your inner (child) content elements
                            vc_map( array(
                                "name" => __("Feature Block", "protechsaas"),
                                "base" => "feature_container",
                                "as_parent" => array('only' => 'feature'), // Use only|except attributes to limit child shortcodes (separate multiple values with comma)
                                "content_element" => true,
                                "show_settings_on_create" => false,
                                "is_container" => true,
                                "params" => array(
                                    // add params same as with any other content element
                                    array(
                                        "type" => "textfield",
                                        "heading" => __("Block Title", "protechsaas"),
                                        'holder' => 'h2',
                                        'class' => 'sub-title-class',
                                        "param_name" => "subtitle",
                                        "description" => __("add the title for your features block", "protechsaas")
                                    ),
                                    array(
                                        "type" => "textfield",
                                        "heading" => __("Title", "protechsaas"),
                                        'holder' => 'h2',
                                        'class' => 'title-class',
                                        "param_name" => "title",
                                        "description" => __("add the main title for your features block", "protechsaas")
                                    ),
                                    array(
                                        "type" => "textarea",
                                        "heading" => __("Content", "protechsaas"),
                                        'holder' => 'p',
                                        'class' => 'content-class',
                                        "param_name" => "content",
                                        "description" => __("add the main content for your features block", "protechsaas")
                                    ),
                                    array(
                                        'type' => 'dropdown',
                                        'holder' => 'div',
                                        'class' => 'style-class',
                                        'heading' => __( 'Block Style', 'protechsaas' ),
                                        'param_name' => 'blockstyle',
                                        'value' => array(
                                                    '1'   => 'Feature  white bg ',
                                                    '2'   => 'Feature  grey bg',
                                                    '3'   => 'Feature  icon bg none ',
                                                  ),
                                        'description' => __( 'choose you features block style', 'protechsaas' ),
                                        'admin_label' => true,
                                        'weight' => 0,
                                    ),
                                ),
                                "js_view" => 'VcColumnView'
                            ) );                             

                        }
                        // Element HTML
                        public function protechsaas_featured_block_html( $atts ,$features = null ) {

                            // Params extraction
                            extract(
                                shortcode_atts(
                                    array(
                                        'subtitle' => '',
                                        'title' => '',
                                        'content' => '',
                                        'blockstyle' => '',
                                    ), 
                                    $atts
                                )
                            );

                            switch ($blockstyle) {
                         case '1':
                            $html = '
                                    <section class="client-speak our-features padding-lg">
                                        <div class="container">
                                            <div class="row justify-content-center head-block">
                                                <div class="col-md-10"> <span>'.$subtitle.'</span>
                                                    <h2>'.$title.'</h2>
                                                    <p class="hidden-xs">'.$content.'</p>
                                                </div>
                                            </div>
                                            <ul class="row features-listing">
                                                '.do_shortcode($features).'
                                            </ul>
                                        </div>
                                    </section>'; 
                            break;
                         case '2':
                            $html = '
                                    <section class="client-speak our-features padding-lg bg-white">
                                        <div class="container">
                                            <div class="row justify-content-center head-block">
                                                <div class="col-md-10"> <span>'.$subtitle.'</span>
                                                    <h2>'.$title.'</h2>
                                                    <p class="hidden-xs">'.$content.'</p>
                                                </div>
                                            </div>
                                            <ul class="row features-listing ico-bg">
                                            '.do_shortcode($features).'
                                            </ul>
                                        </div>
                                    </section>'; 
                            break;
                         case '3':
                            $html = '
                                   <section class="client-speak our-features padding-lg">
                                        <div class="container">
                                            <div class="row justify-content-center head-block">
                                                <div class="col-md-10"> <span>'.$subtitle.'</span>
                                                    <h2>'.$title.'</h2>
                                                    <p class="hidden-xs">'.$content.'</p>
                                                </div>
                                            </div>
                                            <ul class="row features-listing bg-none">
                                                '.do_shortcode($features).'
                                            </ul>
                                        </div>
                                    </section> '; 
                            break;


                         default:
                            $html = '
                                    <section class="client-speak our-features padding-lg">
                                        <div class="container">
                                            <div class="row justify-content-center head-block">
                                                <div class="col-md-10"> <span>'.$subtitle.'</span>
                                                    <h2>'.$title.'</h2>
                                                    <p class="hidden-xs">'.$content.'</p>
                                                </div>
                                            </div>
                                            <ul class="row features-listing">
                                                '.do_shortcode($features).'
                                            </ul>
                                        </div>
                                    </section>'; 
                             break;
                    }
                            return $html;

                        }


                    }
                }

                //feature element
                if ( class_exists( 'WPBakeryShortCode' ) ) {
                    class protechsaasFeature extends WPBakeryShortCode {
                        // Element Init
                        function __construct() {
                            add_action( 'init', array( $this, 'protechsaas_feature_mapping' ) );
                            add_shortcode( 'protechsaas_feature', array( $this, 'protechsaas_feature_html' ) );
                        }
                        // Element Mapping
                        public function protechsaas_feature_mapping() {

                            // Stop all if VC is not enabled
                            if ( !defined( 'WPB_VC_VERSION' ) ) {
                                return;
                            }

                            vc_map( array(
                                "name" => __("Feature", "protechsaas"),
                                "base" => "feature",
                                "content_element" => true,
                                "as_child" => array('only' => 'feature_container'), // Use only|except attributes to limit parent (separate multiple values with comma)
                                "params" => array(
                                    // add params same as with any other content element
                                    array(
                                        "type" => "textfield",
                                        "heading" => __("title", "protechsaas"),
                                        "param_name" => "title",
                                        "description" => __("add the  title for your feature.", "protechsaas")
                                    ),
                                    array(
                                        "type" => "textarea",
                                        "heading" => __("Content", "protechsaas"),
                                        'holder' => 'p',
                                        'class' => 'content-class',
                                        "param_name" => "content",
                                        "description" => __("add the  content for your feature", "protechsaas")
                                    ),
                                    array(
                                        'type' => 'attach_image',
                                        'holder'=> 'div',
                                        'class' => '',
                                        'heading' => __('Icon image', 'protechsaas'),
                                        'param_name' => 'iconimage',
                                        'description' => __('Choose an image for icon if ypu want use your own icons else keep it blank and choose icon from next field', 'protechsaas'),
                                    ),
                                    array(
                                        'type' => 'dropdown',
                                        'holder' => 'div',
                                        'class' => 'style-class',
                                        'heading' => __( 'Saas Icons', 'protechsaas' ),
                                        'param_name' => 'icon',
                                        'value' => array(
                                                    'icon-analytics'   => 'analytics ',
                                                    'icon-responsive'   => 'responsive',
                                                    'icon-support'   => 'support',
                                                    'icon-settings'   => 'settings',
                                                    'icon-file' => 'file',
                                                    'icon-graphic' => 'graphic',
                                                  ),
                                        'description' => __( 'choose you features block style', 'protechsaas' ),
                                        'admin_label' => true,
                                        'weight' => 0,
                                    ),
                                )
                            ) );                           

                        }
                        // Element HTML
                        public function protechsaas_feature_html( $atts ) {

                            // Params extraction
                            extract(
                                shortcode_atts(
                                    array(
                                        'iconimage'   => '',
                                        'title' => '',
                                        'content' => '',
                                        'icon' => '',
                                    ), 
                                    $atts
                                )
                            );

                            if($iconimage != null){
                                $bg=wp_get_attachment_image_src($iconimage,'full');
                                $iconcontent = '<img src="'.$bg[0].'" alt="icon" class="img-fluid"/>';
                            }
                            else {
                                $iconcontent ='<span class="'.$icon.'"></span>';
                            }
                            $html='
                                <li class="col-md-4">
                                    <div class="inner"> <span class="icon">'.$iconcontent.'</span>
                                        <h3>'.$title.'</h3>
                                        <p>'.$content.'</p>
                                    </div>
                                </li>
                            ';
                            return $html;

                        }

                    }
                }

            // Element Class Init
            new protechsaasFeaturedBlock();

            new protechsaasFeature();

            ?>

4 Answers4

4

I had the same problem and took some time to figure this out. We don't want to break from our namespaced environments, and keep our classnames consistent.

There is an extra undocumented attribute you can pass to your vc_map function, and that's php_class_name.

So your code would be:

vc_map(array(
  'name' => __('Feature', 'protechsaas'),
  'php_class_name' => 'protechsaasFeaturedBlock',
));

if ( class_exists( 'WPBakeryShortCodesContainer' ) ) {
  class protechsaasFeaturedBlock extends WPBakeryShortCodesContainer {
      // Your code here
  }
}

This also works with namespaces:

'php_class_name' => '\Company\Package\protechsaasFeaturedBlock'
Fpckalk
  • 116
  • 5
  • 1
    Thank you, this is what i was looking for. – Marek Maurizio Feb 01 '19 at 15:54
  • Thanks! That's what I need to solve exactly the same problem. I had problems with namespaces and even I rename class as WPBakeryShortCode_my_shortcode_tag, it doesn't work. The 'php_class_name' array key in vc_map params is the solution. You can set this value with '\Your\Namespace\ClassName::class' (or simplify with use \Your\Namespace\ClassName and setting value to 'ClassName::class'). – Santiago Cerro López Aug 27 '21 at 18:51
2

As far as I can tell this is not documented, but if you are extending the WPBakeryShortCodesContainer class, your classname must be prefixed with WPBakeryShortCode_ and the suffix must match the name of the shortcode base you're using. There might be other limitations too, I haven't tested it extensively.

So if in vc_map() you're using:

"base" => "feature_container",

then change your class declaration to:

class WPBakeryShortCode_feature_container extends WPBakeryShortCodesContainer

I know this makes no sense, but after a lot of testing this was the cause of my code failing. I thought it was because I was declaring it as a class too instead of directly calling vc_map().

You don't even have to declare a shortcode for this to work, so I guess something in the WPBakeryShortCodesContainer class actually registers the shortcode from the base parameter if there isn't something already there?

And yes, this mega sucks if you're trying to keep your namespace clean/consistent ¯\_(ツ)_/¯

Andrew Toups
  • 189
  • 10
  • This solution worked for me, now the backend is ok (almost, the icon in the nested element is not displaying properly, it goes default with the gray cook hat). More important: the frontend is not working, there are no controls, and the elements inside are disappeared. Any idea how to fix this? – zod Mar 12 '23 at 16:48
0

I copied this as an example for nested elements. I found that there is a typo in your code. This line:

add_shortcode( 'protechsaas_feature', array( $this, 'protechsaas_feature_html' ) );

The feature name is feature instead of protechsaas_feature. This is defined here:

"base" => "feature",

So your code should become:

add_shortcode( 'feature', array( $this, 'protechsaas_feature_html' ) );
Nicky
  • 3,607
  • 6
  • 33
  • 64
0

I tried all the answers here but without success (using WPBakery 6.9).

The vc_map param "php_class_name" does nothing... not sure why some people got it working. The undocumented rule about the custom class name is a step ahead, it really needs that "WPBakeryShortCode_"+"base", but it is not enough.

So I managed to fix some problems. Also overriding a method of the core class, my answer is here: https://stackoverflow.com/a/75721948/9039682

zod
  • 407
  • 4
  • 4