/** * @internal * {@inheritdoc} */ protected function _render($id, $option, $data) { if (empty($data['value']) || !is_array($data['value'])) { $data['value'] = array(); } $controls = array_merge(array('delete' => '<small class="dashicons dashicons-no-alt" title="' . esc_attr__('Remove', 'fw') . '"></small>'), $option['box-controls']); if (isset($controls['delete'])) { $_delete = $controls['delete']; unset($controls['delete']); $controls['delete'] = $_delete; unset($_delete); } $collected = array(); fw_collect_first_level_options($collected, $option['box-options']); $box_options =& $collected['groups_and_options']; unset($collected); $option['attr']['data-for-js'] = json_encode(array('options' => $this->transform_options($box_options), 'template' => $option['template'])); return fw_render_view(fw_get_framework_directory('/includes/option-types/' . $this->get_type() . '/view.php'), array('id' => $id, 'option' => $option, 'data' => $data, 'controls' => $controls, 'box_options' => $box_options)); }
/** * Collect correct options from the first level of the array and group them * @param array $collected Will be filled with found correct options * @param array $options * * @deprecated * It is deprecated since 2.4 because container types were added and there can be any type of containers * but this function is hardcoded only for tab,box,group. * Use fw_collect_options() */ function fw_collect_first_level_options(&$collected, &$options) { if (empty($options)) { return; } if (empty($collected)) { $collected['tabs'] = $collected['boxes'] = $collected['groups'] = $collected['options'] = $collected['groups_and_options'] = $collected['all'] = array(); } foreach ($options as $option_id => &$option) { if (isset($option['options'])) { // this is container for other options switch ($option['type']) { case 'tab': $collected['tabs'][$option_id] =& $option; break; case 'box': $collected['boxes'][$option_id] =& $option; break; case 'group': $collected['groups'][$option_id] =& $option; $collected['groups_and_options'][$option_id] =& $option; break; default: trigger_error('Invalid option container type: ' . $option['type'], E_USER_WARNING); continue 2; } $collected['all'][$option['type'] . ':~:' . $option_id] = array('type' => $option['type'], 'id' => $option_id, 'option' => &$option); } elseif (is_int($option_id) && is_array($option) && isset($options[0])) { /** * Array "without key" containing options. * * This happens when options are returned into array from a function: * $options = array( * 'foo' => array('type' => 'text'), * 'bar' => array('type' => 'textarea'), * * // this is our case * // go inside this array and extract the options as they are on the same array level * array( * 'hello' => array('type' => 'text'), * ), * * // there can be any nested arrays * array( * array( * array( * 'h1' => array('type' => 'text'), * ), * ), * ), * ) */ fw_collect_first_level_options($collected, $option); } elseif (isset($option['type'])) { // simple option, last possible level in options array $collected['options'][$option_id] =& $option; $collected['groups_and_options'][$option_id] =& $option; $collected['all']['option' . ':~:' . $option_id] = array('type' => 'option', 'id' => $option_id, 'option' => &$option); } else { trigger_error('Invalid option: ' . $option_id, E_USER_WARNING); } } unset($option); }
<?php if (!defined('FW')) { die('Forbidden'); } /** * @var string $id * @var array $option * @var array $data * @var array $controls */ $attr = $option['attr']; unset($attr['name']); unset($attr['value']); $collected = array(); fw_collect_first_level_options($collected, $option['box-options']); $box_options =& $collected['groups_and_options']; unset($collected); ob_start(); ?> <small class="fw-option-box-controls"> <?php foreach ($controls as $c_id => $control) { ?> <small class="fw-option-box-control-wrapper"><a href="#" class="fw-option-box-control" data-control-id="<?php echo esc_attr($c_id); ?> " onclick="return false"><?php echo $control; ?> </a></small>
/** * Render options array and return HTML * Can contain: tabs, boxes and options */ public function render_options(&$options, &$values = array(), $options_data = array(), $design = 'default') { /** * register scripts and styles * in case if this method is called before enqueue_scripts action * and option types has some of these in their dependencies */ $this->register_static(); wp_enqueue_style('fw-backend-options'); wp_enqueue_script('fw-backend-options'); $collected = array(); fw_collect_first_level_options($collected, $options); ob_start(); if (!empty($collected['tabs'])) { echo fw_render_view(FW_DIR . '/views/backend-tabs.php', array('tabs' => &$collected['tabs'], 'values' => &$values, 'options_data' => $options_data)); } unset($collected['tabs']); if (!empty($collected['boxes'])) { echo '<div class="fw-postboxes">'; foreach ($collected['boxes'] as $id => &$box) { $attr = isset($box['attr']) ? $box['attr'] : array(); unset($attr['id']); // do not allow id overwrite, it is sent in first argument of render_box() echo $this->render_box('fw-options-box-' . $id, empty($box['title']) ? ' ' : $box['title'], $this->render_options($box['options'], $values, $options_data), array('attr' => $attr)); } echo '</div>'; } unset($collected['boxes']); if (!empty($collected['groups_and_options'])) { foreach ($collected['groups_and_options'] as $id => &$option) { if (isset($option['options'])) { $attr = isset($option['attr']) ? $option['attr'] : array(); $attr['id'] = 'fw-backend-options-group-' . esc_attr($id); if (!isset($attr['class'])) { $attr['class'] = 'fw-backend-options-group'; } else { $attr['class'] = 'fw-backend-options-group ' . $attr['class']; } echo '<div ' . fw_attr_to_html($attr) . '>'; echo $this->render_options($option['options'], $values, $options_data); echo '</div>'; } else { // option $data = $options_data; $data['value'] = isset($values[$id]) ? $values[$id] : null; echo $this->render_option($id, $option, $data, $design); } } } unset($collected['options']); return ob_get_clean(); }
/** * @param WP_Customize_Manager $wp_customize * @param array $options * @param array $parent_data {'type':'...','id':'...'} */ private function customizer_register_options($wp_customize, $options, $parent_data = array()) { $collected = array(); fw_collect_first_level_options($collected, $options); if (empty($collected['all'])) { return; } foreach ($collected['all'] as &$opt) { switch ($opt['type']) { case 'tab': $args = array('title' => $opt['option']['title'], 'description' => empty($opt['option']['desc']) ? '' : $opt['option']['desc']); if ($parent_data) { trigger_error('Not supported panel parent, type: ' . $parent_data['type'], E_USER_WARNING); break; } $wp_customize->add_panel($opt['id'], $args); $this->customizer_register_options($wp_customize, $opt['option']['options'], array('type' => 'panel', 'id' => $opt['id'])); break; case 'box': $args = array('title' => $opt['option']['title']); if ($parent_data) { if ($parent_data['type'] === 'panel') { $args['panel'] = $parent_data['id']; } else { trigger_error('Not supported section parent, type: ' . $parent_data['type'], E_USER_WARNING); break; } } $wp_customize->add_section($opt['id'], $args); $this->customizer_register_options($wp_customize, $opt['option']['options'], array('type' => 'section', 'id' => $opt['id'])); break; case 'option': $setting_id = FW_Option_Type::get_default_name_prefix() . '[' . $opt['id'] . ']'; $args = array('label' => empty($opt['option']['label']) ? '' : $opt['option']['label'], 'description' => empty($opt['option']['desc']) ? '' : $opt['option']['desc'], 'settings' => $setting_id, 'type' => 'radio', 'choices' => array('a' => 'Demo A', 'b' => 'Demo B')); if ($parent_data) { if ($parent_data['type'] === 'section') { $args['section'] = $parent_data['id']; } else { trigger_error('Not supported control parent, type: ' . $parent_data['type'], E_USER_WARNING); break; } } else { // the option is not placed in a section, create a section automatically $args['section'] = 'fw_option_auto_section_' . $opt['id']; $wp_customize->add_section($args['section'], array('title' => empty($opt['option']['label']) ? fw_id_to_title($opt['id']) : $opt['option']['label'])); } if (!class_exists('_FW_Customizer_Control_Option_Wrapper')) { require_once fw_get_framework_directory('/includes/customizer/class--fw-customizer-control-option-wrapper.php'); } $wp_customize->add_setting($setting_id, array('default' => fw()->backend->option_type($opt['option']['type'])->get_value_from_input($opt['option'], null))); $control = new _FW_Customizer_Control_Option_Wrapper($wp_customize, $opt['id'], $args, array('fw_option' => $opt['option'])); add_filter("customize_sanitize_{$setting_id}", array($control, 'setting_sanitize_callback'), 10, 2); $wp_customize->add_control($control); break; default: trigger_error('Not supported option in customizer, type: ' . $opt['type'], E_USER_WARNING); // todo: uncomment } } }
/** * Collect correct options from first level on the array and group them * @param array $collected Will be filled with found correct options * @param array $options */ function fw_collect_first_level_options(&$collected, &$options) { if (empty($options)) { return; } if (empty($collected)) { $collected['tabs'] = array(); $collected['boxes'] = array(); $collected['groups'] = array(); $collected['options'] = array(); $collected['groups_and_options'] = array(); } foreach ($options as $option_id => &$option) { if (isset($option['options'])) { // this is container for other options switch ($option['type']) { case 'tab': $collected['tabs'][$option_id] =& $option; break; case 'box': $collected['boxes'][$option_id] =& $option; break; case 'group': $collected['groups'][$option_id] =& $option; $collected['groups_and_options'][$option_id] =& $option; break; default: trigger_error('Invalid option container type: ' . $option['type'], E_USER_WARNING); } } elseif (is_int($option_id) && is_array($option)) { // array with options fw_collect_first_level_options($collected, $option); } elseif (isset($option['type'])) { // simple option, last possible level in options array $collected['options'][$option_id] =& $option; $collected['groups_and_options'][$option_id] =& $option; } else { trigger_error('Invalid option: ' . $option_id, E_USER_WARNING); } } }
/** * Render options array and return the generated HTML * * @param array $options * @param array $values Correct values returned by fw_get_options_values_from_input() * @param array $options_data {id_prefix => ..., name_prefix => ...} * @param string $design * * @return string HTML */ public function render_options($options, $values = array(), $options_data = array(), $design = 'default') { /** * register scripts and styles * in case if this method is called before enqueue_scripts action * and option types has some of these in their dependencies */ $this->register_static(); wp_enqueue_media(); wp_enqueue_style('fw-backend-options'); wp_enqueue_script('fw-backend-options'); $collected = array(); fw_collect_first_level_options($collected, $options); if (empty($collected['all'])) { return false; } $html = ''; $option = reset($collected['all']); $collected_type = $option['type']; $collected_type_options = array($option['id'] => &$option['option']); while ($collected_type_options) { $option = next($collected['all']); if ($option) { if ($option['type'] === $collected_type) { $collected_type_options[$option['id']] =& $option['option']; continue; } } switch ($collected_type) { case 'tab': $html .= fw_render_view(fw_get_framework_directory('/views/backend-tabs.php'), array('tabs' => &$collected_type_options, 'values' => &$values, 'options_data' => $options_data)); break; case 'box': $html .= '<div class="fw-backend-postboxes metabox-holder">'; foreach ($collected_type_options as $id => &$box) { $attr = isset($box['attr']) ? $box['attr'] : array(); unset($attr['id']); // do not allow id overwrite, it is sent in first argument of render_box() $html .= $this->render_box('fw-options-box-' . $id, empty($box['title']) ? ' ' : $box['title'], $this->render_options($box['options'], $values, $options_data), array('attr' => $attr)); } unset($box); $html .= '</div>'; break; case 'group': foreach ($collected_type_options as $id => &$group) { $attr = isset($group['attr']) ? $group['attr'] : array(); $attr['id'] = 'fw-backend-options-group-' . $id; if (!isset($attr['class'])) { $attr['class'] = 'fw-backend-options-group'; } else { $attr['class'] = 'fw-backend-options-group ' . $attr['class']; } $html .= '<div ' . fw_attr_to_html($attr) . '>'; $html .= $this->render_options($group['options'], $values, $options_data); $html .= '</div>'; } unset($group); break; case 'option': foreach ($collected_type_options as $id => &$_option) { $data = $options_data; $data['value'] = isset($values[$id]) ? $values[$id] : null; $html .= $this->render_option($id, $_option, $data, $design); } unset($_option); break; default: $html .= '<p><em>' . __('Unknown collected type', 'fw') . ': ' . $collected_type . '</em></p>'; } unset($collected_type, $collected_type_options); if ($option) { $collected_type = $option['type']; $collected_type_options = array($option['id'] => &$option['option']); } else { $collected_type_options = array(); } } return $html; }