public function test_fw_collect_options() { $options = array('b1' => array('type' => 'box', 'options' => array('b1o1' => array('type' => 'text'), 'b1o2' => array('type' => 'textarea'))), 't1' => array('type' => 'tab', 'options' => array('t1o1' => array('type' => 'select'), 't1o2' => array('type' => 'radio'))), array('t2' => array('type' => 'tab', 'options' => array('t2o1' => array('type' => 'text')))), array(array('t3' => array('type' => 'tab', 'options' => array('t3o1' => array('type' => 'text'))))), 'g1' => array('type' => 'group', 'options' => array('g1o1' => array('type' => 'checkbox'), 'g1o2' => array('type' => 'checkboxes'))), 'g2' => array('type' => 'group', 'options' => array('g2o1' => array('type' => 'checkbox'), array('g2o2' => array('type' => 'checkboxes')), array(array('g2o2' => array('type' => 'checkboxes'))))), 'g3' => array('type' => 'group', 'options' => array(array('g2o2' => array('type' => 'checkboxes')), array(array('g2o2' => array('type' => 'checkboxes'))), 'g2o1' => array('type' => 'checkbox'), 'g2b1' => array('type' => 'box', 'options' => array('g3b1o1' => array('type' => 'text'), array('g3b1o2' => array('type' => 'text')))), array('g2b2' => array('type' => 'box', 'options' => array(array(array(array('g3b2o1' => array('type' => 'text'))))))))), 'o1' => array('type' => 'text'), array('o2' => array('type' => 'textarea')), array(array('o3' => array('type' => 'text')))); $result = array(); fw_collect_options($result, $options); $this->assertEquals(array('o1' => array('type' => 'text'), 'o2' => array('type' => 'textarea'), 'o3' => array('type' => 'text'), 'b1o1' => array('type' => 'text'), 'b1o2' => array('type' => 'textarea'), 't1o1' => array('type' => 'select'), 't1o2' => array('type' => 'radio'), 't2o1' => array('type' => 'text'), 't3o1' => array('type' => 'text'), 'g1o1' => array('type' => 'checkbox'), 'g1o2' => array('type' => 'checkboxes'), 'g2o1' => array('type' => 'checkbox'), 'g2o2' => array('type' => 'checkboxes'), 'g2o2' => array('type' => 'checkboxes'), 'g2o2' => array('type' => 'checkboxes'), 'g2o2' => array('type' => 'checkboxes'), 'g2o1' => array('type' => 'checkbox'), 'g3b1o1' => array('type' => 'text'), 'g3b1o2' => array('type' => 'text'), 'g3b2o1' => array('type' => 'text')), $result); unset($result); $result = array(); fw_collect_options($result, $options, array('limit' => 1)); $this->assertEquals(1, count($result)); unset($result); $result = array(); fw_collect_options($result, $options, array('limit' => 3)); $this->assertEquals(3, count($result)); unset($result); $result = array(); fw_collect_options($result, $options, array('limit_option_types' => array('text', 'textarea'))); $this->assertEquals(array('o1' => array('type' => 'text'), 'o2' => array('type' => 'textarea'), 'o3' => array('type' => 'text'), 'b1o1' => array('type' => 'text'), 'b1o2' => array('type' => 'textarea'), 't2o1' => array('type' => 'text'), 't3o1' => array('type' => 'text'), 'g3b1o1' => array('type' => 'text'), 'g3b1o2' => array('type' => 'text'), 'g3b2o1' => array('type' => 'text')), $result); unset($result); $result = array(); fw_collect_options($result, $options, array('limit_level' => 1)); $this->assertEquals(array('o1' => array('type' => 'text'), 'o2' => array('type' => 'textarea'), 'o3' => array('type' => 'text')), $result); unset($result); $result = array(); fw_collect_options($result, $options, array('limit_level' => 1, 'limit_option_types' => array('text'))); $this->assertEquals(array('o1' => array('type' => 'text'), 'o3' => array('type' => 'text')), $result); unset($result); $result = array(); fw_collect_options($result, $options, array('limit_level' => 1, 'limit_option_types' => array())); $this->assertEquals(array(), $result); unset($result); $result = array(); fw_collect_options($result, $options, array('limit_option_types' => array(), 'limit_container_types' => false)); $this->assertEquals(array('b1', 't1', 't2', 't3', 'g1', 'g2', 'g3', 'g2b1', 'g2b2'), array_keys($result)); unset($result); $result = array(); fw_collect_options($result, $options, array('limit_option_types' => array(), 'limit_container_types' => array('box', 'tab'))); $this->assertEquals(array('b1', 't1', 't2', 't3', 'g2b1', 'g2b2'), array_keys($result)); unset($result); $result = array(); fw_collect_options($result, $options, array('limit_option_types' => array(), 'limit_container_types' => false, 'limit_level' => 1)); $this->assertEquals(array('b1', 't1', 't2', 't3', 'g1', 'g2', 'g3'), array_keys($result)); unset($result); $result = array(); fw_collect_options($result, $options, array('limit_option_types' => array(), 'limit_container_types' => array('box'), 'limit_level' => 1)); $this->assertEquals(array('b1'), array_keys($result)); unset($result); }
/** * @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); } $box_options = array(); fw_collect_options($box_options, $option['box-options'], array('limit_option_types' => false, 'limit_container_types' => array('group'), 'limit_level' => 1)); $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)); }
/** * @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_options($collected, $options, array('limit_option_types' => false, 'limit_container_types' => false, 'limit_level' => 1, 'info_wrapper' => true)); if (empty($collected)) { return; } foreach ($collected as &$opt) { switch ($opt['group']) { case 'container': $_collected = array(); fw_collect_options($_collected, $opt['option']['options'], array('limit_option_types' => array(), 'limit_container_types' => false, 'limit_level' => 1, 'limit' => 1, 'info_wrapper' => false)); $has_containers = !empty($_collected); unset($_collected); $children_data = array('group' => 'container', 'id' => $opt['id']); $args = array('title' => empty($opt['option']['title']) ? fw_id_to_title($opt['id']) : $opt['option']['title'], 'description' => empty($opt['option']['desc']) ? '' : $opt['option']['desc']); if (isset($opt['option']['wp-customizer-args']) && is_array($opt['option']['wp-customizer-args'])) { $args = array_merge($opt['option']['wp-customizer-args'], $args); } if ($has_containers) { if ($parent_data) { trigger_error($opt['id'] . ' panel can\'t have a parent (' . $parent_data['id'] . ')', E_USER_WARNING); break; } $wp_customize->add_panel($opt['id'], $args); $children_data['customizer_type'] = 'panel'; } else { if ($parent_data) { if ($parent_data['customizer_type'] === 'panel') { $args['panel'] = $parent_data['id']; } else { trigger_error($opt['id'] . ' section can have only panel parent (' . $parent_data['id'] . ')', E_USER_WARNING); break; } } $wp_customize->add_section($opt['id'], $args); $children_data['customizer_type'] = 'section'; } $this->customizer_register_options($wp_customize, $opt['option']['options'], $children_data); unset($children_data); break; case 'option': $setting_id = FW_Option_Type::get_default_name_prefix() . '[' . $opt['id'] . ']'; $args = array('label' => empty($opt['option']['label']) ? fw_id_to_title($opt['id']) : $opt['option']['label'], 'description' => empty($opt['option']['desc']) ? '' : $opt['option']['desc'], 'settings' => $setting_id); if (isset($opt['option']['wp-customizer-args']) && is_array($opt['option']['wp-customizer-args'])) { $args = array_merge($opt['option']['wp-customizer-args'], $args); } if ($parent_data) { if ($parent_data['customizer_type'] === 'section') { $args['section'] = $parent_data['id']; } else { trigger_error('Invalid control parent: ' . $parent_data['customizer_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_Setting_Option')) { require_once fw_get_framework_directory('/includes/customizer/class--fw-customizer-setting-option.php'); } 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(new _FW_Customizer_Setting_Option($wp_customize, $setting_id, array('default' => fw()->backend->option_type($opt['option']['type'])->get_value_from_input($opt['option'], null), 'fw_option' => $opt['option']))); $wp_customize->add_control(new _FW_Customizer_Control_Option_Wrapper($wp_customize, $opt['id'], $args)); break; default: trigger_error('Unknown group: ' . $opt['group'], E_USER_WARNING); } } }
/** * @param array $result * @param array $options * @param array $settings * @param array $_recursion_data (private) for internal use */ function fw_collect_options(&$result, &$options, $settings = array(), $_recursion_data = array()) { static $default_settings = array('info_wrapper' => false, 'limit_level' => 0, 'limit_option_types' => false, 'limit_container_types' => array(), 'limit' => 0); static $access_key = null; if (is_null($access_key)) { $access_key = new FW_Access_Key('fw_collect_options'); } if (empty($options)) { return; } $settings = array_merge($default_settings, $settings); if (empty($_recursion_data)) { $_recursion_data = array('level' => 1, 'access_key' => $access_key); } elseif (!isset($_recursion_data['access_key']) || !$_recursion_data['access_key'] instanceof FW_Access_Key || !($_recursion_data['access_key']->get_key() === 'fw_collect_options')) { trigger_error('Call not allowed', E_USER_ERROR); } if ($settings['limit_level'] && $_recursion_data['level'] > $settings['limit_level']) { return; } foreach ($options as $option_id => &$option) { if (isset($option['options'])) { // this is a container do { if (is_array($settings['limit_container_types']) && !in_array($option['type'], $settings['limit_container_types'])) { break; } if ($settings['limit'] && count($result) >= $settings['limit']) { return; } if ($settings['info_wrapper']) { $result['container:' . $option_id] = array('group' => 'container', 'id' => $option_id, 'option' => &$option, 'level' => $_recursion_data['level']); } else { $result[$option_id] =& $option; } } while (false); fw_collect_options($result, $option['options'], $settings, array_merge($_recursion_data, array('level' => $_recursion_data['level'] + 1))); } 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_options($result, $option, $settings, $_recursion_data); } elseif (isset($option['type'])) { // option if (is_array($settings['limit_option_types']) && !in_array($option['type'], $settings['limit_option_types'])) { continue; } if ($settings['limit'] && count($result) >= $settings['limit']) { return; } if ($settings['info_wrapper']) { $result['option:' . $option_id] = array('group' => 'option', 'id' => $option_id, 'option' => &$option, 'level' => $_recursion_data['level']); } else { $result[$option_id] =& $option; } } else { trigger_error('Invalid option: ' . $option_id, E_USER_WARNING); } } }
/** * Make sure there are no duplicate ids * * @param array $value * @param array $option * * @return array */ public function _filter_addable_popup_value_from_input($value, $option) { $update_options = array(); fw_collect_options($update_options, $option['popup-options'], array('limit_option_types' => array($this->get_type()))); if (empty($update_options)) { return $value; } foreach ($value as &$row) { foreach ($update_options as $opt_id => $opt) { if (isset($row[$opt_id])) { // should not happen, but just in case, prevent notice $row[$opt_id] = fw()->backend->option_type($opt['type'])->get_value_from_input(array_merge($opt, array('value' => $row[$opt_id])), null); } } } return $value; }