static function get($a)
 {
     $d = new self();
     $d->setCallback('line', array(__CLASS__, 'stackLine'));
     $d->walk($a);
     $d = implode("\n", self::$lines);
     self::$lines = array();
     return $d;
 }
 /**
  * Render an checklist of terms.
  *
  * This is the Connections equivalent of @see wp_terms_checklist() in WordPress core ..wp-admin/wp-includes/template.php
  *
  * @access public
  * @since  8.2
  * @static
  *
  * @param array $atts {
  *     Optional. An array of arguments.
  *     NOTE: Additionally, all valid options as supported in @see cnTerm::getTaxonomyTerms().
  *
  * @type bool   $show_count        Whether or not to display the category count.
  *                                 Default: FALSE
  * @type string $name              The select name attribute.
  *                                 Default: 'cat'
  * @type int    $depth             Controls how many levels in the hierarchy of categories are to be included in the list.
  *                                 Default: 0
  *                                 Accepts: 0  - All categories and child categories.
  *                                          -1 - All Categories displayed  flat, not showing the parent/child relationships.
  *                                          1  - Show only top level/root parent categories.
  *                                          n  - Value of n (int) specifies the depth (or level) to descend in displaying the categories.
  * @type string $taxonomy          The taxonomy tree to display.
  *                                 Default: 'category'
  *                                 Accepts: Any registered taxonomy.
  * @type mixed  $selected          The selected term ID(s) the term ID or array of term ID/s that are selected.
  *                                 Default: 0
  * @type bool   $return            Whether or not to return or echo the resulting HTML.
  *                                 Default: FALSE
  * }
  *
  * @return string
  */
 public static function render($atts = array())
 {
     $out = '';
     $defaults = array('orderby' => 'name', 'order' => 'ASC', 'show_count' => FALSE, 'hide_empty' => FALSE, 'name' => 'entry_category', 'depth' => 0, 'taxonomy' => 'category', 'selected' => 0, 'return' => FALSE);
     $atts = wp_parse_args($atts, $defaults);
     if (!is_array($atts['selected'])) {
         $atts['selected'] = array(absint($atts['selected']));
     } else {
         array_walk($atts['selected'], 'absint');
     }
     $walker = new self();
     $walker->tree_type = $atts['taxonomy'];
     // Reset the name attribute so the results from cnTerm::getTaxonomyTerms() are not limited by the select attribute name.
     $terms = cnTerm::getTaxonomyTerms($atts['taxonomy'], array_merge($atts, array('name' => '')));
     if (!empty($terms)) {
         $out .= '<ul id="' . esc_attr($atts['taxonomy']) . 'checklist" class="' . esc_attr($walker->tree_type) . 'checklist form-no-clear">';
         $out .= $walker->walk($terms, $atts['depth'], $atts);
         $out .= '</ul>';
     }
     if ($atts['return']) {
         return $out;
     }
     echo $out;
 }
 /**
  * Display or retrieve the HTML select list of terms.
  *
  * This is the Connections equivalent of @see wp_dropdown_categories() in WordPress core ../wp-includes/category-template.php
  *
  * @access public
  * @since  8.2.4
  * @static
  *
  * @uses   wp_parse_args()
  * @uses   cnTerm::getTaxonomyTerms()
  * @uses   esc_attr()
  * @uses   sanitize_html_class()
  * @uses   apply_filters()
  * @uses   Walker::walk()
  * @uses   selected()
  *
  * @param array $atts {
  *     Optional. An array of arguments.
  *     NOTE: Additionally, all valid options as supported in @see cnTerm::getTaxonomyTerms().
  *
  * @type string $taxonomy          The taxonomy tree to display.
  *                                 Default: 'category'
  * @type bool   $hierarchical      Whether to include terms that have non-empty descendants, even if 'hide_empty' is set to TRUE.
  *                                 Default: TRUE
  * @type string $type              The output type of the categories.
  *                                 Default: select
  *                                 Accepts: select || multiselect
  * @type bool   $group             Whether or not to create option groups using the root parent as the group label.
  *                                 Default: FALSE
  * @type bool   $hide_if_empty     Whether or not to show the select if no terms are returned by term query.
  *                                 Default: FALSE
  * @type string $name              The select name attribute.
  *                                 Default: 'cn-cat'
  * @type string $id                The select id attribute.
  *                                 Default: ''
  * @type array  $class             An array if classes to applied to the select.
  *                                 Default: array('cn-category-select')
  * @type array  $style             An array of style to applied inline where the key is the style attribute and the value is the style attribute value.
  *                                 Default: array()
  * @type bool   $enhanced          Whether of not apply the required attributes for the Chosen jQuery plugin.
  *                                 Default: TRUE
  * @type string $on_change         An inline JavaScript on_change event.
  *                                 Default: ''
  *                                 Accepts: Any valid inline JavaScript.
  * @type int    $tab_index         The tab index of the select.
  *                                 Default: 0
  * @type bool   $show_select_all   Whether or not to render the $show_option_all option.
  *                                 Default: TRUE
  * @type string $show_option_all   A non-blank value causes the display of a link to the directory home page.
  *                                 Default: ''. The default is not to display a link.
  *                                 Accepts: Any valid string.
  * @type string $show_option_none  Set the text to show when no categories are listed.
  *                                 Default: 'No Categories'
  *                                 Accepts: Any valid string.
  * @type string $option_none_value Value to use when no term is selected.
  *                                 Default: -1
  *                                 Accepts: Any valid int/string for an option value attribute.
  * @type string $default           The default string to show as the first item in the list.
  *                                 Default: 'Select Category'
  * @type bool   $show_count        Whether or not to display the category count.
  *                                 Default: FALSE
  * @type bool   $hide_empty        Whether or not to display empty terms.
  *                                 Default: FALSE
  * @type int    $depth             Controls how many levels in the hierarchy of categories are to be included in the list.
  *                                 Default: 0
  *                                 Accepts: 0  - All categories and child categories.
  *                                          -1 - All Categories displayed  flat, not showing the parent/child relationships.
  *                                          1  - Show only top level/root parent categories.
  *                                          n  - Value of n (int) specifies the depth (or level) to descend in displaying the categories.
  * @type array  $parent_id
  * @type array  $selected          The selected term IDs.
  *                                 Default: 0
  * @type string $label             The label to render with the select.
  *                                 Default: ''
  * @type string $before            Content to be render before the label and select.
  *                                 Default: ''
  * @type string $after             Content to be render after the label and select.
  *                                 Default: ''
  * @type string $layout            Tokens which can be sued to control the order of the label and select.
  *                                 Default: '%label%%field%'
  *                                 Accepts: %label% %field%
  * @type bool   $return            Whether or not to return or echo the resulting HTML.
  *                                 Default: FALSE
  * }
  *
  * @return string
  */
 public static function render($atts = array())
 {
     $select = '';
     $out = '';
     $defaults = array('taxonomy' => 'category', 'hierarchical' => TRUE, 'type' => 'select', 'group' => FALSE, 'hide_if_empty' => FALSE, 'name' => 'cn-cat', 'id' => '', 'class' => array('cn-category-select'), 'style' => array(), 'enhanced' => TRUE, 'on_change' => '', 'tab_index' => 0, 'show_select_all' => TRUE, 'show_option_all' => '', 'show_option_none' => '', 'option_none_value' => -1, 'default' => __('Select Category', 'connections'), 'show_count' => FALSE, 'hide_empty' => FALSE, 'depth' => 0, 'parent_id' => array(), 'selected' => 0, 'label' => '', 'before' => '', 'after' => '', 'layout' => '%label%%field%', 'return' => FALSE);
     $atts = wp_parse_args($atts, $defaults);
     if (wp_is_mobile()) {
         $atts['enhanced'] = FALSE;
     }
     // The field parts to be searched for in $atts['layout'].
     $search = array('%label%', '%field%');
     // An array to store the replacement strings for the label and field.
     $replace = array();
     $walker = new self();
     $walker->tree_type = $atts['taxonomy'];
     if (!isset($atts['pad_counts']) && $atts['show_count'] && $atts['hierarchical']) {
         // Padding the counts is ideal, but really, really, bloats the memory required.
         $atts['pad_counts'] = FALSE;
     }
     if (empty($atts['parent_id'])) {
         $terms = cnTerm::getTaxonomyTerms($atts['taxonomy'], $atts);
     } else {
         $atts['parent_id'] = wp_parse_id_list($atts['parent_id']);
         $terms = cnTerm::getTaxonomyTerms($atts['taxonomy'], array_merge($atts, array('include' => $atts['parent_id'], 'child_of' => 0)));
         // If any of the `parent_id` is not a root parent (where $term->parent = 0) set it parent ID to `0`
         // so the term tree will be properly constructed.
         foreach ($terms as $term) {
             if (0 !== $term->parent) {
                 $term->parent = 0;
             }
         }
         foreach ($atts['parent_id'] as $termID) {
             $children = cnTerm::getTaxonomyTerms($atts['taxonomy'], array_merge($atts, array('child_of' => $termID)));
             if (!is_wp_error($children)) {
                 $terms = array_merge($terms, $children);
             }
         }
     }
     if (!$atts['hide_if_empty'] || !empty($terms)) {
         //$out .= PHP_EOL . "<select name='$name' id='$id' class='$class' $tab_index_attribute>" . PHP_EOL;
         // Add the 'cn-enhanced-select' class for the jQuery Chosen Plugin will enhance the drop down.
         if ($atts['enhanced']) {
             $atts['class'] = array_merge((array) $atts['class'], array('cn-enhanced-select'));
         }
         // Create the field label, if supplied.
         $replace[] = !empty($atts['label']) ? cnHTML::label(array('for' => $atts['id'], 'label' => $atts['label'], 'return' => TRUE)) : '';
         $select .= sprintf('<select %1$s %2$s name="%3$s"%4$s%5$sdata-placeholder="%6$s"%7$s%8$s>' . PHP_EOL, empty($atts['class']) ? '' : cnHTML::attribute('class', $atts['class']), empty($atts['id']) ? '' : cnHTML::attribute('id', $atts['id']), $atts['type'] == 'multiselect' ? esc_attr($atts['name']) . '[]' : esc_attr($atts['name']), empty($atts['style']) ? '' : cnHTML::attribute('style', $atts['style']), $atts['type'] == 'multiselect' ? '' : (empty($atts['on_change']) ? '' : sprintf(' onchange="%s" ', esc_js($atts['on_change']))), esc_attr($atts['default']), $atts['type'] == 'multiselect' ? ' MULTIPLE' : '', (int) $atts['tab_index'] > 0 ? " tabindex=\"{$atts['tab_index']}\"" : '');
     } else {
         $select .= '';
     }
     if (empty($terms) && !$atts['hide_if_empty'] && !empty($atts['show_option_none'])) {
         /** This filter is documented in includes/template/class.template-walker-term-select.php */
         $show_option_none = apply_filters('cn_list_cats', $atts['show_option_none']);
         $select .= "\t<option value='" . esc_attr($atts['option_none_value']) . "' selected='selected'>{$show_option_none}</option>" . PHP_EOL;
     }
     if (!empty($terms)) {
         if ($atts['enhanced']) {
             $select .= "\t" . '<option value=""></option>';
         }
         if ($atts['show_select_all'] && $atts['show_option_all']) {
             /** This filter is documented in includes/template/class.template-walker-term-select.php */
             $show_option_all = apply_filters('cn_list_cats', $atts['show_option_all']);
             $selected = !$atts['enhanced'] && is_numeric($atts['selected']) && '0' === strval($atts['selected']) ? " selected='selected'" : '';
             $select .= "\t<option value='0'{$selected}>{$show_option_all}</option>" . PHP_EOL;
         }
         if ($atts['show_option_none']) {
             /** This filter is documented in includes/template/class.template-walker-term-select.php */
             $show_option_none = apply_filters('cn_list_cats', $atts['show_option_none']);
             $selected = selected($atts['option_none_value'], $atts['selected'], FALSE);
             $select .= "\t<option value='" . esc_attr($atts['option_none_value']) . "'{$selected}>{$show_option_none}</option>" . PHP_EOL;
         }
         if ($atts['hierarchical']) {
             $depth = $atts['depth'];
             // Walk the full depth.
         } else {
             $depth = -1;
             // Flat.
         }
         $select .= $walker->walk($terms, $depth, $atts);
     }
     if (!$atts['hide_if_empty'] || !empty($terms)) {
         // If an option group was left open, ensure it is closed before closing the select.
         if ($walker->close_group) {
             $select .= "\t" . '</optgroup>' . PHP_EOL;
             $walker->close_group = FALSE;
         }
         $select .= "</select>" . PHP_EOL;
         $replace[] = $select;
         $out = str_ireplace($search, $replace, $atts['layout']);
         $out = (empty($atts['before']) ? '' : $atts['before']) . $out . (empty($atts['after']) ? '' : $atts['after']);
     }
     /**
      * Filter the taxonomy drop-down output.
      *
      * @since 8.2.4
      *
      * @param string $out  HTML output.
      * @param array  $atts Arguments used to build the drop-down.
      */
     $out = apply_filters('cn_dropdown_cats', $out, $atts);
     if ($atts['return']) {
         return $out;
     }
     echo $out;
 }
 /**
  * Render an unordered list of categories.
  *
  * This is the Connections equivalent of @see wp_list_categories() in WordPress core ../wp-includes/category-template.php
  *
  * @access public
  * @since  8.1.6
  * @static
  *
  * @uses   wp_parse_args()
  * @uses   cnTerm::getTaxonomyTerms()
  * @uses   cnURL::permalink()
  * @uses   Walker::walk()
  *
  * @param array $atts {
  *     Optional. An array of arguments.
  *     NOTE: Additionally, all valid options as supported in @see cnTerm::getTaxonomyTerms().
  *
  * @type string $show_option_all  A non-blank value causes the display of a link to the directory home page.
  *                                Default: ''. The default is not to display a link.
  *                                Accepts: Any valid string.
  * @type string $show_option_none Set the text to show when no categories are listed.
  *                                Default: 'No Categories'
  *                                Accepts: Any valid string.
  * @type bool   $show_count       Whether or not to display the category count.
  *                                Default: FALSE
  * @type int    $depth            Controls how many levels in the hierarchy of categories are to be included in the list.
  *                                Default: 0
  *                                Accepts: 0  - All categories and child categories.
  *                                         -1 - All Categories displayed  flat, not showing the parent/child relationships.
  *                                         1  - Show only top level/root parent categories.
  *                                         n  - Value of n (int) specifies the depth (or level) to descend in displaying the categories.
  * @type string $taxonomy         The taxonomy tree to display.
  *                                Default: 'category'
  *                                Accepts: Any registered taxonomy.
  * @type bool   $return           Whether or not to return or echo the resulting HTML.
  *                                Default: FALSE
  * }
  *
  * @return string
  */
 public static function render($atts = array())
 {
     $out = '';
     $defaults = array('show_option_all' => '', 'show_option_none' => __('No categories', 'connections'), 'orderby' => 'name', 'order' => 'ASC', 'show_count' => FALSE, 'hide_empty' => FALSE, 'child_of' => 0, 'exclude' => array(), 'hierarchical' => TRUE, 'depth' => 0, 'parent_id' => array(), 'taxonomy' => 'category', 'force_home' => FALSE, 'home_id' => cnSettingsAPI::get('connections', 'connections_home_page', 'page_id'), 'return' => FALSE);
     $atts = wp_parse_args($atts, $defaults);
     $atts['parent_id'] = wp_parse_id_list($atts['parent_id']);
     $walker = new self();
     if (empty($atts['parent_id'])) {
         $terms = cnTerm::getTaxonomyTerms($atts['taxonomy'], array_merge($atts, array('name' => '')));
     } else {
         $terms = cnTerm::getTaxonomyTerms($atts['taxonomy'], array_merge($atts, array('include' => $atts['parent_id'], 'child_of' => 0, 'name' => '')));
         // If any of the `parent_id` is not a root parent (where $term->parent = 0) set it parent ID to `0`
         // so the term tree will be properly constructed.
         foreach ($terms as $term) {
             if (0 !== $term->parent) {
                 $term->parent = 0;
             }
         }
         foreach ($atts['parent_id'] as $termID) {
             $children = cnTerm::getTaxonomyTerms($atts['taxonomy'], array_merge($atts, array('child_of' => $termID, 'name' => '')));
             if (!is_wp_error($children)) {
                 $terms = array_merge($terms, $children);
             }
         }
     }
     /**
      * Allows extensions to add/remove class names to the term tree list.
      *
      * @since 8.5.18
      *
      * @param array $class The array of class names.
      * @param array $terms The array of terms.
      * @param array $atts  The method attributes.
      */
     $class = apply_filters('cn_term_list_class', array('cn-cat-tree'), $terms, $atts);
     $class = cnSanitize::htmlClass($class);
     $out .= '<ul class="' . cnFunction::escAttributeDeep($class) . '">' . PHP_EOL;
     if (empty($terms)) {
         $out .= '<li class="cat-item-none">' . $atts['show_option_none'] . '</li>';
     } else {
         if (cnQuery::getVar('cn-cat-slug')) {
             $slug = explode('/', cnQuery::getVar('cn-cat-slug'));
             // If the category slug is a descendant, use the last slug from the URL for the query.
             $atts['current_category'] = end($slug);
         } elseif ($catIDs = cnQuery::getVar('cn-cat')) {
             if (is_array($catIDs)) {
                 // If value is a string, strip the white space and covert to an array.
                 $catIDs = wp_parse_id_list($catIDs);
                 // Use the first element
                 $atts['current_category'] = reset($catIDs);
             } else {
                 $atts['current_category'] = $catIDs;
             }
         } else {
             $atts['current_category'] = 0;
         }
         if (!empty($atts['show_option_all'])) {
             $out .= '<li class="cat-item-all"><a href="' . cnURL::permalink(array('type' => 'home', 'data' => 'url', 'return' => TRUE)) . '">' . $atts['show_option_all'] . '</a></li>';
         }
         $out .= $walker->walk($terms, $atts['depth'], $atts);
     }
     $out .= '</ul>' . PHP_EOL;
     if ($atts['return']) {
         return $out;
     }
     echo $out;
 }
 /**
  * Display or retrieve the HTML select list of terms.
  *
  * This is the Connections equivalent of @see wp_dropdown_categories() in WordPress core ../wp-includes/category-template.php
  *
  * @access public
  * @since  8.2
  * @static
  *
  * @uses   wp_parse_args()
  * @uses   cnTerm::getTaxonomyTerms()
  * @uses   esc_attr()
  * @uses   sanitize_html_class()
  * @uses   apply_filters()
  * @uses   Walker::walk()
  * @uses   selected()
  *
  * @param array $atts {
  *     Optional. An array of arguments.
  *     NOTE: Additionally, all valid options as supported in @see cnTerm::getTaxonomyTerms().
  *
  * @type string $show_option_all   A non-blank value causes the display of a link to the directory home page.
  *                                 Default: ''. The default is not to display a link.
  *                                 Accepts: Any valid string.
  * @type string $show_option_none  Set the text to show when no categories are listed.
  *                                 Default: 'No Categories'
  *                                 Accepts: Any valid string.
  * @type bool   $show_count        Whether or not to display the category count.
  *                                 Default: FALSE
  * @type string $name              The select name attribute.
  *                                 Default: 'cat'
  * @type string $id                The select id attribute.
  *                                 Default: ''
  * @type string $class             The select class attribute.
  *                                 Default: 'postform'
  * @type int    $depth             Controls how many levels in the hierarchy of categories are to be included in the list.
  *                                 Default: 0
  *                                 Accepts: 0  - All categories and child categories.
  *                                          -1 - All Categories displayed  flat, not showing the parent/child relationships.
  *                                          1  - Show only top level/root parent categories.
  *                                          n  - Value of n (int) specifies the depth (or level) to descend in displaying the categories.
  * @type int    $tab_index         The select tab index.
  *                                 Default: 0
  * @type string $taxonomy          The taxonomy tree to display.
  *                                 Default: 'category'
  *                                 Accepts: Any registered taxonomy.
  * @type bool   $hide_if_empty     Whether or not to show the select if no terms are returned by term query.
  *                                 Default: FALSE
  * @type string $option_none_value Value to use when no term is selected.
  *                                 Default: -1
  *                                 Accepts: Any valid int/string for an option value attribute.
  * @type int    $selected          The selected term ID.
  * @type bool   $return            Whether or not to return or echo the resulting HTML.
  *                                 Default: FALSE
  * }
  *
  * @return string
  */
 public static function render($atts = array())
 {
     $out = '';
     $defaults = array('show_option_all' => '', 'show_option_none' => '', 'orderby' => 'name', 'order' => 'ASC', 'show_count' => FALSE, 'hide_empty' => FALSE, 'name' => 'cat', 'id' => '', 'class' => 'postform', 'depth' => 0, 'tab_index' => 0, 'taxonomy' => 'category', 'hide_if_empty' => FALSE, 'option_none_value' => -1, 'selected' => 0, 'return' => FALSE);
     $atts = wp_parse_args($atts, $defaults);
     $walker = new self();
     $walker->tree_type = $atts['taxonomy'];
     if (!isset($atts['pad_counts']) && $atts['show_count'] && $atts['hierarchical']) {
         $atts['pad_counts'] = TRUE;
     }
     $tab_index_attribute = (int) $atts['tab_index'] > 0 ? " tabindex=\"{$atts['tab_index']}\"" : '';
     $terms = cnTerm::getTaxonomyTerms($atts['taxonomy'], $atts);
     $name = esc_attr($atts['name']);
     $class = sanitize_html_class($atts['class']);
     $id = $atts['id'] ? esc_attr($atts['id']) : $name;
     if (!$atts['hide_if_empty'] || !empty($terms)) {
         $out .= PHP_EOL . "<select name='{$name}' id='{$id}' class='{$class}' {$tab_index_attribute}>" . PHP_EOL;
     } else {
         $out .= '';
     }
     if (empty($terms) && !$atts['hide_if_empty'] && !empty($atts['show_option_none'])) {
         /**
          * Filter a taxonomy drop-down display element.
          *
          * @since 8.2
          *
          * @param string $element Taxonomy term name.
          */
         $show_option_none = apply_filters('cn_list_cats', $atts['show_option_none']);
         $out .= "\t<option value='" . esc_attr($atts['option_none_value']) . "' selected='selected'>{$show_option_none}</option>\n";
     }
     if (!empty($terms)) {
         if ($atts['show_option_all']) {
             /** This filter is documented in includes/template/class.template-walker-term-select.php */
             $show_option_all = apply_filters('cn_list_cats', $atts['show_option_all']);
             $selected = '0' === strval($atts['selected']) ? " selected='selected'" : '';
             $out .= "\t<option value='0'{$selected}>{$show_option_all}</option>\n";
         }
         if ($atts['show_option_none']) {
             /** This filter is documented in includes/template/class.template-walker-term-select.php */
             $show_option_none = apply_filters('cn_list_cats', $atts['show_option_none']);
             $selected = selected($atts['option_none_value'], $atts['selected'], FALSE);
             $out .= "\t<option value='" . esc_attr($atts['option_none_value']) . "'{$selected}>{$show_option_none}</option>\n";
         }
         if ($atts['hierarchical']) {
             $depth = $atts['depth'];
             // Walk the full depth.
         } else {
             $depth = -1;
             // Flat.
         }
         $out .= $walker->walk($terms, $depth, $atts);
     }
     if (!$atts['hide_if_empty'] || !empty($terms)) {
         $out .= "</select>" . PHP_EOL;
     }
     /**
      * Filter the taxonomy drop-down output.
      *
      * @since 8.2
      *
      * @param string $out HTML output.
      * @param array  $atts      Arguments used to build the drop-down.
      */
     $out = apply_filters('cn_dropdown_cats', $out, $atts);
     if ($atts['return']) {
         return $out;
     }
     echo $out;
 }
 /**
  * Render an unordered list of categories.
  *
  * This is the Connections equivalent of @see wp_list_categories() in WordPress core ../wp-includes/category-template.php
  *
  * @access public
  * @since  8.1.6
  * @static
  *
  * @uses   wp_parse_args()
  * @uses   cnTerm::getTaxonomyTerms()
  * @uses   cnURL::permalink()
  * @uses   Walker::walk()
  *
  * @param array $atts {
  *     Optional. An array of arguments.
  *     NOTE: Additionally, all valid options as supported in @see cnTerm::getTaxonomyTerms().
  *
  * @type string $show_option_all  A non-blank value causes the display of a link to the directory home page.
  *                                Default: ''. The default is not to display a link.
  *                                Accepts: Any valid string.
  * @type string $show_option_none Set the text to show when no categories are listed.
  *                                Default: 'No Categories'
  *                                Accepts: Any valid string.
  * @type bool   $show_count       Whether or not to display the category count.
  *                                Default: FALSE
  * @type int    $depth            Controls how many levels in the hierarchy of categories are to be included in the list.
  *                                Default: 0
  *                                Accepts: 0  - All categories and child categories.
  *                                         -1 - All Categories displayed  flat, not showing the parent/child relationships.
  *                                         1  - Show only top level/root parent categories.
  *                                         n  - Value of n (int) specifies the depth (or level) to descend in displaying the categories.
  * @type string $taxonomy         The taxonomy tree to display.
  *                                Default: 'category'
  *                                Accepts: Any registered taxonomy.
  * @type bool   $return           Whether or not to return or echo the resulting HTML.
  *                                Default: FALSE
  * }
  *
  * @return string
  */
 public static function render($atts = array())
 {
     $out = '';
     $defaults = array('show_option_all' => '', 'show_option_none' => __('No categories', 'connections'), 'orderby' => 'name', 'order' => 'ASC', 'show_count' => FALSE, 'hide_empty' => FALSE, 'child_of' => 0, 'exclude' => array(), 'hierarchical' => TRUE, 'depth' => 0, 'parent_id' => array(), 'taxonomy' => 'category', 'return' => FALSE);
     $atts = wp_parse_args($atts, $defaults);
     $atts['parent_id'] = wp_parse_id_list($atts['parent_id']);
     $walker = new self();
     if (empty($atts['parent_id'])) {
         $terms = cnTerm::getTaxonomyTerms($atts['taxonomy'], $atts);
     } else {
         $terms = cnTerm::getTaxonomyTerms($atts['taxonomy'], array_merge($atts, array('include' => $atts['parent_id'], 'child_of' => 0)));
         // If any of the `parent_id` is not a root parent (where $term->parent = 0) set it parent ID to `0`
         // so the term tree will be properly constructed.
         foreach ($terms as $term) {
             if (0 !== $term->parent) {
                 $term->parent = 0;
             }
         }
         foreach ($atts['parent_id'] as $termID) {
             $children = cnTerm::getTaxonomyTerms($atts['taxonomy'], array_merge($atts, array('child_of' => $termID)));
             if (!is_wp_error($children)) {
                 $terms = array_merge($terms, $children);
             }
         }
     }
     $out .= '<ul class="cn-cat-tree">' . PHP_EOL;
     if (empty($terms)) {
         $out .= '<li class="cat-item-none">' . $atts['show_option_none'] . '</li>';
     } else {
         if (get_query_var('cn-cat-slug')) {
             $slug = explode('/', get_query_var('cn-cat-slug'));
             // If the category slug is a descendant, use the last slug from the URL for the query.
             $atts['current_category'] = end($slug);
         } elseif ($catIDs = get_query_var('cn-cat')) {
             if (is_array($catIDs)) {
                 // If value is a string, strip the white space and covert to an array.
                 $catIDs = wp_parse_id_list($catIDs);
                 // Use the first element
                 $atts['current_category'] = reset($catIDs);
             } else {
                 $atts['current_category'] = $catIDs;
             }
         } else {
             $atts['current_category'] = 0;
         }
         if (!empty($atts['show_option_all'])) {
             $out .= '<li class="cat-item-all"><a href="' . cnURL::permalink(array('type' => 'home', 'data' => 'url', 'return' => TRUE)) . '">' . $atts['show_option_all'] . '</a></li>';
         }
         $out .= $walker->walk($terms, $atts['depth'], $atts);
     }
     $out .= '</ul>' . PHP_EOL;
     if ($atts['return']) {
         return $out;
     }
     echo $out;
 }
 /**
  * Render an checklist of terms.
  *
  * This is the Connections equivalent of @see wp_terms_checklist() in WordPress core ..wp-admin/wp-includes/template.php
  *
  * @access public
  * @since  8.2.4
  * @static
  *
  * @uses   wp_parse_args()
  * @uses   cnTerm::getTaxonomyTerms()
  * @uses   wp_parse_id_list()
  * @uses   is_wp_error()
  * @uses   esc_attr()
  * @uses   apply_filters
  * @uses   checked()
  * @uses   esc_html()
  * @uses   Walker::walk()
  *
  * @param array $atts {
  *     Optional. An array of arguments.
  *     NOTE: Additionally, all valid options as supported in @see cnTerm::getTaxonomyTerms().
  *
  * @type string $taxonomy        The taxonomy tree to display.
  *                               Default: 'category'
  * @type bool   $hierarchical    Whether to include terms that have non-empty descendants, even if 'hide_empty' is set to TRUE.
  *                               Default: TRUE
  * @type string $name            The select name attribute.
  *                               Default: 'cn-cat'
  * @type bool   $show_select_all Whether or not to render the $show_option_all option.
  *                               Default: TRUE
  * @type string $show_option_all A non-blank value causes the display of a link to the directory home page.
  *                               Default: ''. The default is not to display a link.
  *                               Accepts: Any valid string.
  * @type bool   $show_count      Whether or not to display the category count.
  *                               Default: FALSE
  * @type bool   $hide_empty      Whether or not to display empty terms.
  *                               Default: FALSE
  * @type int    $depth           Controls how many levels in the hierarchy of categories are to be included in the list.
  *                               Default: 0
  *                               Accepts: 0  - All categories and child categories.
  *                                        -1 - All Categories displayed  flat, not showing the parent/child relationships.
  *                                        1  - Show only top level/root parent categories.
  *                                        n  - Value of n (int) specifies the depth (or level) to descend in displaying the categories.
  * @type array  $parent_id
  * @type array  $selected        The selected term IDs.
  *                               Default: 0
  * @type string $before          Content to be render before the label and select.
  *                               Default: ''
  * @type string $after           Content to be render after the label and select.
  *                               Default: ''
  * @type bool $return Whether or not to return or echo the resulting HTML.
  *                               Default: FALSE
  * }
  *
  * @return string
  */
 public static function render($atts = array())
 {
     $out = '';
     $defaults = array('taxonomy' => 'category', 'hierarchical' => TRUE, 'name' => 'cn-cat', 'show_select_all' => TRUE, 'show_option_all' => __('Select Category', 'connections'), 'show_count' => FALSE, 'hide_empty' => FALSE, 'depth' => 0, 'parent_id' => array(), 'selected' => 0, 'before' => '', 'after' => '', 'return' => FALSE);
     $atts = wp_parse_args($atts, $defaults);
     $walker = new self();
     $walker->tree_type = $atts['taxonomy'];
     if (empty($atts['parent_id'])) {
         $terms = cnTerm::getTaxonomyTerms($atts['taxonomy'], $atts);
     } else {
         $atts['parent_id'] = wp_parse_id_list($atts['parent_id']);
         $terms = cnTerm::getTaxonomyTerms($atts['taxonomy'], array_merge($atts, array('include' => $atts['parent_id'], 'child_of' => 0)));
         // If any of the `parent_id` is not a root parent (where $term->parent = 0) set it parent ID to `0`
         // so the term tree will be properly constructed.
         foreach ($terms as $term) {
             if (0 !== $term->parent) {
                 $term->parent = 0;
             }
         }
         foreach ($atts['parent_id'] as $termID) {
             $children = cnTerm::getTaxonomyTerms($atts['taxonomy'], array_merge($atts, array('child_of' => $termID)));
             if (!is_wp_error($children)) {
                 $terms = array_merge($terms, $children);
             }
         }
     }
     if (!empty($terms)) {
         $out .= '<ul class="cn-' . esc_attr($atts['taxonomy']) . '-radio-group">' . PHP_EOL;
         if ($atts['show_select_all'] && $atts['show_option_all']) {
             /** This filter is documented in includes/template/class.template-walker-term-select.php */
             $show_option_all = apply_filters('cn_list_cats', $atts['show_option_all']);
             $type = esc_attr($walker->tree_type);
             $out .= "<li id='cn-{$type}-0'>" . '<label><input value="0" type="radio" name="' . esc_attr($atts['name']) . '" id="cn-in-' . $type . '-0"' . checked(in_array(0, (array) $atts['selected']), TRUE, FALSE) . ' /> ' . esc_html($show_option_all) . '</label>';
             $out .= '</li>' . PHP_EOL;
         }
         $out .= $walker->walk($terms, $atts['depth'], $atts);
         $out .= '</ul>' . PHP_EOL;
     }
     $out = (empty($atts['before']) ? '' : $atts['before']) . $out . (empty($atts['after']) ? '' : $atts['after']);
     if ($atts['return']) {
         return $out;
     }
     echo $out;
 }