/**
  * Display or return HTML-formatted portfolio items.
  *
  * @since  1.0.0
  * @param  string|array $args Arguments.
  * @return string
  */
 public function the_portfolio($options = '')
 {
     /**
      * Filter the array of default options.
      *
      * @since 1.0.0
      * @param array options.
      * @param array The 'the_portfolio_items' function argument.
      */
     $default_options = apply_filters('cherry_the_portfolio_default_options', self::$default_options);
     // default options marge
     self::$options = wp_parse_args($options, $default_options);
     $output = '';
     // The Query.
     $posts_query = $this->get_query_portfolio_items(self::$options);
     // The Display.
     if (!is_wp_error($posts_query)) {
         $css_class = '';
         if (!empty(self::$options['wrap_class'])) {
             $css_class .= sanitize_html_class(self::$options['wrap_class']) . ' ';
         }
         if (!empty(self::$options['custom_class'])) {
             $css_class .= sanitize_html_class(self::$options['custom_class']);
         }
         // Open wrapper.
         $output .= sprintf('<div class="%s">', trim($css_class));
         if (!empty(self::$options['title'])) {
             $output .= self::$options['before_title'] . __(esc_html(self::$options['title']), 'cherry-portfolio') . self::$options['after_title'];
         }
         if (self::$options['filter_visible'] == 'true' && $posts_query->have_posts()) {
             $output .= $this->build_ajax_filter(self::$options['filter_type']);
         }
         switch (self::$options['loading_mode']) {
             case 'portfolio-ajax-pagination-mode':
                 $loading_mode = 'ajax-pagination';
                 break;
             case 'portfolio-more-button-mode':
                 $loading_mode = 'more-button';
                 break;
         }
         $container_attr = '';
         $container_attr .= 'data-post-per-page="' . self::$options['posts_per_page'] . '"';
         $container_attr .= 'data-column="' . self::$options['grid_col'] . '"';
         $container_attr .= 'data-list-layout="' . self::$options['listing_layout'] . '"';
         $container_attr .= 'data-loading-mode="' . $loading_mode . '"';
         $container_attr .= 'data-item-margin="' . self::$options['item_margin'] . '"';
         $container_attr .= 'data-fixed-height="' . self::$options['fixed_height'] . '"';
         $container_attr .= 'data-template="' . self::$options['template'] . '"';
         $container_attr .= 'data-posts-format="' . self::$options['posts_format'] . '"';
         $output .= '<div class="portfolio-container ' . self::$options['listing_layout'] . ' ' . self::$options['loading_animation'] . '" ' . $container_attr . '>';
         $output .= '<div class="portfolio-list"  data-all-posts-count="' . $this->posts_query->found_posts . '">';
         $output .= '</div>';
         $output .= '</div>';
         // Close wrapper.
         $output .= '</div>';
     }
     /**
      * Filters HTML-formatted portfolio items before display or return.
      *
      * @since 1.0.0
      * @param string $output The HTML-formatted portfolio items.
      * @param array  $query  List of WP_Post objects.
      * @param array  $args   The array of arguments.
      */
     $output = apply_filters('cherry_portfolio_html', $output, $posts_query, $options);
     if (self::$options['echo'] != true) {
         return $output;
     }
     // If "echo" is set to true.
     echo $output;
     /**
      * Fires after the portfolio.
      *
      * This hook fires only when "echo" is set to true.
      *
      * @since 1.0.0
      * @param array $array The array of arguments.
      */
     do_action('cherry_portfolio_after', $options);
 }