['label' => __('Title', 'italystrap'), 'desc' => __('Enter the widget title.', 'italystrap'), 'id' => 'title', 'type' => 'text', 'class' => 'widefat', 'default' => '', 'validate' => 'alpha_dash', 'sanitize' => 'strip_tags|esc_attr']]; } /** * Get the fields for widget * * @param array $fields The options array with new fields. * @return array Return an array with all fields */ protected function get_widget_fields(array $fields = []) { if (empty($fields)) { return $this->title_field(); } return array_merge($this->title_field(), $fields); } /** * Echoes the widget content. * * Sub-classes should over-ride this function to generate their widget code. * * @since 2.8.0 * @access public * * @param array $args Display arguments including 'before_title', 'after_title', * 'before_widget', and 'after_widget'. * @param array $instance The settings for the particular instance of the widget. */ public function widget($args, $instance) { if ($this->get_cached_widget()) { return; } $output = ''; $output .= $args['before_widget']; /** * Print the optional widget title */ $output .= $this->widget_title($args, $instance); /** * Modify this for outputting the HTML */ $output .= $this->widget_render($args, $instance); $output .= $args['after_widget']; echo apply_filters('widget_text', $this->cache_widget($args, $output)); // XSS ok. } /** * Dispay the widget content * * @since 2.0.0 * @access public * * @param array $args Display arguments including 'before_title', 'after_title', * 'before_widget', and 'after_widget'. * @param array $instance The settings for the particular instance of the widget. */ abstract public function widget_render($args, $instance); /** * Dispay the optional title * * @since 2.0.0 * @access public * * @param array $args Display arguments including 'before_title', 'after_title', * 'before_widget', and 'after_widget'. * @param array $instance The settings for the particular instance of the widget. * @return string Return the optional title */ protected function widget_title($args, $instance) { $output = ''; /** * This filter is documented in wp-includes/widgets/class-wp-widget-pages.php * * @var string */ $title = apply_filters( 'widget_title', empty($instance['title']) ? '' : $instance['title'], $instance, $this->id_base ); /** * Return the optional widget title with before_title and after_title */ if (! $title) { return $title; } $output .= $args['before_title']; if (! empty($this->args['title_link'])) { $output .= '' . $title . ''; } else { $output .= $title; } $output .= $args['after_title']; return $output; } /** * Create Widget and call PHP5 constructor. * Creates a new widget and sets it's labels, description, fields and options. * * @access public * @param array $args The array with widget configuration. */ protected function create_widget(array $args) { /** * Settings some defaults options. * * New feauture added from WP 4.5 to add selective refresh on widget, see the link fro more information. * * @see https://make.wordpress.org/core/2016/03/22/implementing-selective-refresh-support-for-widgets/ * * @var array */ $defaults = ['label' => '', 'description' => __('⇒ Add a $args[\'description\'] to your widget', 'italystrap'), 'fields' => [], 'widget_options' => [], 'control_options' => []]; /** * Parse and merge args with defaults. * * @var array */ $args = wp_parse_args((array) $args, (array) $defaults); $args['fields'] = $this->get_widget_fields((array) $args['fields']); $this->is_valid_args($args); /** * Convert $args['label'] spaces with dash '-'. */ $id_base = sanitize_title($args['label']); $name = $args['label']; /** * Set the default widget title */ $args['fields']['title']['default'] = $name; /** * Check options. * * @var array */ $widget_options = ['description' => $args['description']]; $widget_options = wp_parse_args((array) $args['widget_options'], (array) $widget_options); /** * The options contains the height, width, and id_base keys. * The height option is never used. * The width option is the width of the fully expanded control form, * but try hard to use the default width. * The id_base is for multi-widgets (widgets which allow multiple instances * such as the text widget), an id_base must be provided. * The widget id will end up looking like {$id_base}-{$unique_number}. * The id_base is optional. See wp_register_widget_control() * https://codex.wordpress.org/Function_Reference/wp_register_widget_control * * Example: array( 'width' => 450 ); * * @var array */ $control_options = $args['control_options']; /** * With this filter you can change the default widget fields * * @var array */ $this->fields = apply_filters('italystrap_widget_fields', $args['fields'], $id_base); /** * Call WP_Widget to create the widget. * * @since 2.8.0 * @access public * * @param string $id_base Optional Base ID for the widget, lowercase and unique. * If left empty, a portion of the widget's class name * will be used Has to be unique. * @param string $name Name for the widget displayed on the configuration page. * @param array $widget_options Optional. Widget options. * See wp_register_sidebar_widget() for information * on accepted arguments. Default empty array. * @param array $control_options Optional. Widget control options. * See wp_register_widget_control() for * information on accepted arguments. Default empty array. */ parent::__construct($id_base, $name, $widget_options, $control_options); $this->init_events(); } /** * Init events. */ protected function init_events() { add_action('save_post', [$this, 'flush_widget_cache']); add_action('deleted_post', [$this, 'flush_widget_cache']); add_action('switch_theme', [$this, 'flush_widget_cache']); } /** * Check if it is valid args before init. * * @param array $args The widget arguments. */ protected function is_valid_args(array $args) { if (empty($args['label']) || ! is_string($args['label'])) { throw new InvalidArgumentException('The $args[\'label\'] must be not empty. Insert the widget title.'); } if (! is_string($args['label'])) { throw new InvalidArgumentException('The $args[\'label\'] must be a string.'); } if (empty($args['fields'])) { throw new InvalidArgumentException('The $args[\'fields\'] must be not empty.'); } } /** * Outputs the settings update form. * * @access public * * @param array $instance Current settings. */ public function form($instance) { $this->instance = $instance; $this->fields_type = new Fields(); /** * Creates the settings form. * * @var string */ $form = $this->render_form(); echo $form; // WPCS: XSS OK. } /** * @TODO Maybe use it for registering stuff */ public function _register() { // $this->init_events(); parent::_register(); } /** * Updates a particular instance of a widget. * * This function should check that `$new_instance` is set correctly. The newly-calculated * value of `$instance` should be returned. If false is returned, the instance won't be * saved/updated. * * @access public * * @param array $new_instance New settings for this instance * as input by the user via WP_Widget::form(). * @param array $old_instance Old settings for this instance. * @return array Settings to save or bool false to cancel saving. */ public function update($new_instance, $old_instance) { $instance = $new_instance; $this->before_update_fields(); $this->validation = new Validation(); $this->sanitization = new Sanitization(); $this->translator = new Translator('ItalyStrap'); foreach ($this->fields as $field) { if (! isset($instance[ $field['id'] ])) { $instance[ $field['id'] ] = ''; } /** * Register string for translation */ if (isset($field['translate']) && true === $field['translate']) { $this->translator->registerString($field['id'], strip_tags($instance[ $field['id'] ])); } /** * Validate fields if $field['validate'] is set */ if (isset($field['validate'])) { if (false === $this->validation->validate($field['validate'], $instance[ $field['id'] ])) { $instance[ $field['id'] ] = ''; } } if (isset($field['capability']) && true === $field['capability']) { $instance[ $field['id'] ] = $instance[ $field['id'] ]; } elseif (isset($field['sanitize'])) { $instance[ $field['id'] ] = $this->sanitization->sanitize($field['sanitize'], $instance[ $field['id'] ]); } else { $instance[ $field['id'] ] = strip_tags($instance[ $field['id'] ]); } } $this->flush_widget_cache(); $alloptions = wp_cache_get('alloptions', 'options'); if (isset($alloptions[ $this->id ])) { delete_option($this->id); } return $this->after_validate_fields($instance); } /** * Fire Before Validate Fields * * Allows to hook code on the update. * * @access public */ protected function before_update_fields() { return; } /** * Fire After Validate Fields * * Allows to modify the output after validating the fields. * * @access public * @param array $instance The $instance of widget. * @return array Return the $instance of widget */ protected function after_validate_fields($instance) { return $instance; } /** * Create the section array for tab in widget panel * * @param array $fields The fields array. * @return array Return the array for section */ private function make_sections_array(array $fields) { $sections = []; foreach ((array) $fields as $key) { if (isset($key['section']) && 'general' !== $key['section']) { $sections[ $key['section'] ][ $key['id'] ] = (array) $key; } else { $sections['general'][ $key['id'] ] = (array) $key; } } return $sections; } /** * Get the sections array key * * @param array $sections The sections array. * @return array Return an array with sections key */ private function get_sections_keys(array $sections) { return array_keys($sections); } /** * Create the sections tabs menu in widget panel * * @param array $sections The sections array. * @return string Return the HTML for tabs menu in widget panel */ protected function create_sections_tabs_menu(array $sections) { $tabs = '