private static function register_pending_item_types()
 {
     if (!is_array(self::$item_types_pending_registration)) {
         // all pending item types already registered
         return;
     }
     foreach (self::$item_types_pending_registration as $item_type_class) {
         if (is_string($item_type_class)) {
             $item_type_instance = new $item_type_class();
         } else {
             $item_type_instance = $item_type_class;
         }
         unset($item_type_class);
         if (!is_subclass_of($item_type_instance, 'FW_Option_Type_Builder_Item')) {
             trigger_error('Invalid builder item type class ' . get_class($item_type_instance), E_USER_WARNING);
             continue;
         }
         $builder_type = $item_type_instance->get_builder_type();
         /**
          * @var FW_Option_Type_Builder $builder_type_instance
          */
         $builder_type_instance = fw()->backend->option_type($builder_type);
         if (!$builder_type_instance->item_type_is_valid($item_type_instance)) {
             trigger_error('Invalid builder item. (type: ' . $item_type_instance->get_type() . ')', E_USER_WARNING);
             continue;
         }
         $builder_type_instance->_register_item_type($item_type_instance);
     }
     self::$item_types_pending_registration = false;
 }
 /**
  * @internal
  * {@inheritdoc}
  */
 protected function _render($id, $option, $data)
 {
     $static_uri = fw()->extensions->get('page-builder')->get_uri('/includes/page-builder/static');
     $version = fw()->extensions->get('page-builder')->manifest->get_version();
     wp_enqueue_style('fw-option-type-' . $this->get_type(), $static_uri . '/css/styles.css', array(), $version);
     /*
      * there should not be (and it does not make sens to be)
      * more than one page builder per page that is integrated
      * with the default post content editor
      * integration in the sens of inserting the button to activate/deactivate
      * the builder, to replace the post content with the shortcode notation
      */
     if ($this->editor_integration_enabled && $option['editor_integration'] === true) {
         trigger_error(__('There must not be more than one page Editor integrated with the wp post editor per page', 'fw'), E_USER_ERROR);
     } elseif ($option['editor_integration'] === true) {
         $this->editor_integration_enabled = true;
         wp_enqueue_style('fw-option-type-' . $this->get_type() . '-editor-integration', $static_uri . '/css/editor_integration.css', array(), $version);
         wp_enqueue_script('fw-option-type-' . $this->get_type() . '-editor-integration', $static_uri . '/js/editor_integration.js', array('jquery', 'fw-events'), $version, true);
         $builder_templates = apply_filters('fw_ext_page_builder_templates', array());
         // remove not existing templates
         $builder_templates = array_intersect(array_keys(wp_get_theme()->get_page_templates()), $builder_templates);
         /**
          * Make sure the array is not associative array('template.php', ...)
          * instead of array(2 => 'template.php', ...)
          * because the json needs to be ['template.php', ...] instead of {2: 'template.php', ...}
          */
         $builder_templates = array_values($builder_templates);
         wp_localize_script('fw-option-type-' . $this->get_type() . '-editor-integration', 'fw_option_type_' . str_replace('-', '_', $this->get_type()) . '_editor_integration_data', array('l10n' => array('showButton' => __('Visual Page Builder', 'fw'), 'hideButton' => __('Default Editor', 'fw')), 'optionId' => $option['attr']['id'], 'renderInBuilderMode' => isset($data['value']['builder_active']) ? $data['value']['builder_active'] : apply_filters('fw_page_builder_set_as_default', false), 'builderTemplates' => $builder_templates));
     }
     return parent::_render($id, $option, $data);
 }
 private static function get_access_key()
 {
     if (!self::$access_key) {
         self::$access_key = new FW_Access_Key('fw_ext_builder_option_type');
     }
     return self::$access_key;
 }
 /**
  * @internal
  */
 protected function _get_value_from_input($option, $input_value)
 {
     $value = parent::_get_value_from_input($option, $input_value);
     $value['shortcode_notation'] = $this->get_shortcode_notation(json_decode($value['json'], true));
     if ($option['editor_integration'] === true) {
         $value['builder_active'] = isset($_POST['layout-builder-active']) && $_POST['layout-builder-active'] === 'true';
     }
     return $value;
 }
    }
    /**
     * {@inheritdoc}
     */
    public function get_value_from_attributes($attributes)
    {
        return $this->get_fixed_attributes($attributes);
    }
    /**
     * {@inheritdoc}
     */
    public function frontend_render(array $item, $input_value)
    {
        return fw_render_view($this->locate_path('/views/view.php', dirname(__FILE__) . '/view.php'), array('title' => $item['options']['title'], 'subtitle' => $item['options']['subtitle']));
    }
    /**
     * {@inheritdoc}
     */
    public function frontend_validate(array $item, $input_value)
    {
    }
    /**
     * {@inheritdoc}
     */
    public function visual_only()
    {
        return true;
    }
}
FW_Option_Type_Builder::register_item_type('FW_Option_Type_Form_Builder_Item_Form_Header_Title');
                $attr['checked'] = 'checked';
            }
            $choices[] = $attr;
        }
        if ($options['randomize']) {
            shuffle($choices);
        }
        return fw_render_view($this->locate_path('/views/view.php', dirname(__FILE__) . '/view.php'), array('item' => $item, 'choices' => $choices, 'value' => $value));
    }
    /**
     * {@inheritdoc}
     */
    public function frontend_validate(array $item, $input_value)
    {
        $options = $item['options'];
        $messages = array('required' => str_replace(array('{label}'), array($options['label']), __('The {label} field is required', 'fw')), 'not_existing_choices' => str_replace(array('{label}'), array($options['label']), __('{label}: Submitted data contains not existing choices', 'fw')));
        if (empty($options['choices'])) {
            // the item was not displayed in frontend
            return;
        }
        if ($options['required'] && empty($input_value)) {
            return $messages['required'];
        }
        // check if has not existing choices
        if (!empty($input_value) && count($input_value) != count(array_intersect($options['choices'], $input_value))) {
            return $messages['not_existing_choices'];
        }
    }
}
FW_Option_Type_Builder::register_item_type('FW_Option_Type_Form_Builder_Item_Checkboxes');
                 */
                $attributes['atts'] = fw_get_options_values_from_input($shortcode_data['options'], array());
            } else {
                /**
                 * There are saved attributes.
                 * But we need to execute the _get_value_from_input() method for all options,
                 * because some of them may be (need to be) changed (auto-generated) https://github.com/ThemeFuse/Unyson/issues/275
                 * Add the values to $option['value']
                 */
                $options = fw_extract_only_options($shortcode_data['options']);
                foreach ($attributes['atts'] as $option_id => $option_value) {
                    if (isset($options[$option_id])) {
                        $options[$option_id]['value'] = $option_value;
                    }
                }
                $attributes['atts'] = fw_get_options_values_from_input($options, array());
            }
        }
        return $attributes;
    }
    public function get_shortcode_data($atts = array())
    {
        $return = array('tag' => $atts['shortcode']);
        if (isset($atts['atts'])) {
            $return['atts'] = $atts['atts'];
        }
        return $return;
    }
}
FW_Option_Type_Builder::register_item_type('Page_Builder_Simple_Item');
                 * There are saved attributes.
                 * But we need to execute the _get_value_from_input() method for all options,
                 * because some of them may be (need to be) changed (auto-generated) https://github.com/ThemeFuse/Unyson/issues/275
                 * Add the values to $option['value']
                 */
                $options = fw_extract_only_options($options);
                foreach ($attributes['atts'] as $option_id => $option_value) {
                    if (isset($options[$option_id])) {
                        $options[$option_id]['value'] = $option_value;
                    }
                }
                $attributes['atts'] = fw_get_options_values_from_input($options, array());
            }
        }
        return $attributes;
    }
    public function get_shortcode_data($atts = array())
    {
        $default_width = fw_ext_builder_get_item_width($this->get_builder_type());
        end($default_width);
        // move to the last width (usually it's the biggest)
        $default_width = key($default_width);
        $return_atts = array('width' => $default_width);
        if (isset($atts['atts'])) {
            $return_atts = array_merge($return_atts, $atts['atts']);
        }
        return array('tag' => str_replace('-', '_', $this->get_type()), 'atts' => $return_atts);
    }
}
FW_Option_Type_Builder::register_item_type('Page_Builder_Contact_Form_Item');
        return $this->get_fixed_attributes($attributes);
    }
    /**
     * {@inheritdoc}
     */
    public function frontend_render(array $item, $input_value)
    {
        $options = $item['options'];
        $attr = array('type' => 'text', 'name' => $item['shortcode'], 'placeholder' => $options['placeholder'], 'value' => is_null($input_value) ? '' : $input_value, 'id' => 'id-' . fw_unique_increment());
        if ($options['required']) {
            $attr['required'] = 'required';
        }
        return fw_render_view($this->locate_path('/views/view.php', dirname(__FILE__) . '/view.php'), array('item' => $item, 'attr' => $attr));
    }
    /**
     * {@inheritdoc}
     */
    public function frontend_validate(array $item, $input_value)
    {
        $options = $item['options'];
        $messages = array('required' => str_replace(array('{label}'), array($options['label']), __('The {label} field is required', 'fw')), 'incorrect' => str_replace(array('{label}'), array($options['label']), __('The {label} field must contain a valid email', 'fw')));
        if ($options['required'] && !fw_strlen(trim($input_value))) {
            return $messages['required'];
        }
        if (!empty($input_value) && !filter_var($input_value, FILTER_VALIDATE_EMAIL)) {
            return $messages['incorrect'];
        }
    }
}
FW_Option_Type_Builder::register_item_type('FW_Option_Type_Form_Builder_Item_Email');
     * array(
     *      'type'      => 'simple',
     *      'subtype'   => 'button',
     *      'optionValues'  => array(
     *          'size' => 'large',
     *          'type' => 'primary'
     *      )
     * )
     * @param $registered_items Option_Type_Layout_Builder_Item[] The layout builder items, useful when
     * the shortcode accepts nested shortcodes
     * @return string The shortcode notation of the shortcode ex: [button size="large" type="primary"]
     */
    public function get_shortcode_notation($atts, $registered_items)
    {
        $attributes = 'type="' . base64_encode($atts['subtype']) . '"';
        if (isset($atts['firstInRow']) && $atts['firstInRow']) {
            $attributes .= ' first_in_row="' . base64_encode('true') . '"';
        }
        $content = '';
        if (!empty($atts['_items'])) {
            foreach ($atts['_items'] as $item) {
                if (!in_array($item['type'], $this->restricted_types)) {
                    $content .= $registered_items[$item['type']]->get_shortcode_notation($item, $registered_items);
                }
            }
        }
        return "[column {$attributes}]{$content}[/column]";
    }
}
FW_Option_Type_Builder::register_item_type('FW_Option_Type_Layout_Builder_Column_Item');
                 * There are saved attributes.
                 * But we need to execute the _get_value_from_input() method for all options,
                 * because some of them may be (need to be) changed (auto-generated) https://github.com/ThemeFuse/Unyson/issues/275
                 * Add the values to $option['value']
                 */
                $options = fw_extract_only_options($options);
                foreach ($attributes['atts'] as $option_id => $option_value) {
                    if (isset($options[$option_id])) {
                        $options[$option_id]['value'] = $option_value;
                    }
                }
                $attributes['atts'] = fw_get_options_values_from_input($options, array());
            }
        }
        return $attributes;
    }
    public function get_shortcode_data($atts = array())
    {
        $default_width = fw_ext_builder_get_item_width($this->get_builder_type());
        end($default_width);
        // move to the last width (usually it's the biggest)
        $default_width = key($default_width);
        $return_atts = array('width' => $atts['width'] ? $atts['width'] : $default_width);
        if (isset($atts['atts'])) {
            $return_atts = array_merge($return_atts, $atts['atts']);
        }
        return array('tag' => $this->get_type(), 'atts' => $return_atts);
    }
}
FW_Option_Type_Builder::register_item_type('Page_Builder_Column_Item');
    {
        $options = $item['options'];
        $attr = array('type' => 'text', 'name' => $item['shortcode'], 'placeholder' => $options['placeholder'], 'value' => is_null($input_value) ? $options['default_value'] : $input_value, 'id' => 'id-' . fw_unique_increment());
        if ($options['required']) {
            $attr['required'] = 'required';
        }
        return fw_render_view($this->locate_path('/views/view.php', dirname(__FILE__) . '/view.php'), array('item' => $item, 'attr' => $attr));
    }
    /**
     * {@inheritdoc}
     */
    public function frontend_validate(array $item, $input_value)
    {
        $options = $item['options'];
        $messages = array('required' => str_replace(array('{label}'), array($options['label']), __('The {label} field is required', 'fw')), 'incorrect' => str_replace(array('{label}'), array($options['label']), __('The {label} field must be a valid website name', 'fw')));
        if (!$options['required'] && !fw_strlen(trim($input_value))) {
            return null;
        }
        if ($options['required'] && !fw_strlen(trim($input_value))) {
            return $messages['required'];
        }
        if (!preg_match('/^https?:\\/\\//', $input_value)) {
            $input_value = 'http://' . $input_value;
        }
        if (!empty($input_value) && !filter_var($input_value, FILTER_VALIDATE_URL)) {
            return $messages['incorrect'];
        }
    }
}
FW_Option_Type_Builder::register_item_type('FW_Option_Type_Form_Builder_Item_Website');
<?php

if (!defined('FW')) {
    die('Forbidden');
}
class Page_Builder_Row_Item extends Page_Builder_Item
{
    public function get_type()
    {
        return 'row';
    }
    public function enqueue_static()
    {
    }
    protected function get_thumbnails_data()
    {
        return array();
    }
    public function get_value_from_attributes($attributes)
    {
        $attributes['type'] = $this->get_type();
        return $attributes;
    }
    public function get_shortcode_data($atts = array())
    {
        return array('tag' => $this->get_type());
    }
}
FW_Option_Type_Builder::register_item_type('Page_Builder_Row_Item');
 /**
  * @internal
  * {@inheritdoc}
  */
 protected function _enqueue_static($id, $option, $data)
 {
     parent::_enqueue_static($id, $option, $data);
     wp_enqueue_style('fw-builder-' . $this->get_type(), fw_get_framework_directory_uri('/extensions/forms/includes/option-types/' . $this->get_type() . '/static/css/styles.css'), array('fw'));
     wp_enqueue_script('fw-builder-' . $this->get_type(), fw_get_framework_directory_uri('/extensions/forms/includes/option-types/' . $this->get_type() . '/static/js/helpers.js'), array('fw'), false, true);
 }
        wp_register_script('g-recaptcha', 'https://www.google.com/recaptcha/api.js?onload=fw_forms_builder_item_recaptcha_init&render=explicit&hl=' . get_locale(), array('jquery'), null, true);
        wp_enqueue_script('frontend-recaptcha', $this->get_uri('/static/js/frontend-recaptcha.js'), array('g-recaptcha'), fw_ext('forms')->manifest->get_version(), true);
        wp_localize_script('frontend-recaptcha', 'form_builder_item_recaptcha', array('site_key' => $keys['site-key']));
        return fw_render_view($this->locate_path('/views/view.php', dirname(__FILE__) . '/view.php'), array('item' => $item, 'label' => isset($input_value['label']) ? $input_value['label'] : __('Security Code', 'fw'), 'attr' => array('class' => 'form-builder-item-recaptcha')));
    }
    /**
     * {@inheritdoc}
     */
    public function frontend_validate(array $item, $input_value)
    {
        $mesages = array('not-configured' => __('Could not validate the form', 'fw'), 'not-human' => __('Please fill the recaptcha', 'fw'));
        $keys = fw_ext('forms')->get_db_settings_option('recaptcha-keys');
        if (empty($keys)) {
            return $mesages['not-configured'];
        }
        $recaptcha = new ReCaptcha($keys['secret-key']);
        $gRecaptchaResponse = FW_Request::POST('g-recaptcha-response');
        if (empty($gRecaptchaResponse)) {
            return $mesages['not-human'];
        }
        $resp = $recaptcha->verify($gRecaptchaResponse);
        if ($resp->isSuccess()) {
            return false;
        } else {
            $errors = $resp->getErrorCodes();
            return $mesages['not-human'];
        }
    }
}
FW_Option_Type_Builder::register_item_type('FW_Option_Type_Form_Builder_Item_Recaptcha');
        }
        $length = fw_strlen($input_value);
        if ($length && !empty($options['constraints']['constraint'])) {
            $constraint = $options['constraints']['constraint'];
            $constraint_data = $options['constraints'][$constraint];
            switch ($constraint) {
                case 'characters':
                    if ($constraint_data['min'] && $length < $constraint_data['min']) {
                        return sprintf($messages['characters_min_' . ($constraint_data['min'] == 1 ? 'singular' : 'plural')], $constraint_data['min']);
                    }
                    if ($constraint_data['max'] && $length > $constraint_data['max']) {
                        return sprintf($messages['characters_max_' . ($constraint_data['max'] == 1 ? 'singular' : 'plural')], $constraint_data['max']);
                    }
                    break;
                case 'words':
                    $words_length = count(preg_split('/\\s+/', $input_value));
                    if ($constraint_data['min'] && $words_length < $constraint_data['min']) {
                        return sprintf($messages['words_min_' . ($constraint_data['min'] == 1 ? 'singular' : 'plural')], $constraint_data['min']);
                    }
                    if ($constraint_data['max'] && $words_length > $constraint_data['max']) {
                        return sprintf($messages['words_max_' . ($constraint_data['max'] == 1 ? 'singular' : 'plural')], $constraint_data['max']);
                    }
                    break;
                default:
                    return 'Unknown constraint: ' . $constraint;
            }
        }
    }
}
FW_Option_Type_Builder::register_item_type('FW_Option_Type_Form_Builder_Item_Textarea');
        }
        if (!empty($input_value) && !empty($options['constraints']['constraint'])) {
            $constraint = $options['constraints']['constraint'];
            $constraint_data = $options['constraints'][$constraint];
            switch ($constraint) {
                case 'digits':
                    $length = fw_strlen(str_replace(array(',', '.', '-'), '', $input_value));
                    if ($constraint_data['min'] && $length < $constraint_data['min']) {
                        return sprintf($messages['digits_min_' . ($constraint_data['min'] == 1 ? 'singular' : 'plural')], $constraint_data['min']);
                    }
                    if ($constraint_data['max'] && $length > $constraint_data['max']) {
                        return sprintf($messages['digits_max_' . ($constraint_data['max'] == 1 ? 'singular' : 'plural')], $constraint_data['max']);
                    }
                    break;
                case 'value':
                    $value = doubleval($input_value);
                    if (!is_null($constraint_data['min']) && $value < $constraint_data['min']) {
                        return sprintf($messages['value_min'], $constraint_data['min'], $constraint_data['min'] == 1 ? '' : 's');
                    }
                    if (!is_null($constraint_data['max']) && $value > $constraint_data['max']) {
                        return sprintf($messages['value_max'], $constraint_data['max'], $constraint_data['max'] == 1 ? '' : 's');
                    }
                    break;
                default:
                    return 'Unknown constraint: ' . $constraint;
            }
        }
    }
}
FW_Option_Type_Builder::register_item_type('FW_Option_Type_Form_Builder_Item_Number');
                $attr['checked'] = 'checked';
            }
            $choices[] = $attr;
        }
        if ($options['randomize']) {
            shuffle($choices);
        }
        return fw_render_view($this->locate_path('/views/view.php', dirname(__FILE__) . '/view.php'), array('item' => $item, 'choices' => $choices, 'value' => $value));
    }
    /**
     * {@inheritdoc}
     */
    public function frontend_validate(array $item, $input_value)
    {
        $options = $item['options'];
        $messages = array('required' => str_replace(array('{label}'), array($options['label']), __('The {label} field is required', 'fw')), 'not_existing_choice' => str_replace(array('{label}'), array($options['label']), __('{label}: Submitted data contains not existing choice', 'fw')));
        if (empty($options['choices'])) {
            // the item was not displayed in frontend
            return;
        }
        if ($options['required'] && empty($input_value)) {
            return $messages['required'];
        }
        // check if has not existing choices
        if (!empty($input_value) && !in_array($input_value, $options['choices'])) {
            return $messages['not_existing_choice'];
        }
    }
}
FW_Option_Type_Builder::register_item_type('FW_Option_Type_Form_Builder_Item_Radio');
                $attr['selected'] = 'selected';
            }
            $choices[] = $attr;
        }
        if ($options['randomize']) {
            shuffle($choices);
        }
        return fw_render_view($this->locate_path('/views/view.php', dirname(__FILE__) . '/view.php'), array('item' => $item, 'choices' => $choices, 'value' => $value, 'attr' => array('type' => 'select', 'name' => $item['shortcode'], 'id' => 'id-' . fw_unique_increment())));
    }
    /**
     * {@inheritdoc}
     */
    public function frontend_validate(array $item, $input_value)
    {
        $options = $item['options'];
        $messages = array('required' => str_replace(array('{label}'), array($options['label']), __('The {label} field is required', 'fw')), 'not_existing_choice' => str_replace(array('{label}'), array($options['label']), __('{label}: Submitted data contains not existing choice', 'fw')));
        if (empty($options['choices'])) {
            // the item was not displayed in frontend
            return;
        }
        if ($options['required'] && empty($input_value)) {
            return $messages['required'];
        }
        // check if has not existing choices
        if (!empty($input_value) && !in_array($input_value, $options['choices'])) {
            return $messages['not_existing_choice'];
        }
    }
}
FW_Option_Type_Builder::register_item_type('FW_Option_Type_Form_Builder_Item_Select');
    }
    /**
     * Transforms the array representation of the shortcode to shortcode notation
     *
     * @param $atts array The array representation of the shortcode ex:
     * array(
     *      'type'      => 'simple',
     *      'subtype'   => 'button',
     *      'optionValues'  => array(
     *          'size' => 'large',
     *          'type' => 'primary',
     *      )
     * )
     * @param $registered_items Option_Type_Layout_Builder_Item[] The layout builder items, useful when
     * the shortcode accepts nested shortcodes
     * @return string The shortcode notation of the shortcode ex: [button size="large" type="primary"]
     */
    public function get_shortcode_notation($atts, $registered_items)
    {
        $shortcode = fw()->extensions->get('shortcodes')->get_shortcode($atts['subtype']);
        if ($shortcode) {
            $values = isset($atts['optionValues']) ? $atts['optionValues'] : array();
            $shortcode_notation = $shortcode->generate_shortcode_notation($values);
            return $shortcode_notation;
        } else {
            return '';
        }
    }
}
FW_Option_Type_Builder::register_item_type('FW_Option_Type_Layout_Builder_Simple_Item');