/**
  * 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 array $widget_options the widget options with their current values
  * @param WPWD\Components\Widget|null $parent_widget the parent widget component of this section or null
  */
 public function render($widget_options, $parent_widget = null)
 {
     if (null === $parent_widget) {
         $parent_widget = $this->get_parent();
     }
     echo '<h3>' . $this->args['title'] . '</h3>';
     /**
      * 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 widget
      */
     do_action('wpwd_section_before', $this->slug, $this->args, $parent_widget->slug);
     if (!empty($this->args['description'])) {
         echo '<p class="description">' . $this->args['description'] . '</p>';
     }
     if (count($children = $this->get_children()) > 0) {
         foreach ($children as $field) {
             $field->render($widget_options[$field->slug], $parent_widget, $this);
         }
     } 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.', 'widgets-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 widget
      */
     do_action('wpwd_section_after', $this->slug, $this->args, $parent_widget->slug);
 }
 protected function get_template_part($args, $instance)
 {
     $sidebar_slug = $args['id'];
     do_action('get_template_part_' . $this->slug, $this->slug, $sidebar_slug);
     $template_names = array($this->slug . '-' . $sidebar_slug . '.php', $this->slug . '.php');
     $template_paths = Utility::get_template_paths();
     $located = false;
     foreach ($template_names as $template_name) {
         foreach ($template_paths as $template_path) {
             if (file_exists($template_path . $template_name)) {
                 $located = $template_path . $template_name;
                 break;
             }
         }
         if ($located) {
             break;
         }
     }
     if ($located) {
         $this->load_template_file($located, $instance);
     } elseif ($this->args['template_file'] && file_exists($this->args['template_file'])) {
         $this->load_template_file($this->args['template_file'], $instance);
     } elseif ($this->args['template_callback'] && is_callable($this->args['template_callback'])) {
         $this->load_template_callback($this->args['template_callback'], $instance);
     } else {
         App::doing_it_wrong(__METHOD__, sprintf(__('The widget %s is missing a valid template file or callback. You must provide either a template file or a callback function for it.', 'widgets-definitely'), $this->slug), '0.5.0');
     }
 }
 /**
  * Renders the widget form.
  *
  * It iterates through all the sections belonging to this widget and calls each one's `render()` function.
  *
  * If no sections are available for this widget, the function will try to call the widget callback function to generate the output.
  *
  * @since 0.5.0
  * @param array $widget_options the widget's widget options with their current values
  */
 public function render_form($widget_options)
 {
     //TODO: of course the following does not work; create manual errors here
     settings_errors($this->slug);
     /**
      * This action can be used to display additional content on top of this widget form.
      *
      * @since 0.5.0
      * @param string the slug of the current widget
      * @param array the arguments array for the current widget
      */
     do_action('wpwd_widget_form_before', $this->slug, $this->args);
     if (count($children = $this->get_children()) > 0) {
         foreach ($children as $section) {
             echo '<div class="wpwd-form-section">';
             $section->render($widget_options, $this);
             echo '</div>';
         }
     } elseif ($this->args['form_callback'] && is_callable($this->args['form_callback'])) {
         call_user_func($this->args['form_callback']);
     } else {
         App::doing_it_wrong(__METHOD__, sprintf(__('There are no sections to display for widget %s. Either add some or provide a valid callback function instead.', 'widgets-definitely'), $this->slug), '0.5.0');
     }
     /**
      * This action can be used to display additional content at the bottom of this widget form.
      *
      * @since 0.5.0
      * @param string the slug of the current widget
      * @param array the arguments array for the current widget
      */
     do_action('wpwd_widget_form_after', $this->slug, $this->args);
 }