/** * The run() method. * * This will initialize the plugin on the 'after_setup_theme' action. * * @internal * @since 0.5.0 * @param array $args array of class arguments (passed by the plugin utility class) */ protected function run() { FieldManager::init(); WidgetHandler::instance(); // use after_setup_theme action so it is initialized as soon as possible, but also so that both plugins and themes can use the action add_action('after_setup_theme', array($this, 'init'), 5); add_filter('wpwd_widget_validated', array($this, 'widget_validated'), 10, 2); add_filter('wpwd_section_validated', array($this, 'section_validated'), 10, 2); }
/** * The run() method. * * This will initialize the plugin on the 'after_setup_theme' action. * If we are currently in the WordPress admin area, the WPCD\Admin class will be instantiated. * * @since 0.5.0 */ protected function run() { FieldManager::init(); Customizer::instance(); AJAX::instance(); CSSGenerator::instance(); // use after_setup_theme action so it is initialized as soon as possible, but also so that both plugins and themes can use the action add_action('after_setup_theme', array($this, 'init'), 3); add_filter('wpcd_panel_validated', array($this, 'panel_validated'), 10, 2); add_filter('wpcd_section_validated', array($this, 'section_validated'), 10, 2); }
/** * Validates a value for the field. * * @since 0.5.0 * @param mixed $val the current value of the field * @return string|WP_Error the validated field value or an error object */ public function validate($val = null) { if (!$val) { return ''; } $input = sanitize_email($val); $val = is_email($input); if (!$val) { return new WPError('invalid_email', sprintf(__('%s is not a valid email address.', 'wpdlib'), \WPDLib\FieldTypes\Manager::format($input, 'string', 'output'))); } return $val; }
/** * Displays the input control for the field. * * @since 0.5.0 * @param string $val the current value of the field * @param bool $echo whether to echo the output (default is true) * @return string the HTML output of the field control */ public function display($val, $echo = true) { $args = $this->args; $args = array_merge($args, $this->data_atts); $output = '<textarea' . FieldManager::make_html_attributes($args, false, false) . '>'; $output .= esc_textarea($val); $output .= '</textarea>'; if ($echo) { echo $output; } return $output; }
/** * Displays the input control for the field. * * @since 0.5.0 * @param integer|float $val the current value of the field * @param bool $echo whether to echo the output (default is true) * @return string the HTML output of the field control */ public function display($val, $echo = true) { $args = $this->args; $args['value'] = $val; $args = array_merge($args, $this->data_atts); $text_args = array('id' => $args['id'] . '-' . $this->type . '-viewer', 'class' => 'wpdlib-input-' . $this->type . '-viewer', 'value' => $args['value'], 'min' => $args['min'], 'max' => $args['max'], 'step' => $args['step']); $output = '<input type="number"' . FieldManager::make_html_attributes($text_args, false, false) . ' />'; $output .= '<input type="' . $this->type . '"' . FieldManager::make_html_attributes($args, false, false) . ' />'; if ($echo) { echo $output; } return $output; }
/** * The run() method. * * This will initialize the plugin on the 'after_setup_theme' action. * * @internal * @since 0.5.0 * @param array $args array of class arguments (passed by the plugin utility class) */ protected function run() { FieldManager::init(); General::instance(); if (is_admin()) { Admin::instance(); } // use after_setup_theme action so it is initialized as soon as possible, but also so that both plugins and themes can use the action add_action('after_setup_theme', array($this, 'init'), 1); add_filter('wpdlib_menu_validated', array($this, 'menu_validated'), 10, 2); add_filter('wpod_screen_validated', array($this, 'screen_validated'), 10, 2); add_filter('wpod_tab_validated', array($this, 'tab_validated'), 10, 2); add_filter('wpod_section_validated', array($this, 'section_validated'), 10, 2); }
/** * Parses a value for the field. * * @since 0.5.0 * @param mixed $val the current value of the field * @param bool|array $formatted whether to also format the value (default is false) * @return string the correctly parsed value */ public function parse($val, $formatted = false) { if ($formatted) { if (!is_array($formatted)) { $formatted = array(); } $formatted = wp_parse_args($formatted, array('mode' => 'text')); switch ($formatted['mode']) { case 'link': return '<a href="' . esc_url($val) . '" target="_blank">' . esc_url($val) . '</a>'; case 'text': default: return FieldManager::format($val, 'url', 'output'); } } return FieldManager::format($val, 'url', 'input'); }
/** * Parses a value for the field. * * @since 0.5.0 * @param mixed $val the current value of the field * @param bool|array $formatted whether to also format the value (default is false) * @return string the correctly parsed value */ public function parse($val, $formatted = false) { if ($formatted) { $parsed = FieldManager::format($val, 'html', 'input'); if (!is_array($formatted)) { $formatted = array(); } $formatted = wp_parse_args($formatted, array('wpautop' => true, 'shortcode' => false)); if ($formatted['wpautop']) { $parsed = wpautop($parsed); } if ($formatted['shortcode']) { $parsed = do_shortcode($parsed); } return $parsed; } return FieldManager::format($val, 'html', 'input'); }
/** * Parses a value for the field. * * @since 0.5.0 * @param mixed $val the current value of the field * @param bool|array $formatted whether to also format the value (default is false) * @return integer|string the correctly parsed value (string if $formatted is true) */ public function parse($val, $formatted = false) { if ('url' === $this->args['store']) { $val = FieldManager::format($val, 'url', 'input'); } else { $val = absint($val); } if ($formatted) { if (!is_array($formatted)) { $formatted = array(); } $formatted = wp_parse_args($formatted, array('mode' => 'field', 'field' => 'url', 'template' => '')); $attachment_id = $val; if ('url' === $this->args['store']) { if ('field' === $formatted['mode'] && 'url' === $formatted['field']) { return $val; } $attachment_id = attachment_url_to_postid($val); } return $this->format_attachment($attachment_id, $formatted); } return $val; }
/** * Renders the term metabox. * * It displays the title and description (if available) for the metabox. * Then it shows the fields of this metabox or, if no fields are available, calls the callback function. * * @since 0.6.0 * @param WP_Term $term the term currently being shown */ public function render($term) { $parent_taxonomy = $this->get_parent(); if ('side' == $this->args['context']) { echo '<div class="wpdlib-narrow">'; } /** * This action can be used to display additional content on top of this term metabox. * * @since 0.6.0 * @param string the slug of the current metabox * @param array the arguments array for the current metabox * @param string the slug of the current taxonomy */ do_action('wpptd_term_metabox_before', $this->slug, $this->args, $parent_taxonomy->slug); if (!empty($this->args['description'])) { echo '<p class="description">' . $this->args['description'] . '</p>'; } if (count($this->get_children()) > 0) { $table_atts = array('class' => 'form-table wpdlib-form-table'); /** * This filter can be used to adjust the term editing form table attributes. * * @since 0.6.0 * @param array the associative array of form table attributes * @param WPPTD\Components\TermMetabox current metabox instance */ $table_atts = apply_filters('wpptd_term_table_atts', $table_atts, $this); echo '<table' . FieldManager::make_html_attributes($table_atts, false, false) . '>'; foreach ($this->get_children() as $field) { $field->render($term); } echo '</table>'; } elseif ($this->args['callback'] && is_callable($this->args['callback'])) { call_user_func($this->args['callback'], $term); } else { App::doing_it_wrong(__METHOD__, sprintf(__('There are no fields to display for metabox %s. Either add some or provide a valid callback function instead.', 'post-types-definitely'), $this->slug), '0.5.0'); } /** * This action can be used to display additional content at the bottom of this term metabox. * * @since 0.6.0 * @param string the slug of the current metabox * @param array the arguments array for the current metabox * @param string the slug of the current taxonomy */ do_action('wpptd_term_metabox_after', $this->slug, $this->args, $parent_taxonomy->slug); if ('side' == $this->args['context']) { echo '</div>'; } }
/** * Renders the sections of this tab. * * If the tab is set to be draggable, the function will run its metabox action. * Otherwise it will just manually output the sections. * * @since 0.5.0 */ protected function render_sections() { $form_atts = array('id' => $this->slug, 'action' => admin_url('options.php'), 'method' => 'post', 'novalidate' => true); /** * This filter can be used to adjust the form attributes. * * @since 0.5.0 * @param array the associative array of form attributes * @param WPOD\Components\Tab current tab instance */ $form_atts = apply_filters('wpod_form_atts', $form_atts, $this); echo '<form' . FieldManager::make_html_attributes($form_atts, false, false) . '>'; if ('draggable' == $this->args['mode']) { wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false); wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false); echo '<div class="metabox-holder">'; echo '<div class="postbox-container">'; do_meta_boxes($this->slug, 'normal', null); echo '</div>'; echo '</div>'; } else { foreach ($this->get_children() as $section) { $section->render(false); } } settings_fields($this->slug); submit_button(); echo '</form>'; }
/** * Parses a value for the field. * * @since 0.6.0 * @param mixed $val the current value of the field * @param bool|array $formatted whether to also format the value (default is false) * @return string the correctly parsed value */ public function parse($val, $formatted = false) { if ('coords' === $this->args['store']) { $val = explode('|', $val); if (2 !== count($val)) { return ''; } $mode = 'input'; if ($formatted) { $mode = 'output'; } for ($i = 0; $i < 2; $i++) { $val[$i] = FieldManager::format($val[$i], 'float', $mode, array('decimals' => 10)); } return $val[0] . '|' . $val[1]; } if ($formatted) { return FieldManager::format($val, 'string', 'output'); } return FieldManager::format($val, 'string', 'input'); }
/** * Parses a value for the field. * * @since 0.5.0 * @param mixed $val the current value of the field * @param bool|array $formatted whether to also format the value (default is false) * @return integer|float|string the correctly parsed value (string if $formatted is true) */ public function parse($val, $formatted = false) { $format = 'float'; if (is_int($this->args['step'])) { $format = 'int'; } if ($formatted) { return FieldManager::format($val, $format, 'output'); } return FieldManager::format($val, $format, 'input'); }
/** * Displays a single item in the select. * * @since 0.5.0 * @param string $value the value of the item * @param string|array $label the label of the item * @param string $id the overall field's ID attribute * @param string $name the overall field's name attribute * @param string|array $current the current value of the field * @param bool $echo whether to echo the output (default is true) * @return string the HTML output of the item */ protected function display_item($value, $label, $single_type, $id, $name, $current = '', $echo = true) { $option_atts = array('value' => $value, 'selected' => $this->is_value_checked_or_selected($current, $value)); if (is_array($label)) { if (isset($label['image'])) { $option_atts['data-image'] = esc_url($label['image']); } elseif (isset($label['color'])) { $option_atts['data-color'] = ltrim($label['color'], '#'); } if (isset($label['label'])) { $label = $label['label']; } else { $label = ''; } } $output = '<option' . FieldManager::make_html_attributes($option_atts, false, false) . '>' . esc_html($label) . '</option>'; if ($echo) { echo $output; } return $output; }
/** * Parses a value for the field. * * @since 0.5.0 * @param mixed $val the current value of the field * @param bool|array $formatted whether to also format the value (default is false) * @return string the correctly parsed value */ public function parse($val, $formatted = false) { if ($formatted) { return FieldManager::format($val, 'string', 'output'); } return FieldManager::format($val, 'string', 'input'); }
public function enqueue_control_assets() { $min = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min'; FieldManager::enqueue_assets($this->_fields_cache); wp_enqueue_script('wpcd-controls', App::get_url('assets/dist/js/controls' . $min . '.js'), array('wpdlib-fields', 'customize-controls'), App::get_info('version'), true); wp_enqueue_style('wpcd-controls', App::get_url('assets/dist/css/controls' . $min . '.css'), array('wpdlib-fields'), App::get_info('version')); }
/** * Parses a value for the field. * * @since 0.5.0 * @param mixed $val the current value of the field * @param bool|array $formatted whether to also format the value (default is false) * @return bool|string the correctly parsed value (a string if $formatted is true) */ public function parse($val, $formatted = false) { if ($formatted) { if (!is_array($formatted)) { $formatted = array(); } $formatted = wp_parse_args(array('mode' => 'text')); switch ($formatted['mode']) { case 'tick': if ($val) { return '✔'; } return ''; case 'text': default: return FieldManager::format($val, 'boolean', 'output'); } } return FieldManager::format($val, 'boolean', 'input'); }
/** * Renders the section. * * It displays the title and description (if available) for the section. * Then it shows the fields of this section or, if no fields are available, calls the callback function. * * @since 0.5.0 * @param boolean $metabox if this function is called inside a metabox, this parameter needs to be true, otherwise it has to be explicitly false */ public function render($metabox = true) { // only display the title if the section is not displayed as a metabox if (null !== $metabox || false === $metabox) { echo '<h3>' . $this->args['title'] . '</h3>'; } $parent_tab = $this->get_parent(); /** * This action can be used to display additional content on top of this section. * * @since 0.5.0 * @param string the slug of the current section * @param array the arguments array for the current section * @param string the slug of the current tab */ do_action('wpod_section_before', $this->slug, $this->args, $parent_tab->slug); if (!empty($this->args['description'])) { echo '<p class="description">' . $this->args['description'] . '</p>'; } if (count($this->get_children()) > 0) { $table_atts = array('class' => 'form-table wpdlib-form-table'); /** * This filter can be used to adjust the form table attributes. * * @since 0.5.0 * @param array the associative array of form table attributes * @param WPOD\Components\Section current section instance */ $table_atts = apply_filters('wpod_table_atts', $table_atts, $this); echo '<table' . FieldManager::make_html_attributes($table_atts, false, false) . '>'; do_settings_fields($parent_tab->slug, $this->slug); echo '</table>'; } elseif ($this->args['callback'] && is_callable($this->args['callback'])) { call_user_func($this->args['callback']); } else { App::doing_it_wrong(__METHOD__, sprintf(__('There are no fields to display for section %s. Either add some or provide a valid callback function instead.', 'options-definitely'), $this->slug), '0.5.0'); } /** * This action can be used to display additional content at the bottom of this section. * * @since 0.5.0 * @param string the slug of the current section * @param array the arguments array for the current section * @param string the slug of the current tab */ do_action('wpod_section_after', $this->slug, $this->args, $parent_tab->slug); }
/** * Validates the arguments array. * * @since 0.5.0 * @param WPWD\Components\Section $parent the parent component * @return bool|WPDLib\Util\Error an error object if an error occurred during validation, true if it was validated, false if it did not need to be validated */ public function validate($parent = null) { $status = parent::validate($parent); if ($status === true) { if (is_array($this->args['class'])) { $this->args['class'] = implode(' ', $this->args['class']); } if (!empty($this->args['class'])) { $this->args['class'] .= ' '; } $this->args['class'] .= 'widefat'; if (isset($this->args['options']) && !is_array($this->args['options'])) { $this->args['options'] = array(); } $this->_field = FieldManager::get_instance($this->args); if ($this->_field === null) { return new UtilError('no_valid_field_type', sprintf(__('The field type %1$s assigned to the field component %2$s is not a valid field type.', 'widgets-definitely'), $this->args['type'], $this->slug), '', ComponentManager::get_scope()); } if (null === $this->args['default']) { $this->args['default'] = $this->_field->validate(); } $this->args = Utility::validate_position_args($this->args); } return $status; }
/** * Validates the arguments array. * * @since 0.5.0 */ public function validate($parent = null) { $status = parent::validate($parent); if ($status === true) { if (null === $this->args['capability']) { $this->args['capability'] = $parent->capability; } if (isset($this->args['priority'])) { if (null === $this->args['position']) { $this->args['position'] = $this->args['priority']; } unset($this->args['priority']); } $this->args = Utility::validate_position_args($this->args); if (null === $this->args['mode']) { $this->args['mode'] = $parent->get_parent()->mode; } if (is_array($this->args['class'])) { $this->args['class'] = implode(' ', $this->args['class']); } if (isset($this->args['options']) && !is_array($this->args['options'])) { $this->args['options'] = array(); } if (in_array($this->args['type'], array('multiselect', 'multibox'), true)) { return new UtilError('multichoice_not_supported', sprintf(__('The multichoice field type assigned to the field component %s is not supported in the Customizer.', 'customizer-definitely'), $this->slug), '', ComponentManager::get_scope()); } if ('repeatable' == $this->args['type']) { return new UtilError('repeatable_not_supported', sprintf(__('The repeatable field type assigned to the field component %s is not supported in the Customizer.', 'customizer-definitely'), $this->slug), '', ComponentManager::get_scope()); } $this->_field = FieldManager::get_instance($this->args); if (null === $this->_field) { return new UtilError('no_valid_field_type', sprintf(__('The field type %1$s assigned to the field component %2$s is not a valid field type.', 'customizer-definitely'), $this->args['type'], $this->slug), '', ComponentManager::get_scope()); } if (null === $this->args['default']) { $this->args['default'] = $this->_field->validate(); } $this->args['preview_args'] = Customizer::instance()->validate_preview_args($this->args['preview_args'], $this->args['type'], $this->_field); if (null === $this->args['transport']) { if ($this->args['preview_args']['update_callback']) { $this->args['transport'] = 'postMessage'; } else { $this->args['transport'] = 'refresh'; } } } return $status; }
/** * Formats a single item for output. * * The argument passed as $val is the value of a specific field option. * * The 'mode' key in the $args array specifies in which format it should be returned: * - html (if option has an image, it will be printed inside an IMG tag; if it has a color, it will be printed as a div with that color as background) * - text (if option has an image, it will be printed as the plain URL; if it has a color, it will be printed as a hex color string) * * @since 0.5.0 * @param string|array $val the field option value to format * @param array $args arguments on how to format * @return string the correctly parsed value */ protected function format_item($val, $args = array()) { $skip_formatting = false; if (isset($this->args['options'][$val])) { if (is_array($this->args['options'][$val])) { if (isset($this->args['options'][$val]['label']) && !empty($this->args['options'][$val]['label'])) { $val = $this->args['options'][$val]['label']; } elseif (isset($this->args['options'][$val]['image'])) { if ('html' == $args['mode']) { $val = '<img src="' . esc_url($this->args['options'][$val]['image']) . '" style="display: inline-block;width:64px;height:auto;">'; $skip_formatting = true; } else { $val = esc_url($this->args['options'][$val]['image']); } } elseif (isset($this->args['options'][$val]['color'])) { if ('html' == $args['mode']) { $val = '<div style="display:inline-block;width:64px;height:48px;background-color:' . $this->args['options'][$val]['color'] . ';"></div>'; $skip_formatting = true; } else { $val = $this->args['options'][$val]['color']; } } } else { $val = $this->args['options'][$val]; } } if ($skip_formatting) { return $val; } return FieldManager::format($val, 'string', 'output'); }
/** * Enqueues all the assets needed on the term editing screen of the taxonomy. * * @since 0.6.0 * @see WPDLib\FieldTypes\Manager::enqueue_assets() */ public function enqueue_assets() { $_fields = array(); foreach ($this->get_children('WPPTD\\Components\\TermMetabox') as $metabox) { foreach ($metabox->get_children() as $field) { $_fields[] = $field->_field; } } FieldManager::enqueue_assets($_fields); }
/** * Displays a single group of fields. * * The function is also used to generate a dynamic template which is used in Javascript when appending new groups. * * @since 0.5.0 * @param integer $key the index of the group * @param array $values the values of the group as `$field_slug => $value` * @param bool $echo whether to echo the output (default is true) * @return string the HTML output of the group */ protected function display_item($key, $values = array(), $echo = true) { $output = '<tr class="wpdlib-repeatable-row">'; $output .= '<td class="wpdlib-repeatable-number">'; if ('{{' . 'KEY' . '}}' === $key) { $output .= '<span>' . sprintf(__('%s.', 'wpdlib'), '{{' . 'KEY_PLUSONE' . '}}') . '</span>'; } else { $key = absint($key); $output .= '<span>' . sprintf(__('%s.', 'wpdlib'), $key + 1) . '</span>'; } $output .= '</td>'; foreach ($this->args['repeatable']['fields'] as $slug => $args) { if (!isset($this->fields[$slug])) { continue; } $val = isset($values[$slug]) ? $values[$slug] : $this->fields[$slug]->validate(); $this->fields[$slug]->id = $this->args['id'] . '-' . $key . '-' . $slug; $this->fields[$slug]->name = $this->args['name'] . '[' . $key . '][' . $slug . ']'; $output .= '<td class="wpdlib-repeatable-col wpdlib-repeatable-' . $this->args['id'] . '-' . $slug . '">'; $output .= $this->fields[$slug]->display($val, false); $output .= '</td>'; } $button_args = array('class' => 'wpdlib-remove-repeatable-button', 'href' => '#', 'data-number' => $key); $output .= '<td class="wpdlib-repeatable-remove">'; $output .= '<a' . FieldManager::make_html_attributes($button_args, false, false) . '>' . __('Remove', 'wpdlib') . '</a>'; $output .= '</td>'; $output .= '</tr>'; if ($echo) { echo $output; } return $output; }
/** * Formats a timestamp into a date format string ready for saving to the database. * * @since 0.5.0 * @param integer $val the timestamp to format * @return string|null the date format string or null if formatting not possible */ protected function format_timestamp($val) { return $val !== null ? FieldManager::format($val, $this->type, 'input') : null; }
/** * Parses a value for the field. * * @since 0.5.0 * @param mixed $val the current value of the field * @param bool|array $formatted whether to also format the value (default is false) * @return string the correctly parsed value */ public function parse($val, $formatted = false) { if (!$val) { return ''; } if ($formatted) { if (!is_array($formatted)) { $formatted = array(); } $formatted = wp_parse_args(array('mode' => 'text')); switch ($formatted['mode']) { case 'color': return '<div style="display:inline-block;width:64px;height:48px;background-color:' . $val . ';"></div>'; case 'color-text': return '<div style="display:inline-block;padding:5px 10px;background-color:' . $val . ';">' . FieldManager::format($val, 'string', 'output') . '</div>'; case 'text': default: return FieldManager::format($val, 'string', 'output'); } } return FieldManager::format($val, 'string', 'input'); }