Exemplo n.º 1
0
 /**
  * Generate the widget control form (Do NOT override).
  *
  * @since 0.0.1
  * @access public
  *
  * @param int|array $widget_args Widget instance number or array of widget arguments.
  * @return string|null
  */
 public function form_callback($widget_args = 1)
 {
     if (is_numeric($widget_args)) {
         $widget_args = array('number' => $widget_args);
     }
     $widget_args = hq_parse_args($widget_args, array('number' => -1));
     $all_instances = $this->get_settings();
     if (-1 == $widget_args['number']) {
         // We echo out a form where 'number' can be set later
         $this->_set('__i__');
         $instance = array();
     } else {
         $this->_set($widget_args['number']);
         $instance = $all_instances[$widget_args['number']];
     }
     /**
      * Filter the widget instance's settings before displaying the control form.
      *
      * Returning false effectively short-circuits display of the control form.
      *
      * @since 0.0.1
      *
      * @param array     $instance The current widget instance's settings.
      * @param HQ_Widget $this     The current widget instance.
      */
     $instance = apply_filters('widget_form_callback', $instance, $this);
     $return = null;
     if (false !== $instance) {
         $return = $this->form($instance);
         /**
          * Fires at the end of the widget control form.
          *
          * Use this hook to add extra fields to the widget form. The hook
          * is only fired if the value passed to the 'widget_form_callback'
          * hook is not false.
          *
          * Note: If the widget has no form, the text echoed from the default
          * form method can be hidden using CSS.
          *
          * @since 0.0.1
          *
          * @param HQ_Widget $this     The widget instance, passed by reference.
          * @param null      $return   Return null if new fields are added.
          * @param array     $instance An array of the widget's settings.
          */
         do_action_ref_array('in_widget_form', array(&$this, &$return, $instance));
     }
     return $return;
 }
Exemplo n.º 2
0
/**
 * Kill HiveQueen execution and display XML message with error message.
 *
 * This is the handler for hq_die when processing XMLRPC requests.
 *
 * @since 0.0.1
 * @access private
 *
 * @global hq_xmlrpc_server $hq_xmlrpc_server
 *
 * @param string       $message Error message.
 * @param string       $title   Optional. Error title. Default empty.
 * @param string|array $args    Optional. Arguments to control behavior. Default empty array.
 */
function _xmlrpc_hq_die_handler($message, $title = '', $args = array())
{
    global $hq_xmlrpc_server;
    $defaults = array('response' => 500);
    $r = hq_parse_args($args, $defaults);
    if ($hq_xmlrpc_server) {
        $error = new IXR_Error($r['response'], $message);
        $hq_xmlrpc_server->output($error->getXml());
    }
    die;
}
Exemplo n.º 3
0
 /**
  * Displays a human readable HTML representation of the difference between two strings.
  *
  * The Diff is available for getting the changes between versions. The output is
  * HTML, so the primary use is for displaying the changes. If the two strings
  * are equivalent, then an empty string will be returned.
  *
  * The arguments supported and can be changed are listed below.
  *
  * 'title' : Default is an empty string. Titles the diff in a manner compatible
  *		with the output.
  * 'title_left' : Default is an empty string. Change the HTML to the left of the
  *		title.
  * 'title_right' : Default is an empty string. Change the HTML to the right of
  *		the title.
  *
  * @since 0.0.1
  *
  * @see hq_parse_args() Used to change defaults to user defined settings.
  * @uses Text_Diff
  * @uses HQ_Text_Diff_Renderer_Table
  *
  * @param string       $left_string  "old" (left) version of string
  * @param string       $right_string "new" (right) version of string
  * @param string|array $args         Optional. Change 'title', 'title_left', and 'title_right' defaults.
  * @return string Empty string if strings are equivalent or HTML with differences.
  */
 function hq_text_diff($left_string, $right_string, $args = null)
 {
     $defaults = array('title' => '', 'title_left' => '', 'title_right' => '');
     $args = hq_parse_args($args, $defaults);
     if (!class_exists('HQ_Text_Diff_Renderer_Table')) {
         require ABSPATH . HQINC . '/hq-diff.php';
     }
     $left_string = normalize_whitespace($left_string);
     $right_string = normalize_whitespace($right_string);
     $left_lines = explode("\n", $left_string);
     $right_lines = explode("\n", $right_string);
     $text_diff = new Text_Diff($left_lines, $right_lines);
     $renderer = new HQ_Text_Diff_Renderer_Table($args);
     $diff = $renderer->render($text_diff);
     if (!$diff) {
         return '';
     }
     $r = "<table class='diff'>\n";
     if (!empty($args['show_split_view'])) {
         $r .= "<col class='content diffsplit left' /><col class='content diffsplit middle' /><col class='content diffsplit right' />";
     } else {
         $r .= "<col class='content' />";
     }
     if ($args['title'] || $args['title_left'] || $args['title_right']) {
         $r .= "<thead>";
     }
     if ($args['title']) {
         $r .= "<tr class='diff-title'><th colspan='4'>{$args['title']}</th></tr>\n";
     }
     if ($args['title_left'] || $args['title_right']) {
         $r .= "<tr class='diff-sub-title'>\n";
         $r .= "\t<td></td><th>{$args['title_left']}</th>\n";
         $r .= "\t<td></td><th>{$args['title_right']}</th>\n";
         $r .= "</tr>\n";
     }
     if ($args['title'] || $args['title_left'] || $args['title_right']) {
         $r .= "</thead>\n";
     }
     $r .= "<tbody>\n{$diff}\n</tbody>\n";
     $r .= "</table>";
     return $r;
 }
Exemplo n.º 4
0
/**
 * List all the authors of the blog, with several options available.
 *
 * @link https://codex.wordpress.org/Template_Tags/hq_list_authors
 *
 * @since 0.0.1
 *
 * @global hqdb $hqdb
 *
 * @param string|array $args {
 *     Optional. Array or string of default arguments.
 *
 *     @type string $orderby       How to sort the authors. Accepts 'nicename', 'email', 'url', 'registered',
 *                                 'user_nicename', 'user_email', 'user_url', 'user_registered', 'name',
 *                                 'display_name', 'post_count', 'ID', 'meta_value', 'user_login'. Default 'name'.
 *     @type string $order         Sorting direction for $orderby. Accepts 'ASC', 'DESC'. Default 'ASC'.
 *     @type int    $number        Maximum authors to return or display. Default empty (all authors).
 *     @type bool   $optioncount   Show the count in parenthesis next to the author's name. Default false.
 *     @type bool   $exclude_admin Whether to exclude the 'admin' account, if it exists. Default false.
 *     @type bool   $show_fullname Whether to show the author's full name. Default false.
 *     @type bool   $hide_empty    Whether to hide any authors with no posts. Default true.
 *     @type string $feed          If not empty, show a link to the author's feed and use this text as the alt
 *                                 parameter of the link. Default empty.
 *     @type string $feed_image    If not empty, show a link to the author's feed and use this image URL as
 *                                 clickable anchor. Default empty.
 *     @type string $feed_type     The feed type to link to, such as 'rss2'. Defaults to default feed type.
 *     @type bool   $echo          Whether to output the result or instead return it. Default true.
 *     @type string $style         If 'list', each author is wrapped in an `<li>` element, otherwise the authors
 *                                 will be separated by commas.
 *     @type bool   $html          Whether to list the items in HTML form or plaintext. Default true.
 *     @type string $exclude       An array, comma-, or space-separated list of author IDs to exclude. Default empty.
 *     @type string $exclude       An array, comma-, or space-separated list of author IDs to include. Default empty.
 * }
 * @return string|void The output, if echo is set to false.
 */
function hq_list_authors($args = '')
{
    global $hqdb;
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'number' => '', 'optioncount' => false, 'exclude_admin' => true, 'show_fullname' => false, 'hide_empty' => true, 'feed' => '', 'feed_image' => '', 'feed_type' => '', 'echo' => true, 'style' => 'list', 'html' => true, 'exclude' => '', 'include' => '');
    $args = hq_parse_args($args, $defaults);
    $return = '';
    $query_args = hq_array_slice_assoc($args, array('orderby', 'order', 'number', 'exclude', 'include'));
    $query_args['fields'] = 'ids';
    $authors = get_users($query_args);
    $author_count = array();
    foreach ((array) $hqdb->get_results("SELECT DISTINCT post_author, COUNT(ID) AS count FROM {$hqdb->posts} WHERE " . get_private_posts_cap_sql('post') . " GROUP BY post_author") as $row) {
        $author_count[$row->post_author] = $row->count;
    }
    foreach ($authors as $author_id) {
        $author = get_userdata($author_id);
        if ($args['exclude_admin'] && 'admin' == $author->display_name) {
            continue;
        }
        $posts = isset($author_count[$author->ID]) ? $author_count[$author->ID] : 0;
        if (!$posts && $args['hide_empty']) {
            continue;
        }
        if ($args['show_fullname'] && $author->first_name && $author->last_name) {
            $name = "{$author->first_name} {$author->last_name}";
        } else {
            $name = $author->display_name;
        }
        if (!$args['html']) {
            $return .= $name . ', ';
            continue;
            // No need to go further to process HTML.
        }
        if ('list' == $args['style']) {
            $return .= '<li>';
        }
        $link = '<a href="' . get_author_posts_url($author->ID, $author->user_nicename) . '" title="' . esc_attr(sprintf(__("Posts by %s"), $author->display_name)) . '">' . $name . '</a>';
        if (!empty($args['feed_image']) || !empty($args['feed'])) {
            $link .= ' ';
            if (empty($args['feed_image'])) {
                $link .= '(';
            }
            $link .= '<a href="' . get_author_feed_link($author->ID, $args['feed_type']) . '"';
            $alt = '';
            if (!empty($args['feed'])) {
                $alt = ' alt="' . esc_attr($args['feed']) . '"';
                $name = $args['feed'];
            }
            $link .= '>';
            if (!empty($args['feed_image'])) {
                $link .= '<img src="' . esc_url($args['feed_image']) . '" style="border: none;"' . $alt . ' />';
            } else {
                $link .= $name;
            }
            $link .= '</a>';
            if (empty($args['feed_image'])) {
                $link .= ')';
            }
        }
        if ($args['optioncount']) {
            $link .= ' (' . $posts . ')';
        }
        $return .= $link;
        $return .= 'list' == $args['style'] ? '</li>' : ', ';
    }
    $return = rtrim($return, ', ');
    if (!$args['echo']) {
        return $return;
    }
    echo $return;
}
Exemplo n.º 5
0
/**
 * This function inserts/updates links into/in the database.
 *
 * @since 0.0.1
 *
 * @global hqdb $hqdb
 *
 * @param array $linkdata Elements that make up the link to insert.
 * @param bool  $hq_error Optional. If true return HQ_Error object on failure.
 * @return int|HQ_Error Value 0 or HQ_Error on failure. The link ID on success.
 */
function hq_insert_link($linkdata, $hq_error = false)
{
    global $hqdb;
    $defaults = array('link_id' => 0, 'link_name' => '', 'link_url' => '', 'link_rating' => 0);
    $args = hq_parse_args($linkdata, $defaults);
    $r = hq_unslash(sanitize_bookmark($args, 'db'));
    $link_id = $r['link_id'];
    $link_name = $r['link_name'];
    $link_url = $r['link_url'];
    $update = false;
    if (!empty($link_id)) {
        $update = true;
    }
    if (trim($link_name) == '') {
        if (trim($link_url) != '') {
            $link_name = $link_url;
        } else {
            return 0;
        }
    }
    if (trim($link_url) == '') {
        return 0;
    }
    $link_rating = !empty($r['link_rating']) ? $r['link_rating'] : 0;
    $link_image = !empty($r['link_image']) ? $r['link_image'] : '';
    $link_target = !empty($r['link_target']) ? $r['link_target'] : '';
    $link_visible = !empty($r['link_visible']) ? $r['link_visible'] : 'Y';
    $link_owner = !empty($r['link_owner']) ? $r['link_owner'] : get_current_user_id();
    $link_notes = !empty($r['link_notes']) ? $r['link_notes'] : '';
    $link_description = !empty($r['link_description']) ? $r['link_description'] : '';
    $link_rss = !empty($r['link_rss']) ? $r['link_rss'] : '';
    $link_rel = !empty($r['link_rel']) ? $r['link_rel'] : '';
    $link_category = !empty($r['link_category']) ? $r['link_category'] : array();
    // Make sure we set a valid category
    if (!is_array($link_category) || 0 == count($link_category)) {
        $link_category = array(get_option('default_link_category'));
    }
    if ($update) {
        if (false === $hqdb->update($hqdb->links, compact('link_url', 'link_name', 'link_image', 'link_target', 'link_description', 'link_visible', 'link_rating', 'link_rel', 'link_notes', 'link_rss'), compact('link_id'))) {
            if ($hq_error) {
                return new HQ_Error('db_update_error', __('Could not update link in the database'), $hqdb->last_error);
            } else {
                return 0;
            }
        }
    } else {
        if (false === $hqdb->insert($hqdb->links, compact('link_url', 'link_name', 'link_image', 'link_target', 'link_description', 'link_visible', 'link_owner', 'link_rating', 'link_rel', 'link_notes', 'link_rss'))) {
            if ($hq_error) {
                return new HQ_Error('db_insert_error', __('Could not insert link into the database'), $hqdb->last_error);
            } else {
                return 0;
            }
        }
        $link_id = (int) $hqdb->insert_id;
    }
    hq_set_link_cats($link_id, $link_category);
    if ($update) {
        /**
         * Fires after a link was updated in the database.
         *
         * @since 0.0.1
         *
         * @param int $link_id ID of the link that was updated.
         */
        do_action('edit_link', $link_id);
    } else {
        /**
         * Fires after a link was added to the database.
         *
         * @since 0.0.1
         *
         * @param int $link_id ID of the link that was added.
         */
        do_action('add_link', $link_id);
    }
    clean_bookmark_cache($link_id);
    return $link_id;
}
Exemplo n.º 6
0
 /**
  * Prepare the query variables.
  *
  * @since 0.0.1
  * @access public
  *
  * @global hqdb $hqdb
  * @global int  $blog_id
  *
  * @param string|array $query {
  *     Optional. Array or string of Query parameters.
  *
  *     @type int          $blog_id             The site ID. Default is the global blog id.
  *     @type string       $role                Role name. Default empty.
  *     @type string       $meta_key            User meta key. Default empty.
  *     @type string       $meta_value          User meta value. Default empty.
  *     @type string       $meta_compare        Comparison operator to test the `$meta_value`. Accepts '=', '!=',
  *                                             '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN',
  *                                             'BETWEEN', 'NOT BETWEEN', 'EXISTS', 'NOT EXISTS', 'REGEXP',
  *                                             'NOT REGEXP', or 'RLIKE'. Default '='.
  *     @type array        $include             An array of user IDs to include. Default empty array.
  *     @type array        $exclude             An array of user IDs to exclude. Default empty array.
  *     @type string       $search              Search keyword. Searches for possible string matches on columns.
  *                                             When `$search_columns` is left empty, it tries to determine which
  *                                             column to search in based on search string. Default empty.
  *     @type array        $search_columns      Array of column names to be searched. Accepts 'ID', 'login',
  *                                             'nicename', 'email', 'url'. Default empty array.
  *     @type string|array $orderby             Field(s) to sort the retrieved users by. May be a single value,
  *                                             an array of values, or a multi-dimensional array with fields as
  *                                             keys and orders ('ASC' or 'DESC') as values. Accepted values are
  *                                             'ID', 'display_name' (or 'name'), 'user_login' (or 'login'),
  *                                             'user_nicename' (or 'nicename'), 'user_email' (or 'email'),
  *                                             'user_url' (or 'url'), 'user_registered' (or 'registered'),
  *                                             'post_count', 'meta_value', 'meta_value_num', the value of
  *                                             `$meta_key`, or an array key of `$meta_query`. To use
  *                                             'meta_value' or 'meta_value_num', `$meta_key` must be also be
  *                                             defined. Default 'user_login'.
  *     @type string       $order               Designates ascending or descending order of users. Order values
  *                                             passed as part of an `$orderby` array take precedence over this
  *                                             parameter. Accepts 'ASC', 'DESC'. Default 'ASC'.
  *     @type int          $offset              Number of users to offset in retrieved results. Can be used in
  *                                             conjunction with pagination. Default 0.
  *     @type int          $number              Number of users to limit the query for. Can be used in
  *                                             conjunction with pagination. Value -1 (all) is not supported.
  *                                             Default empty (all users).
  *     @type bool         $count_total         Whether to count the total number of users found. If pagination
  *                                             is not needed, setting this to false can improve performance.
  *                                             Default true.
  *     @type string|array $fields              Which fields to return. Single or all fields (string), or array
  *                                             of fields. Accepts 'ID', 'display_name', 'login', 'nicename',
  *                                             'email', 'url', 'registered'. Use 'all' for all fields and
  *                                             'all_with_meta' to include meta fields. Default 'all'.
  *     @type string       $who                 Type of users to query. Accepts 'authors'.
  *                                             Default empty (all users).
  *     @type bool|array   $has_published_posts Pass an array of post types to filter results to users who have
  *                                             published posts in those post types. `true` is an alias for all
  *                                             public post types.
  * }
  */
 public function prepare_query($query = array())
 {
     global $hqdb;
     if (empty($this->query_vars) || !empty($query)) {
         $this->query_limit = null;
         $this->query_vars = hq_parse_args($query, array('blog_id' => $GLOBALS['blog_id'], 'role' => '', 'meta_key' => '', 'meta_value' => '', 'meta_compare' => '', 'include' => array(), 'exclude' => array(), 'search' => '', 'search_columns' => array(), 'orderby' => 'login', 'order' => 'ASC', 'offset' => '', 'number' => '', 'count_total' => true, 'fields' => 'all', 'who' => '', 'has_published_posts' => null));
     }
     /**
      * Fires before the HQ_User_Query has been parsed.
      *
      * The passed HQ_User_Query object contains the query variables, not
      * yet passed into SQL.
      *
      * @since 0.0.1
      *
      * @param HQ_User_Query $this The current HQ_User_Query instance,
      *                            passed by reference.
      */
     do_action('pre_get_users', $this);
     $qv =& $this->query_vars;
     if (is_array($qv['fields'])) {
         $qv['fields'] = array_unique($qv['fields']);
         $this->query_fields = array();
         foreach ($qv['fields'] as $field) {
             $field = 'ID' === $field ? 'ID' : sanitize_key($field);
             $this->query_fields[] = "{$hqdb->users}.{$field}";
         }
         $this->query_fields = implode(',', $this->query_fields);
     } elseif ('all' == $qv['fields']) {
         $this->query_fields = "{$hqdb->users}.*";
     } else {
         $this->query_fields = "{$hqdb->users}.ID";
     }
     if (isset($qv['count_total']) && $qv['count_total']) {
         $this->query_fields = 'SQL_CALC_FOUND_ROWS ' . $this->query_fields;
     }
     $this->query_from = "FROM {$hqdb->users}";
     $this->query_where = "WHERE 1=1";
     // Parse and sanitize 'include', for use by 'orderby' as well as 'include' below.
     if (!empty($qv['include'])) {
         $include = hq_parse_id_list($qv['include']);
     } else {
         $include = false;
     }
     $blog_id = 0;
     if (isset($qv['blog_id'])) {
         $blog_id = absint($qv['blog_id']);
     }
     if (isset($qv['who']) && 'authors' == $qv['who'] && $blog_id) {
         $qv['meta_key'] = $hqdb->get_blog_prefix($blog_id) . 'user_level';
         $qv['meta_value'] = 0;
         $qv['meta_compare'] = '!=';
         $qv['blog_id'] = $blog_id = 0;
         // Prevent extra meta query
     }
     if ($qv['has_published_posts'] && $blog_id) {
         if (true === $qv['has_published_posts']) {
             $post_types = get_post_types(array('public' => true));
         } else {
             $post_types = (array) $qv['has_published_posts'];
         }
         foreach ($post_types as &$post_type) {
             $post_type = $hqdb->prepare('%s', $post_type);
         }
         $posts_table = $hqdb->get_blog_prefix($blog_id) . 'posts';
         $this->query_where .= " AND {$hqdb->users}.ID IN ( SELECT DISTINCT {$posts_table}.post_author FROM {$posts_table} WHERE {$posts_table}.post_status = 'publish' AND {$posts_table}.post_type IN ( " . join(", ", $post_types) . " ) )";
     }
     // Meta query.
     $this->meta_query = new HQ_Meta_Query();
     $this->meta_query->parse_query_vars($qv);
     $role = '';
     if (isset($qv['role'])) {
         $role = trim($qv['role']);
     }
     if ($blog_id && ($role || is_multisite())) {
         $cap_meta_query = array();
         $cap_meta_query['key'] = $hqdb->get_blog_prefix($blog_id) . 'capabilities';
         if ($role) {
             $cap_meta_query['value'] = '"' . $role . '"';
             $cap_meta_query['compare'] = 'like';
         }
         if (empty($this->meta_query->queries)) {
             $this->meta_query->queries = array($cap_meta_query);
         } elseif (!in_array($cap_meta_query, $this->meta_query->queries, true)) {
             // Append the cap query to the original queries and reparse the query.
             $this->meta_query->queries = array('relation' => 'AND', array($this->meta_query->queries, $cap_meta_query));
         }
         $this->meta_query->parse_query_vars($this->meta_query->queries);
     }
     if (!empty($this->meta_query->queries)) {
         $clauses = $this->meta_query->get_sql('user', $hqdb->users, 'ID', $this);
         $this->query_from .= $clauses['join'];
         $this->query_where .= $clauses['where'];
         if ($this->meta_query->has_or_relation()) {
             $this->query_fields = 'DISTINCT ' . $this->query_fields;
         }
     }
     // sorting
     $qv['order'] = isset($qv['order']) ? strtoupper($qv['order']) : '';
     $order = $this->parse_order($qv['order']);
     if (empty($qv['orderby'])) {
         // Default order is by 'user_login'.
         $ordersby = array('user_login' => $order);
     } elseif (is_array($qv['orderby'])) {
         $ordersby = $qv['orderby'];
     } else {
         // 'orderby' values may be a comma- or space-separated list.
         $ordersby = preg_split('/[,\\s]+/', $qv['orderby']);
     }
     $orderby_array = array();
     foreach ($ordersby as $_key => $_value) {
         if (!$_value) {
             continue;
         }
         if (is_int($_key)) {
             // Integer key means this is a flat array of 'orderby' fields.
             $_orderby = $_value;
             $_order = $order;
         } else {
             // Non-integer key means this the key is the field and the value is ASC/DESC.
             $_orderby = $_key;
             $_order = $_value;
         }
         $parsed = $this->parse_orderby($_orderby);
         if (!$parsed) {
             continue;
         }
         $orderby_array[] = $parsed . ' ' . $this->parse_order($_order);
     }
     // If no valid clauses were found, order by user_login.
     if (empty($orderby_array)) {
         $orderby_array[] = "user_login {$order}";
     }
     $this->query_orderby = 'ORDER BY ' . implode(', ', $orderby_array);
     // limit
     if (isset($qv['number']) && $qv['number']) {
         if ($qv['offset']) {
             $this->query_limit = $hqdb->prepare("LIMIT %d, %d", $qv['offset'], $qv['number']);
         } else {
             $this->query_limit = $hqdb->prepare("LIMIT %d", $qv['number']);
         }
     }
     $search = '';
     if (isset($qv['search'])) {
         $search = trim($qv['search']);
     }
     if ($search) {
         $leading_wild = ltrim($search, '*') != $search;
         $trailing_wild = rtrim($search, '*') != $search;
         if ($leading_wild && $trailing_wild) {
             $wild = 'both';
         } elseif ($leading_wild) {
             $wild = 'leading';
         } elseif ($trailing_wild) {
             $wild = 'trailing';
         } else {
             $wild = false;
         }
         if ($wild) {
             $search = trim($search, '*');
         }
         $search_columns = array();
         if ($qv['search_columns']) {
             $search_columns = array_intersect($qv['search_columns'], array('ID', 'user_login', 'user_email', 'user_url', 'user_nicename'));
         }
         if (!$search_columns) {
             if (false !== strpos($search, '@')) {
                 $search_columns = array('user_email');
             } elseif (is_numeric($search)) {
                 $search_columns = array('user_login', 'ID');
             } elseif (preg_match('|^https?://|', $search) && !(is_multisite() && hq_is_large_network('users'))) {
                 $search_columns = array('user_url');
             } else {
                 $search_columns = array('user_login', 'user_url', 'user_email', 'user_nicename', 'display_name');
             }
         }
         /**
          * Filter the columns to search in a HQ_User_Query search.
          *
          * The default columns depend on the search term, and include 'user_email',
          * 'user_login', 'ID', 'user_url', 'display_name', and 'user_nicename'.
          *
          * @since 0.0.1
          *
          * @param array         $search_columns Array of column names to be searched.
          * @param string        $search         Text being searched.
          * @param HQ_User_Query $this           The current HQ_User_Query instance.
          */
         $search_columns = apply_filters('user_search_columns', $search_columns, $search, $this);
         $this->query_where .= $this->get_search_sql($search, $search_columns, $wild);
     }
     if (!empty($include)) {
         // Sanitized earlier.
         $ids = implode(',', $include);
         $this->query_where .= " AND {$hqdb->users}.ID IN ({$ids})";
     } elseif (!empty($qv['exclude'])) {
         $ids = implode(',', hq_parse_id_list($qv['exclude']));
         $this->query_where .= " AND {$hqdb->users}.ID NOT IN ({$ids})";
     }
     // Date queries are allowed for the user_registered field.
     if (!empty($qv['date_query']) && is_array($qv['date_query'])) {
         $date_query = new HQ_Date_Query($qv['date_query'], 'user_registered');
         $this->query_where .= $date_query->get_sql();
     }
     /**
      * Fires after the HQ_User_Query has been parsed, and before
      * the query is executed.
      *
      * The passed HQ_User_Query object contains SQL parts formed
      * from parsing the given query.
      *
      * @since 0.0.1
      *
      * @param HQ_User_Query $this The current HQ_User_Query instance,
      *                            passed by reference.
      */
     do_action_ref_array('pre_user_query', array(&$this));
 }
Exemplo n.º 7
0
 /**
  * Sets up the HiveQueen query by parsing query string.
  *
  * @since 0.0.1
  * @access public
  *
  * @param string $query URL query string.
  * @return array List of posts.
  */
 public function query($query)
 {
     $this->init();
     $this->query = $this->query_vars = hq_parse_args($query);
     //Goyo: Debug
     //printf("querys:  ");
     //foreach ( (array) array_keys($query) as $hqvar) {
     //foreach ( (array) array_keys($this->query) as $hqvar) {
     //              printf("hqvar => %s", $hqvar);
     //}
     return $this->get_posts();
 }
Exemplo n.º 8
0
 /**
  * Add a new permalink structure.
  *
  * A permalink structure (permastruct) is an abstract definition of a set of rewrite rules; it
  * is an easy way of expressing a set of regular expressions that rewrite to a set of query strings.
  * The new permastruct is added to the {@link HQ_Rewrite::$extra_permastructs} array. When the
  * rewrite rules are built by {@link HQ_Rewrite::rewrite_rules()} all of these extra permastructs
  * are passed to {@link HQ_Rewrite::generate_rewrite_rules()} which transforms them into the
  * regular expressions that many love to hate.
  *
  * The $args parameter gives you control over how {@link HQ_Rewrite::generate_rewrite_rules()}
  * works on the new permastruct.
  *
  * @since 0.0.1
  * @access public
  *
  * @param string $name   Name for permalink structure.
  * @param string $struct Permalink structure (e.g. category/%category%)
  * @param array  $args   Optional configuration for building the rules from the permalink structure:
  *     - with_front (bool) - Should the structure be prepended with HQ_Rewrite::$front? Default is true.
  *     - ep_mask (int) - Endpoint mask defining what endpoints are added to the structure. Default is EP_NONE.
  *     - paged (bool) - Should archive pagination rules be added for the structure? Default is true.
  *     - feed (bool) - Should feed rewrite rules be added for the structure? Default is true.
  *     - forcomments (bool) - Should the feed rules be a query for a comments feed? Default is false.
  *     - walk_dirs (bool) - Should the 'directories' making up the structure be walked over and rewrite
  *                          rules built for each in turn? Default is true.
  *     - endpoints (bool) - Should endpoints be applied to the generated rewrite rules? Default is true.
  */
 public function add_permastruct($name, $struct, $args = array())
 {
     // backwards compatibility for the old parameters: $with_front and $ep_mask
     if (!is_array($args)) {
         $args = array('with_front' => $args);
     }
     if (func_num_args() == 4) {
         $args['ep_mask'] = func_get_arg(3);
     }
     $defaults = array('with_front' => true, 'ep_mask' => EP_NONE, 'paged' => true, 'feed' => true, 'forcomments' => false, 'walk_dirs' => true, 'endpoints' => true);
     $args = array_intersect_key($args, $defaults);
     $args = hq_parse_args($args, $defaults);
     if ($args['with_front']) {
         $struct = $this->front . $struct;
     } else {
         $struct = $this->root . $struct;
     }
     $args['struct'] = $struct;
     $this->extra_permastructs[$name] = $args;
 }
Exemplo n.º 9
0
/**
 * Allows a theme to register its support of a certain feature
 *
 * Must be called in the theme's functions.php file to work.
 * If attached to a hook, it must be after_setup_theme.
 * The init hook may be too late for some features.
 *
 * @since 0.0.1
 *
 * @global array $_hq_theme_features
 *
 * @param string $feature The feature being added.
 * @return void|bool False on failure, void otherwise.
 */
function add_theme_support($feature)
{
    global $_hq_theme_features;
    if (func_num_args() == 1) {
        $args = true;
    } else {
        $args = array_slice(func_get_args(), 1);
    }
    switch ($feature) {
        case 'post-formats':
            if (is_array($args[0])) {
                $post_formats = get_post_format_slugs();
                unset($post_formats['standard']);
                $args[0] = array_intersect($args[0], array_keys($post_formats));
            }
            break;
        case 'html5':
            // You can't just pass 'html5', you need to pass an array of types.
            if (empty($args[0])) {
                // Build an array of types for back-compat.
                $args = array(0 => array('comment-list', 'comment-form', 'search-form'));
            } elseif (!is_array($args[0])) {
                _doing_it_wrong("add_theme_support( 'html5' )", __('You need to pass an array of types.'), '3.6.1');
                return false;
            }
            // Calling 'html5' again merges, rather than overwrites.
            if (isset($_hq_theme_features['html5'])) {
                $args[0] = array_merge($_hq_theme_features['html5'][0], $args[0]);
            }
            break;
        case 'custom-header-uploads':
            return add_theme_support('custom-header', array('uploads' => true));
        case 'custom-header':
            if (!is_array($args)) {
                $args = array(0 => array());
            }
            $defaults = array('default-image' => '', 'random-default' => false, 'width' => 0, 'height' => 0, 'flex-height' => false, 'flex-width' => false, 'default-text-color' => '', 'header-text' => true, 'uploads' => true, 'hq-head-callback' => '', 'admin-head-callback' => '', 'admin-preview-callback' => '');
            $jit = isset($args[0]['__jit']);
            unset($args[0]['__jit']);
            // Merge in data from previous add_theme_support() calls.
            // The first value registered wins. (A child theme is set up first.)
            if (isset($_hq_theme_features['custom-header'])) {
                $args[0] = hq_parse_args($_hq_theme_features['custom-header'][0], $args[0]);
            }
            // Load in the defaults at the end, as we need to insure first one wins.
            // This will cause all constants to be defined, as each arg will then be set to the default.
            if ($jit) {
                $args[0] = hq_parse_args($args[0], $defaults);
            }
            // If a constant was defined, use that value. Otherwise, define the constant to ensure
            // the constant is always accurate (and is not defined later,  overriding our value).
            // As stated above, the first value wins.
            // Once we get to hq_loaded (just-in-time), define any constants we haven't already.
            // Constants are lame. Don't reference them. This is just for backwards compatibility.
            if (defined('NO_HEADER_TEXT')) {
                $args[0]['header-text'] = !NO_HEADER_TEXT;
            } elseif (isset($args[0]['header-text'])) {
                define('NO_HEADER_TEXT', empty($args[0]['header-text']));
            }
            if (defined('HEADER_IMAGE_WIDTH')) {
                $args[0]['width'] = (int) HEADER_IMAGE_WIDTH;
            } elseif (isset($args[0]['width'])) {
                define('HEADER_IMAGE_WIDTH', (int) $args[0]['width']);
            }
            if (defined('HEADER_IMAGE_HEIGHT')) {
                $args[0]['height'] = (int) HEADER_IMAGE_HEIGHT;
            } elseif (isset($args[0]['height'])) {
                define('HEADER_IMAGE_HEIGHT', (int) $args[0]['height']);
            }
            if (defined('HEADER_TEXTCOLOR')) {
                $args[0]['default-text-color'] = HEADER_TEXTCOLOR;
            } elseif (isset($args[0]['default-text-color'])) {
                define('HEADER_TEXTCOLOR', $args[0]['default-text-color']);
            }
            if (defined('HEADER_IMAGE')) {
                $args[0]['default-image'] = HEADER_IMAGE;
            } elseif (isset($args[0]['default-image'])) {
                define('HEADER_IMAGE', $args[0]['default-image']);
            }
            if ($jit && !empty($args[0]['default-image'])) {
                $args[0]['random-default'] = false;
            }
            // If headers are supported, and we still don't have a defined width or height,
            // we have implicit flex sizes.
            if ($jit) {
                if (empty($args[0]['width']) && empty($args[0]['flex-width'])) {
                    $args[0]['flex-width'] = true;
                }
                if (empty($args[0]['height']) && empty($args[0]['flex-height'])) {
                    $args[0]['flex-height'] = true;
                }
            }
            break;
        case 'custom-background':
            if (!is_array($args)) {
                $args = array(0 => array());
            }
            $defaults = array('default-image' => '', 'default-repeat' => 'repeat', 'default-position-x' => 'left', 'default-attachment' => 'scroll', 'default-color' => '', 'hq-head-callback' => '_custom_background_cb', 'admin-head-callback' => '', 'admin-preview-callback' => '');
            $jit = isset($args[0]['__jit']);
            unset($args[0]['__jit']);
            // Merge in data from previous add_theme_support() calls. The first value registered wins.
            if (isset($_hq_theme_features['custom-background'])) {
                $args[0] = hq_parse_args($_hq_theme_features['custom-background'][0], $args[0]);
            }
            if ($jit) {
                $args[0] = hq_parse_args($args[0], $defaults);
            }
            if (defined('BACKGROUND_COLOR')) {
                $args[0]['default-color'] = BACKGROUND_COLOR;
            } elseif (isset($args[0]['default-color']) || $jit) {
                define('BACKGROUND_COLOR', $args[0]['default-color']);
            }
            if (defined('BACKGROUND_IMAGE')) {
                $args[0]['default-image'] = BACKGROUND_IMAGE;
            } elseif (isset($args[0]['default-image']) || $jit) {
                define('BACKGROUND_IMAGE', $args[0]['default-image']);
            }
            break;
            // Ensure that 'title-tag' is accessible in the admin.
        // Ensure that 'title-tag' is accessible in the admin.
        case 'title-tag':
            // Can be called in functions.php but must happen before hq_loaded, i.e. not in header.php.
            if (did_action('hq_loaded')) {
                /* translators: 1: Theme support 2: hook name */
                _doing_it_wrong("add_theme_support( 'title-tag' )", sprintf(__('Theme support for %1$s should be registered before the %2$s hook.'), '<code>title-tag</code>', '<code>hq_loaded</code>'), '4.1');
                return false;
            }
    }
    $_hq_theme_features[$feature] = $args;
}
Exemplo n.º 10
0
/**
 * Retrieve paginated link for archive post pages.
 *
 * Technically, the function can be used to create paginated link list for any
 * area. The 'base' argument is used to reference the url, which will be used to
 * create the paginated links. The 'format' argument is then used for replacing
 * the page number. It is however, most likely and by default, to be used on the
 * archive post pages.
 *
 * The 'type' argument controls format of the returned value. The default is
 * 'plain', which is just a string with the links separated by a newline
 * character. The other possible values are either 'array' or 'list'. The
 * 'array' value will return an array of the paginated link list to offer full
 * control of display. The 'list' value will place all of the paginated links in
 * an unordered HTML list.
 *
 * The 'total' argument is the total amount of pages and is an integer. The
 * 'current' argument is the current page number and is also an integer.
 *
 * An example of the 'base' argument is "http://example.com/all_posts.php%_%"
 * and the '%_%' is required. The '%_%' will be replaced by the contents of in
 * the 'format' argument. An example for the 'format' argument is "?page=%#%"
 * and the '%#%' is also required. The '%#%' will be replaced with the page
 * number.
 *
 * You can include the previous and next links in the list by setting the
 * 'prev_next' argument to true, which it is by default. You can set the
 * previous text, by using the 'prev_text' argument. You can set the next text
 * by setting the 'next_text' argument.
 *
 * If the 'show_all' argument is set to true, then it will show all of the pages
 * instead of a short list of the pages near the current page. By default, the
 * 'show_all' is set to false and controlled by the 'end_size' and 'mid_size'
 * arguments. The 'end_size' argument is how many numbers on either the start
 * and the end list edges, by default is 1. The 'mid_size' argument is how many
 * numbers to either side of current page, but not including current page.
 *
 * It is possible to add query vars to the link by using the 'add_args' argument
 * and see {@link add_query_arg()} for more information.
 *
 * The 'before_page_number' and 'after_page_number' arguments allow users to
 * augment the links themselves. Typically this might be to add context to the
 * numbered links so that screen reader users understand what the links are for.
 * The text strings are added before and after the page number - within the
 * anchor tag.
 *
 * @since 0.0.1
 *
 * @global HQ_Query   $hq_query
 * @global HQ_Rewrite $hq_rewrite
 *
 * @param string|array $args {
 *     Optional. Array or string of arguments for generating paginated links for archives.
 *
 *     @type string $base               Base of the paginated url. Default empty.
 *     @type string $format             Format for the pagination structure. Default empty.
 *     @type int    $total              The total amount of pages. Default is the value HQ_Query's
 *                                      `max_num_pages` or 1.
 *     @type int    $current            The current page number. Default is 'paged' query var or 1.
 *     @type bool   $show_all           Whether to show all pages. Default false.
 *     @type int    $end_size           How many numbers on either the start and the end list edges.
 *                                      Default 1.
 *     @type int    $mid_size           How many numbers to either side of the current pages. Default 2.
 *     @type bool   $prev_next          Whether to include the previous and next links in the list. Default true.
 *     @type bool   $prev_text          The previous page text. Default '« Previous'.
 *     @type bool   $next_text          The next page text. Default '« Previous'.
 *     @type string $type               Controls format of the returned value. Possible values are 'plain',
 *                                      'array' and 'list'. Default is 'plain'.
 *     @type array  $add_args           An array of query args to add. Default false.
 *     @type string $add_fragment       A string to append to each link. Default empty.
 *     @type string $before_page_number A string to appear before the page number. Default empty.
 *     @type string $after_page_number  A string to append after the page number. Default empty.
 * }
 * @return array|string|void String of page links or array of page links.
 */
function paginate_links($args = '')
{
    global $hq_query, $hq_rewrite;
    // Setting up default values based on the current URL.
    $pagenum_link = html_entity_decode(get_pagenum_link());
    $url_parts = explode('?', $pagenum_link);
    // Get max pages and current page out of the current query, if available.
    $total = isset($hq_query->max_num_pages) ? $hq_query->max_num_pages : 1;
    $current = get_query_var('paged') ? intval(get_query_var('paged')) : 1;
    // Append the format placeholder to the base URL.
    $pagenum_link = trailingslashit($url_parts[0]) . '%_%';
    // URL base depends on permalink settings.
    $format = $hq_rewrite->using_index_permalinks() && !strpos($pagenum_link, 'index.php') ? 'index.php/' : '';
    $format .= $hq_rewrite->using_permalinks() ? user_trailingslashit($hq_rewrite->pagination_base . '/%#%', 'paged') : '?paged=%#%';
    $defaults = array('base' => $pagenum_link, 'format' => $format, 'total' => $total, 'current' => $current, 'show_all' => false, 'prev_next' => true, 'prev_text' => __('&laquo; Previous'), 'next_text' => __('Next &raquo;'), 'end_size' => 1, 'mid_size' => 2, 'type' => 'plain', 'add_args' => array(), 'add_fragment' => '', 'before_page_number' => '', 'after_page_number' => '');
    $args = hq_parse_args($args, $defaults);
    if (!is_array($args['add_args'])) {
        $args['add_args'] = array();
    }
    // Merge additional query vars found in the original URL into 'add_args' array.
    if (isset($url_parts[1])) {
        // Find the format argument.
        $format = explode('?', str_replace('%_%', $args['format'], $args['base']));
        $format_query = isset($format[1]) ? $format[1] : '';
        hq_parse_str($format_query, $format_args);
        // Find the query args of the requested URL.
        hq_parse_str($url_parts[1], $url_query_args);
        // Remove the format argument from the array of query arguments, to avoid overwriting custom format.
        foreach ($format_args as $format_arg => $format_arg_value) {
            unset($url_query_args[$format_arg]);
        }
        $args['add_args'] = array_merge($args['add_args'], urlencode_deep($url_query_args));
    }
    // Who knows what else people pass in $args
    $total = (int) $args['total'];
    if ($total < 2) {
        return;
    }
    $current = (int) $args['current'];
    $end_size = (int) $args['end_size'];
    // Out of bounds?  Make it the default.
    if ($end_size < 1) {
        $end_size = 1;
    }
    $mid_size = (int) $args['mid_size'];
    if ($mid_size < 0) {
        $mid_size = 2;
    }
    $add_args = $args['add_args'];
    $r = '';
    $page_links = array();
    $dots = false;
    if ($args['prev_next'] && $current && 1 < $current) {
        $link = str_replace('%_%', 2 == $current ? '' : $args['format'], $args['base']);
        $link = str_replace('%#%', $current - 1, $link);
        if ($add_args) {
            $link = add_query_arg($add_args, $link);
        }
        $link .= $args['add_fragment'];
        /**
         * Filter the paginated links for the given archive pages.
         *
         * @since 0.0.1
         *
         * @param string $link The paginated link URL.
         */
        $page_links[] = '<a class="prev page-numbers" href="' . esc_url(apply_filters('paginate_links', $link)) . '">' . $args['prev_text'] . '</a>';
    }
    for ($n = 1; $n <= $total; $n++) {
        if ($n == $current) {
            $page_links[] = "<span class='page-numbers current'>" . $args['before_page_number'] . number_format_i18n($n) . $args['after_page_number'] . "</span>";
            $dots = true;
        } else {
            if ($args['show_all'] || ($n <= $end_size || $current && $n >= $current - $mid_size && $n <= $current + $mid_size || $n > $total - $end_size)) {
                $link = str_replace('%_%', 1 == $n ? '' : $args['format'], $args['base']);
                $link = str_replace('%#%', $n, $link);
                if ($add_args) {
                    $link = add_query_arg($add_args, $link);
                }
                $link .= $args['add_fragment'];
                /** This filter is documented in hq-includes/general-template.php */
                $page_links[] = "<a class='page-numbers' href='" . esc_url(apply_filters('paginate_links', $link)) . "'>" . $args['before_page_number'] . number_format_i18n($n) . $args['after_page_number'] . "</a>";
                $dots = true;
            } elseif ($dots && !$args['show_all']) {
                $page_links[] = '<span class="page-numbers dots">' . __('&hellip;') . '</span>';
                $dots = false;
            }
        }
    }
    if ($args['prev_next'] && $current && ($current < $total || -1 == $total)) {
        $link = str_replace('%_%', $args['format'], $args['base']);
        $link = str_replace('%#%', $current + 1, $link);
        if ($add_args) {
            $link = add_query_arg($add_args, $link);
        }
        $link .= $args['add_fragment'];
        /** This filter is documented in hq-includes/general-template.php */
        $page_links[] = '<a class="next page-numbers" href="' . esc_url(apply_filters('paginate_links', $link)) . '">' . $args['next_text'] . '</a>';
    }
    switch ($args['type']) {
        case 'array':
            return $page_links;
        case 'list':
            $r .= "<ul class='page-numbers'>\n\t<li>";
            $r .= join("</li>\n\t<li>", $page_links);
            $r .= "</li>\n</ul>\n";
            break;
        default:
            $r = join("\n", $page_links);
            break;
    }
    return $r;
}
Exemplo n.º 11
0
/**
 * Return all menu items of a navigation menu.
 *
 * @since 0.0.1
 *
 * @global string $_menu_item_sort_prop
 * @staticvar array $fetched
 *
 * @param string $menu Menu name, ID, or slug.
 * @param array  $args Optional. Arguments to pass to {@see get_posts()}.
 * @return false|array $items Array of menu items, otherwise false.
 */
function hq_get_nav_menu_items($menu, $args = array())
{
    $menu = hq_get_nav_menu_object($menu);
    if (!$menu) {
        return false;
    }
    static $fetched = array();
    $items = get_objects_in_term($menu->term_id, 'nav_menu');
    if (is_hq_error($items)) {
        return false;
    }
    $defaults = array('order' => 'ASC', 'orderby' => 'menu_order', 'post_type' => 'nav_menu_item', 'post_status' => 'publish', 'output' => ARRAY_A, 'output_key' => 'menu_order', 'nopaging' => true);
    $args = hq_parse_args($args, $defaults);
    $args['include'] = $items;
    if (!empty($items)) {
        $items = get_posts($args);
    } else {
        $items = array();
    }
    // Get all posts and terms at once to prime the caches
    if (empty($fetched[$menu->term_id]) || hq_using_ext_object_cache()) {
        $fetched[$menu->term_id] = true;
        $posts = array();
        $terms = array();
        foreach ($items as $item) {
            $object_id = get_post_meta($item->ID, '_menu_item_object_id', true);
            $object = get_post_meta($item->ID, '_menu_item_object', true);
            $type = get_post_meta($item->ID, '_menu_item_type', true);
            if ('post_type' == $type) {
                $posts[$object][] = $object_id;
            } elseif ('taxonomy' == $type) {
                $terms[$object][] = $object_id;
            }
        }
        if (!empty($posts)) {
            foreach (array_keys($posts) as $post_type) {
                get_posts(array('post__in' => $posts[$post_type], 'post_type' => $post_type, 'nopaging' => true, 'update_post_term_cache' => false));
            }
        }
        unset($posts);
        if (!empty($terms)) {
            foreach (array_keys($terms) as $taxonomy) {
                get_terms($taxonomy, array('include' => $terms[$taxonomy], 'hierarchical' => false));
            }
        }
        unset($terms);
    }
    $items = array_map('hq_setup_nav_menu_item', $items);
    if (!is_admin()) {
        // Remove invalid items only in frontend
        $items = array_filter($items, '_is_valid_nav_menu_item');
    }
    if (ARRAY_A == $args['output']) {
        $GLOBALS['_menu_item_sort_prop'] = $args['output_key'];
        usort($items, '_sort_nav_menu_items');
        $i = 1;
        foreach ($items as $k => $item) {
            $items[$k]->{$args['output_key']} = $i++;
        }
    }
    /**
     * Filter the navigation menu items being returned.
     *
     * @since 0.0.1
     *
     * @param array  $items An array of menu item post objects.
     * @param object $menu  The menu object.
     * @param array  $args  An array of arguments used to retrieve menu item objects.
     */
    return apply_filters('hq_get_nav_menu_items', $items, $menu, $args);
}
Exemplo n.º 12
0
/**
 * Enqueues all scripts, styles, settings, and templates necessary to use
 * all media JS APIs.
 *
 * @since 0.0.1
 *
 * @global int       $content_width
 * @global hqdb      $hqdb
 * @global HQ_Locale $hq_locale
 *
 * @param array $args {
 *     Arguments for enqueuing media scripts.
 *
 *     @type int|HQ_Post A post object or ID.
 * }
 */
function hq_enqueue_media($args = array())
{
    // Enqueue me just once per page, please.
    if (did_action('hq_enqueue_media')) {
        return;
    }
    global $content_width, $hqdb, $hq_locale;
    $defaults = array('post' => null);
    $args = hq_parse_args($args, $defaults);
    // We're going to pass the old thickbox media tabs to `media_upload_tabs`
    // to ensure plugins will work. We will then unset those tabs.
    $tabs = array('type' => '', 'type_url' => '', 'gallery' => '', 'library' => '');
    /** This filter is documented in hq-admin/includes/media.php */
    $tabs = apply_filters('media_upload_tabs', $tabs);
    unset($tabs['type'], $tabs['type_url'], $tabs['gallery'], $tabs['library']);
    $props = array('link' => get_option('image_default_link_type'), 'align' => get_option('image_default_align'), 'size' => get_option('image_default_size'));
    $exts = array_merge(hq_get_audio_extensions(), hq_get_video_extensions());
    $mimes = get_allowed_mime_types();
    $ext_mimes = array();
    foreach ($exts as $ext) {
        foreach ($mimes as $ext_preg => $mime_match) {
            if (preg_match('#' . $ext . '#i', $ext_preg)) {
                $ext_mimes[$ext] = $mime_match;
                break;
            }
        }
    }
    $has_audio = $hqdb->get_var("\n\t\tSELECT ID\n\t\tFROM {$hqdb->posts}\n\t\tWHERE post_type = 'attachment'\n\t\tAND post_mime_type LIKE 'audio%'\n\t\tLIMIT 1\n\t");
    $has_video = $hqdb->get_var("\n\t\tSELECT ID\n\t\tFROM {$hqdb->posts}\n\t\tWHERE post_type = 'attachment'\n\t\tAND post_mime_type LIKE 'video%'\n\t\tLIMIT 1\n\t");
    $months = $hqdb->get_results($hqdb->prepare("\n\t\tSELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month\n\t\tFROM {$hqdb->posts}\n\t\tWHERE post_type = %s\n\t\tORDER BY post_date DESC\n\t", 'attachment'));
    foreach ($months as $month_year) {
        $month_year->text = sprintf(__('%1$s %2$d'), $hq_locale->get_month($month_year->month), $month_year->year);
    }
    $settings = array('tabs' => $tabs, 'tabUrl' => add_query_arg(array('chromeless' => true), admin_url('media-upload.php')), 'mimeTypes' => hq_list_pluck(get_post_mime_types(), 0), 'captions' => !apply_filters('disable_captions', ''), 'nonce' => array('sendToEditor' => hq_create_nonce('media-send-to-editor')), 'post' => array('id' => 0), 'defaultProps' => $props, 'attachmentCounts' => array('audio' => $has_audio ? 1 : 0, 'video' => $has_video ? 1 : 0), 'embedExts' => $exts, 'embedMimes' => $ext_mimes, 'contentWidth' => $content_width, 'months' => $months, 'mediaTrash' => MEDIA_TRASH ? 1 : 0);
    $post = null;
    if (isset($args['post'])) {
        $post = get_post($args['post']);
        $settings['post'] = array('id' => $post->ID, 'nonce' => hq_create_nonce('update-post_' . $post->ID));
        $thumbnail_support = current_theme_supports('post-thumbnails', $post->post_type) && post_type_supports($post->post_type, 'thumbnail');
        if (!$thumbnail_support && 'attachment' === $post->post_type && $post->post_mime_type) {
            if (hq_attachment_is('audio', $post)) {
                $thumbnail_support = post_type_supports('attachment:audio', 'thumbnail') || current_theme_supports('post-thumbnails', 'attachment:audio');
            } elseif (hq_attachment_is('video', $post)) {
                $thumbnail_support = post_type_supports('attachment:video', 'thumbnail') || current_theme_supports('post-thumbnails', 'attachment:video');
            }
        }
        if ($thumbnail_support) {
            $featured_image_id = get_post_meta($post->ID, '_thumbnail_id', true);
            $settings['post']['featuredImageId'] = $featured_image_id ? $featured_image_id : -1;
        }
    }
    $hier = $post && is_post_type_hierarchical($post->post_type);
    if ($post) {
        $post_type_object = get_post_type_object($post->post_type);
    } else {
        $post_type_object = get_post_type_object('post');
    }
    $strings = array('url' => __('URL'), 'addMedia' => __('Add Media'), 'search' => __('Search'), 'select' => __('Select'), 'cancel' => __('Cancel'), 'update' => __('Update'), 'replace' => __('Replace'), 'remove' => __('Remove'), 'back' => __('Back'), 'selected' => __('%d selected'), 'dragInfo' => __('Drag and drop to reorder media files.'), 'uploadFilesTitle' => __('Upload Files'), 'uploadImagesTitle' => __('Upload Images'), 'mediaLibraryTitle' => __('Media Library'), 'insertMediaTitle' => __('Insert Media'), 'createNewGallery' => __('Create a new gallery'), 'createNewPlaylist' => __('Create a new playlist'), 'createNewVideoPlaylist' => __('Create a new video playlist'), 'returnToLibrary' => __('&#8592; Return to library'), 'allMediaItems' => __('All media items'), 'allDates' => __('All dates'), 'noItemsFound' => __('No items found.'), 'insertIntoPost' => $hier ? __('Insert into page') : __('Insert into post'), 'unattached' => __('Unattached'), 'trash' => _x('Trash', 'noun'), 'uploadedToThisPost' => $hier ? __('Uploaded to this page') : __('Uploaded to this post'), 'warnDelete' => __("You are about to permanently delete this item.\n  'Cancel' to stop, 'OK' to delete."), 'warnBulkDelete' => __("You are about to permanently delete these items.\n  'Cancel' to stop, 'OK' to delete."), 'warnBulkTrash' => __("You are about to trash these items.\n  'Cancel' to stop, 'OK' to delete."), 'bulkSelect' => __('Bulk Select'), 'cancelSelection' => __('Cancel Selection'), 'trashSelected' => __('Trash Selected'), 'untrashSelected' => __('Untrash Selected'), 'deleteSelected' => __('Delete Selected'), 'deletePermanently' => __('Delete Permanently'), 'apply' => __('Apply'), 'filterByDate' => __('Filter by date'), 'filterByType' => __('Filter by type'), 'searchMediaLabel' => __('Search Media'), 'noMedia' => __('No media attachments found.'), 'attachmentDetails' => __('Attachment Details'), 'insertFromUrlTitle' => __('Insert from URL'), 'setFeaturedImageTitle' => $post_type_object->labels->featured_image, 'setFeaturedImage' => $post_type_object->labels->set_featured_image, 'createGalleryTitle' => __('Create Gallery'), 'editGalleryTitle' => __('Edit Gallery'), 'cancelGalleryTitle' => __('&#8592; Cancel Gallery'), 'insertGallery' => __('Insert gallery'), 'updateGallery' => __('Update gallery'), 'addToGallery' => __('Add to gallery'), 'addToGalleryTitle' => __('Add to Gallery'), 'reverseOrder' => __('Reverse order'), 'imageDetailsTitle' => __('Image Details'), 'imageReplaceTitle' => __('Replace Image'), 'imageDetailsCancel' => __('Cancel Edit'), 'editImage' => __('Edit Image'), 'chooseImage' => __('Choose Image'), 'selectAndCrop' => __('Select and Crop'), 'skipCropping' => __('Skip Cropping'), 'cropImage' => __('Crop Image'), 'cropYourImage' => __('Crop your image'), 'cropping' => __('Cropping&hellip;'), 'suggestedDimensions' => __('Suggested image dimensions:'), 'cropError' => __('There has been an error cropping your image.'), 'audioDetailsTitle' => __('Audio Details'), 'audioReplaceTitle' => __('Replace Audio'), 'audioAddSourceTitle' => __('Add Audio Source'), 'audioDetailsCancel' => __('Cancel Edit'), 'videoDetailsTitle' => __('Video Details'), 'videoReplaceTitle' => __('Replace Video'), 'videoAddSourceTitle' => __('Add Video Source'), 'videoDetailsCancel' => __('Cancel Edit'), 'videoSelectPosterImageTitle' => __('Select Poster Image'), 'videoAddTrackTitle' => __('Add Subtitles'), 'playlistDragInfo' => __('Drag and drop to reorder tracks.'), 'createPlaylistTitle' => __('Create Audio Playlist'), 'editPlaylistTitle' => __('Edit Audio Playlist'), 'cancelPlaylistTitle' => __('&#8592; Cancel Audio Playlist'), 'insertPlaylist' => __('Insert audio playlist'), 'updatePlaylist' => __('Update audio playlist'), 'addToPlaylist' => __('Add to audio playlist'), 'addToPlaylistTitle' => __('Add to Audio Playlist'), 'videoPlaylistDragInfo' => __('Drag and drop to reorder videos.'), 'createVideoPlaylistTitle' => __('Create Video Playlist'), 'editVideoPlaylistTitle' => __('Edit Video Playlist'), 'cancelVideoPlaylistTitle' => __('&#8592; Cancel Video Playlist'), 'insertVideoPlaylist' => __('Insert video playlist'), 'updateVideoPlaylist' => __('Update video playlist'), 'addToVideoPlaylist' => __('Add to video playlist'), 'addToVideoPlaylistTitle' => __('Add to Video Playlist'));
    /**
     * Filter the media view settings.
     *
     * @since 0.0.1
     *
     * @param array   $settings List of media view settings.
     * @param HQ_Post $post     Post object.
     */
    $settings = apply_filters('media_view_settings', $settings, $post);
    /**
     * Filter the media view strings.
     *
     * @since 0.0.1
     *
     * @param array   $strings List of media view strings.
     * @param HQ_Post $post    Post object.
     */
    $strings = apply_filters('media_view_strings', $strings, $post);
    $strings['settings'] = $settings;
    // Ensure we enqueue media-editor first, that way media-views is
    // registered internally before we try to localize it. see #24724.
    hq_enqueue_script('media-editor');
    hq_localize_script('media-views', '_hqMediaViewsL10n', $strings);
    hq_enqueue_script('media-audiovideo');
    hq_enqueue_style('media-views');
    if (is_admin()) {
        hq_enqueue_script('mce-view');
        hq_enqueue_script('image-edit');
    }
    hq_enqueue_style('imgareaselect');
    hq_plupload_default_settings();
    require_once ABSPATH . HQINC . '/media-template.php';
    add_action('admin_footer', 'hq_print_media_templates');
    add_action('hq_footer', 'hq_print_media_templates');
    add_action('customize_controls_print_footer_scripts', 'hq_print_media_templates');
    /**
     * Fires at the conclusion of hq_enqueue_media().
     *
     * @since 0.0.1
     */
    do_action('hq_enqueue_media');
}
Exemplo n.º 13
0
/**
 * Insert an attachment.
 *
 * If you set the 'ID' in the $args parameter, it will mean that you are
 * updating and attempt to update the attachment. You can also set the
 * attachment name or title by setting the key 'post_name' or 'post_title'.
 *
 * You can set the dates for the attachment manually by setting the 'post_date'
 * and 'post_date_gmt' keys' values.
 *
 * By default, the comments will use the default settings for whether the
 * comments are allowed. You can close them manually or keep them open by
 * setting the value for the 'comment_status' key.
 *
 * @since 0.0.1
 *
 * @see hq_insert_post()
 *
 * @param string|array $args   Arguments for inserting an attachment.
 * @param string       $file   Optional. Filename.
 * @param int          $parent Optional. Parent post ID.
 * @return int Attachment ID.
 */
function hq_insert_attachment($args, $file = false, $parent = 0)
{
    $defaults = array('file' => $file, 'post_parent' => 0);
    $data = hq_parse_args($args, $defaults);
    if (!empty($parent)) {
        $data['post_parent'] = $parent;
    }
    $data['post_type'] = 'attachment';
    return hq_insert_post($data);
}
Exemplo n.º 14
0
    /**
     * @param array $instance
     */
    public function form($instance)
    {
        //Defaults
        $instance = hq_parse_args((array) $instance, array('title' => ''));
        $title = esc_attr($instance['title']);
        $count = isset($instance['count']) ? (bool) $instance['count'] : false;
        $hierarchical = isset($instance['hierarchical']) ? (bool) $instance['hierarchical'] : false;
        $dropdown = isset($instance['dropdown']) ? (bool) $instance['dropdown'] : false;
        ?>
		<p><label for="<?php 
        echo $this->get_field_id('title');
        ?>
"><?php 
        _e('Title:');
        ?>
</label>
		<input class="widefat" id="<?php 
        echo $this->get_field_id('title');
        ?>
" name="<?php 
        echo $this->get_field_name('title');
        ?>
" type="text" value="<?php 
        echo $title;
        ?>
" /></p>

		<p><input type="checkbox" class="checkbox" id="<?php 
        echo $this->get_field_id('dropdown');
        ?>
" name="<?php 
        echo $this->get_field_name('dropdown');
        ?>
"<?php 
        checked($dropdown);
        ?>
 />
		<label for="<?php 
        echo $this->get_field_id('dropdown');
        ?>
"><?php 
        _e('Display as dropdown');
        ?>
</label><br />

		<input type="checkbox" class="checkbox" id="<?php 
        echo $this->get_field_id('count');
        ?>
" name="<?php 
        echo $this->get_field_name('count');
        ?>
"<?php 
        checked($count);
        ?>
 />
		<label for="<?php 
        echo $this->get_field_id('count');
        ?>
"><?php 
        _e('Show post counts');
        ?>
</label><br />

		<input type="checkbox" class="checkbox" id="<?php 
        echo $this->get_field_id('hierarchical');
        ?>
" name="<?php 
        echo $this->get_field_name('hierarchical');
        ?>
"<?php 
        checked($hierarchical);
        ?>
 />
		<label for="<?php 
        echo $this->get_field_id('hierarchical');
        ?>
"><?php 
        _e('Show hierarchy');
        ?>
</label></p>
<?php 
    }
Exemplo n.º 15
0
/**
 * Determines if there is an HTTP Transport that can process this request.
 *
 * @since 0.0.1
 *
 * @param array  $capabilities Array of capabilities to test or a hq_remote_request() $args array.
 * @param string $url          Optional. If given, will check if the URL requires SSL and adds
 *                             that requirement to the capabilities array.
 *
 * @return bool
 */
function hq_http_supports($capabilities = array(), $url = null)
{
    $http = _hq_http_get_object();
    $capabilities = hq_parse_args($capabilities);
    $count = count($capabilities);
    // If we have a numeric $capabilities array, spoof a hq_remote_request() associative $args array
    if ($count && count(array_filter(array_keys($capabilities), 'is_numeric')) == $count) {
        $capabilities = array_combine(array_values($capabilities), array_fill(0, $count, true));
    }
    if ($url && !isset($capabilities['ssl'])) {
        $scheme = parse_url($url, PHP_URL_SCHEME);
        if ('https' == $scheme || 'ssl' == $scheme) {
            $capabilities['ssl'] = true;
        }
    }
    return (bool) $http->_get_first_available_transport($capabilities);
}
Exemplo n.º 16
0
/**
 * Retrieve default data about the avatar.
 *
 * @since 0.0.1
 *
 * @param mixed $id_or_email The Gravatar to check the data against. Accepts a user_id, gravatar md5 hash,
 *                           user email, HQ_User object, HQ_Post object, or comment object.
 * @param array $args {
 *     Optional. Arguments to return instead of the default arguments.
 *
 *     @type int    $size           Height and width of the avatar image file in pixels. Default 96.
 *     @type int    $height         Display height of the avatar in pixels. Defaults to $size.
 *     @type int    $width          Display width of the avatar in pixels. Defaults to $size.
 *     @type string $default        URL for the default image or a default type. Accepts '404' (return
 *                                  a 404 instead of a default image), 'retro' (8bit), 'monsterid' (monster),
 *                                  'wavatar' (cartoon face), 'indenticon' (the "quilt"), 'mystery', 'mm',
 *                                  or 'mysterman' (The Oyster Man), 'blank' (transparent GIF), or
 *                                  'gravatar_default' (the Gravatar logo). Default is the value of the
 *                                  'avatar_default' option, with a fallback of 'mystery'.
 *     @type bool   $force_default  Whether to always show the default image, never the Gravatar. Default false.
 *     @type string $rating         What rating to display avatars up to. Accepts 'G', 'PG', 'R', 'X', and are
 *                                  judged in that order. Default is the value of the 'avatar_rating' option.
 *     @type string $scheme         URL scheme to use. See set_url_scheme() for accepted values.
 *                                  Default null.
 *     @type array  $processed_args When the function returns, the value will be the processed/sanitized $args
 *                                  plus a "found_avatar" guess. Pass as a reference. Default null.
 *     @type string $extra_attr     HTML attributes to insert in the IMG element. Is not sanitized. Default empty.
 * }
 * @return array $processed_args {
 *     Along with the arguments passed in `$args`, this will contain a couple of extra arguments.
 *
 *     @type bool   $found_avatar True if we were able to find an avatar for this user,
 *                                false or not set if we couldn't.
 *     @type string $url          The URL of the avatar we found.
 * }
 */
function get_avatar_data($id_or_email, $args = null)
{
    $args = hq_parse_args($args, array('size' => 96, 'height' => null, 'width' => null, 'default' => get_option('avatar_default', 'mystery'), 'force_default' => false, 'rating' => get_option('avatar_rating'), 'scheme' => null, 'processed_args' => null, 'extra_attr' => ''));
    if (is_numeric($args['size'])) {
        $args['size'] = absint($args['size']);
        if (!$args['size']) {
            $args['size'] = 96;
        }
    } else {
        $args['size'] = 96;
    }
    if (is_numeric($args['height'])) {
        $args['height'] = absint($args['height']);
        if (!$args['height']) {
            $args['height'] = $args['size'];
        }
    } else {
        $args['height'] = $args['size'];
    }
    if (is_numeric($args['width'])) {
        $args['width'] = absint($args['width']);
        if (!$args['width']) {
            $args['width'] = $args['size'];
        }
    } else {
        $args['width'] = $args['size'];
    }
    if (empty($args['default'])) {
        $args['default'] = get_option('avatar_default', 'mystery');
    }
    switch ($args['default']) {
        case 'mm':
        case 'mystery':
        case 'mysteryman':
            $args['default'] = 'mm';
            break;
        case 'gravatar_default':
            $args['default'] = false;
            break;
    }
    $args['force_default'] = (bool) $args['force_default'];
    $args['rating'] = strtolower($args['rating']);
    $args['found_avatar'] = false;
    /**
     * Filter whether to retrieve the avatar URL early.
     *
     * Passing a non-null value in the 'url' member of the return array will
     * effectively short circuit get_avatar_data(), passing the value through
     * the {@see 'get_avatar_data'} filter and returning early.
     *
     * @since 0.0.1
     *
     * @param array             $args          Arguments passed to get_avatar_data(), after processing.
     * @param int|object|string $id_or_email   A user ID, email address, or comment object.
     */
    $args = apply_filters('pre_get_avatar_data', $args, $id_or_email);
    if (isset($args['url']) && !is_null($args['url'])) {
        /** This filter is documented in hq-includes/link-template.php */
        return apply_filters('get_avatar_data', $args, $id_or_email);
    }
    $email_hash = '';
    $user = $email = false;
    // Process the user identifier.
    if (is_numeric($id_or_email)) {
        $user = get_user_by('id', absint($id_or_email));
    } elseif (is_string($id_or_email)) {
        if (strpos($id_or_email, '@md5.gravatar.com')) {
            // md5 hash
            list($email_hash) = explode('@', $id_or_email);
        } else {
            // email address
            $email = $id_or_email;
        }
    } elseif ($id_or_email instanceof HQ_User) {
        // User Object
        $user = $id_or_email;
    } elseif ($id_or_email instanceof HQ_Post) {
        // Post Object
        $user = get_user_by('id', (int) $id_or_email->post_author);
    } elseif (is_object($id_or_email) && isset($id_or_email->comment_ID)) {
        // Comment Object
        /**
         * Filter the list of allowed comment types for retrieving avatars.
         *
         * @since 0.0.1
         *
         * @param array $types An array of content types. Default only contains 'comment'.
         */
        $allowed_comment_types = apply_filters('get_avatar_comment_types', array('comment'));
        if (!empty($id_or_email->comment_type) && !in_array($id_or_email->comment_type, (array) $allowed_comment_types)) {
            $args['url'] = false;
            /** This filter is documented in hq-includes/link-template.php */
            return apply_filters('get_avatar_data', $args, $id_or_email);
        }
        if (!empty($id_or_email->user_id)) {
            $user = get_user_by('id', (int) $id_or_email->user_id);
        }
        if ((!$user || is_hq_error($user)) && !empty($id_or_email->comment_author_email)) {
            $email = $id_or_email->comment_author_email;
        }
    }
    if (!$email_hash) {
        if ($user) {
            $email = $user->user_email;
        }
        if ($email) {
            $email_hash = md5(strtolower(trim($email)));
        }
    }
    if ($email_hash) {
        $args['found_avatar'] = true;
        $gravatar_server = hexdec($email_hash[0]) % 3;
    } else {
        $gravatar_server = rand(0, 2);
    }
    $url_args = array('s' => $args['size'], 'd' => $args['default'], 'f' => $args['force_default'] ? 'y' : false, 'r' => $args['rating']);
    if (is_ssl()) {
        $url = 'https://secure.gravatar.com/avatar/' . $email_hash;
    } else {
        $url = sprintf('http://%d.gravatar.com/avatar/%s', $gravatar_server, $email_hash);
    }
    $url = add_query_arg(rawurlencode_deep(array_filter($url_args)), set_url_scheme($url, $args['scheme']));
    /**
     * Filter the avatar URL.
     *
     * @since 0.0.1
     *
     * @param string            $url         The URL of the avatar.
     * @param int|object|string $id_or_email A user ID, email address, or comment object.
     * @param array             $args        Arguments passed to get_avatar_data(), after processing.
     */
    $args['url'] = apply_filters('get_avatar_url', $url, $id_or_email, $args);
    /**
     * Filter the avatar data.
     *
     * @since 0.0.1
     *
     * @param array             $args        Arguments passed to get_avatar_data(), after processing.
     * @param int|object|string $id_or_email A user ID, email address, or comment object.
     */
    return apply_filters('get_avatar_data', $args, $id_or_email);
}
Exemplo n.º 17
0
/**
 * Output a HTML element with a star rating for a given rating.
 *
 * Outputs a HTML element with the star rating exposed on a 0..5 scale in
 * half star increments (ie. 1, 1.5, 2 stars). Optionally, if specified, the
 * number of ratings may also be displayed by passing the $number parameter.
 *
 * @since 0.0.1
 * @param array $args {
 *     Optional. Array of star ratings arguments.
 *
 *     @type int    $rating The rating to display, expressed in either a 0.5 rating increment,
 *                          or percentage. Default 0.
 *     @type string $type   Format that the $rating is in. Valid values are 'rating' (default),
 *                          or, 'percent'. Default 'rating'.
 *     @type int    $number The number of ratings that makes up this rating. Default 0.
 * }
 */
function hq_star_rating($args = array())
{
    $defaults = array('rating' => 0, 'type' => 'rating', 'number' => 0);
    $r = hq_parse_args($args, $defaults);
    // Non-english decimal places when the $rating is coming from a string
    $rating = str_replace(',', '.', $r['rating']);
    // Convert Percentage to star rating, 0..5 in .5 increments
    if ('percent' == $r['type']) {
        $rating = round($rating / 10, 0) / 2;
    }
    // Calculate the number of each type of star needed
    $full_stars = floor($rating);
    $half_stars = ceil($rating - $full_stars);
    $empty_stars = 5 - $full_stars - $half_stars;
    if ($r['number']) {
        /* translators: 1: The rating, 2: The number of ratings */
        $format = _n('%1$s rating based on %2$s rating', '%1$s rating based on %2$s ratings', $r['number']);
        $title = sprintf($format, number_format_i18n($rating, 1), number_format_i18n($r['number']));
    } else {
        /* translators: 1: The rating */
        $title = sprintf(__('%s rating'), number_format_i18n($rating, 1));
    }
    echo '<div class="star-rating" title="' . esc_attr($title) . '">';
    echo '<span class="screen-reader-text">' . $title . '</span>';
    echo str_repeat('<div class="star star-full"></div>', $full_stars);
    echo str_repeat('<div class="star star-half"></div>', $half_stars);
    echo str_repeat('<div class="star star-empty"></div>', $empty_stars);
    echo '</div>';
}
Exemplo n.º 18
0
 /**
  * Sets up the HiveQueen query for retrieving comments.
  *
  * @since 0.0.1
  * @since 0.0.1
  *              'post_author__not_in', 'author__in', 'author__not_in', 'post__in',
  *              'post__not_in', 'include_unapproved', 'type__in', and 'type__not_in'
  *              arguments to $query_vars.
  * @since 0.0.1
  * @access public
  *
  * @param string|array $query Array or URL query string of parameters.
  * @return array|int List of comments, or number of comments when 'count' is passed as a query var.
  */
 public function query($query)
 {
     $this->query_vars = hq_parse_args($query);
     return $this->get_comments();
 }
Exemplo n.º 19
0
/**
 * Displays a navigation menu.
 *
 * @since 0.0.1
 *
 * @staticvar array $menu_id_slugs
 *
 * @param array $args {
 *     Optional. Array of nav menu arguments.
 *
 *     @type string        $menu            Desired menu. Accepts (matching in order) id, slug, name. Default empty.
 *     @type string        $menu_class      CSS class to use for the ul element which forms the menu. Default 'menu'.
 *     @type string        $menu_id         The ID that is applied to the ul element which forms the menu.
 *                                          Default is the menu slug, incremented.
 *     @type string        $container       Whether to wrap the ul, and what to wrap it with. Default 'div'.
 *     @type string        $container_class Class that is applied to the container. Default 'menu-{menu slug}-container'.
 *     @type string        $container_id    The ID that is applied to the container. Default empty.
 *     @type callback|bool $fallback_cb     If the menu doesn't exists, a callback function will fire.
 *                                          Default is 'hq_page_menu'. Set to false for no fallback.
 *     @type string        $before          Text before the link text. Default empty.
 *     @type string        $after           Text after the link text. Default empty.
 *     @type string        $link_before     Text before the link. Default empty.
 *     @type string        $link_after      Text after the link. Default empty.
 *     @type bool          $echo            Whether to echo the menu or return it. Default true.
 *     @type int           $depth           How many levels of the hierarchy are to be included. 0 means all. Default 0.
 *     @type object        $walker          Instance of a custom walker class. Default empty.
 *     @type string        $theme_location  Theme location to be used. Must be registered with register_nav_menu()
 *                                          in order to be selectable by the user.
 *     @type string        $items_wrap      How the list items should be wrapped. Default is a ul with an id and class.
 *                                          Uses printf() format with numbered placeholders.
 * }
 * @return object|false|void Menu output if $echo is false, false if there are no items or no menu was found.
 */
function hq_nav_menu($args = array())
{
    static $menu_id_slugs = array();
    $defaults = array('menu' => '', 'container' => 'div', 'container_class' => '', 'container_id' => '', 'menu_class' => 'menu', 'menu_id' => '', 'echo' => true, 'fallback_cb' => 'hq_page_menu', 'before' => '', 'after' => '', 'link_before' => '', 'link_after' => '', 'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>', 'depth' => 0, 'walker' => '', 'theme_location' => '');
    $args = hq_parse_args($args, $defaults);
    /**
     * Filter the arguments used to display a navigation menu.
     *
     * @since 0.0.1
     *
     * @see hq_nav_menu()
     *
     * @param array $args Array of hq_nav_menu() arguments.
     */
    $args = apply_filters('hq_nav_menu_args', $args);
    $args = (object) $args;
    /**
     * Filter whether to short-circuit the hq_nav_menu() output.
     *
     * Returning a non-null value to the filter will short-circuit
     * hq_nav_menu(), echoing that value if $args->echo is true,
     * returning that value otherwise.
     *
     * @since 0.0.1
     *
     * @see hq_nav_menu()
     *
     * @param string|null $output Nav menu output to short-circuit with. Default null.
     * @param object      $args   An object containing hq_nav_menu() arguments.
     */
    $nav_menu = apply_filters('pre_hq_nav_menu', null, $args);
    if (null !== $nav_menu) {
        if ($args->echo) {
            echo $nav_menu;
            return;
        }
        return $nav_menu;
    }
    // Get the nav menu based on the requested menu
    $menu = hq_get_nav_menu_object($args->menu);
    // Get the nav menu based on the theme_location
    if (!$menu && $args->theme_location && ($locations = get_nav_menu_locations()) && isset($locations[$args->theme_location])) {
        $menu = hq_get_nav_menu_object($locations[$args->theme_location]);
    }
    // get the first menu that has items if we still can't find a menu
    if (!$menu && !$args->theme_location) {
        $menus = hq_get_nav_menus();
        foreach ($menus as $menu_maybe) {
            if ($menu_items = hq_get_nav_menu_items($menu_maybe->term_id, array('update_post_term_cache' => false))) {
                $menu = $menu_maybe;
                break;
            }
        }
    }
    if (empty($args->menu)) {
        $args->menu = $menu;
    }
    // If the menu exists, get its items.
    if ($menu && !is_hq_error($menu) && !isset($menu_items)) {
        $menu_items = hq_get_nav_menu_items($menu->term_id, array('update_post_term_cache' => false));
    }
    /*
     * If no menu was found:
     *  - Fall back (if one was specified), or bail.
     *
     * If no menu items were found:
     *  - Fall back, but only if no theme location was specified.
     *  - Otherwise, bail.
     */
    if ((!$menu || is_hq_error($menu) || isset($menu_items) && empty($menu_items) && !$args->theme_location) && isset($args->fallback_cb) && $args->fallback_cb && is_callable($args->fallback_cb)) {
        return call_user_func($args->fallback_cb, (array) $args);
    }
    if (!$menu || is_hq_error($menu)) {
        return false;
    }
    $nav_menu = $items = '';
    $show_container = false;
    if ($args->container) {
        /**
         * Filter the list of HTML tags that are valid for use as menu containers.
         *
         * @since 0.0.1
         *
         * @param array $tags The acceptable HTML tags for use as menu containers.
         *                    Default is array containing 'div' and 'nav'.
         */
        $allowed_tags = apply_filters('hq_nav_menu_container_allowedtags', array('div', 'nav'));
        if (in_array($args->container, $allowed_tags)) {
            $show_container = true;
            $class = $args->container_class ? ' class="' . esc_attr($args->container_class) . '"' : ' class="menu-' . $menu->slug . '-container"';
            $id = $args->container_id ? ' id="' . esc_attr($args->container_id) . '"' : '';
            $nav_menu .= '<' . $args->container . $id . $class . '>';
        }
    }
    // Set up the $menu_item variables
    _hq_menu_item_classes_by_context($menu_items);
    $sorted_menu_items = $menu_items_with_children = array();
    foreach ((array) $menu_items as $menu_item) {
        $sorted_menu_items[$menu_item->menu_order] = $menu_item;
        if ($menu_item->menu_item_parent) {
            $menu_items_with_children[$menu_item->menu_item_parent] = true;
        }
    }
    // Add the menu-item-has-children class where applicable
    if ($menu_items_with_children) {
        foreach ($sorted_menu_items as &$menu_item) {
            if (isset($menu_items_with_children[$menu_item->ID])) {
                $menu_item->classes[] = 'menu-item-has-children';
            }
        }
    }
    unset($menu_items, $menu_item);
    /**
     * Filter the sorted list of menu item objects before generating the menu's HTML.
     *
     * @since 0.0.1
     *
     * @param array  $sorted_menu_items The menu items, sorted by each menu item's menu order.
     * @param object $args              An object containing hq_nav_menu() arguments.
     */
    $sorted_menu_items = apply_filters('hq_nav_menu_objects', $sorted_menu_items, $args);
    $items .= walk_nav_menu_tree($sorted_menu_items, $args->depth, $args);
    unset($sorted_menu_items);
    // Attributes
    if (!empty($args->menu_id)) {
        $wrap_id = $args->menu_id;
    } else {
        $wrap_id = 'menu-' . $menu->slug;
        while (in_array($wrap_id, $menu_id_slugs)) {
            if (preg_match('#-(\\d+)$#', $wrap_id, $matches)) {
                $wrap_id = preg_replace('#-(\\d+)$#', '-' . ++$matches[1], $wrap_id);
            } else {
                $wrap_id = $wrap_id . '-1';
            }
        }
    }
    $menu_id_slugs[] = $wrap_id;
    $wrap_class = $args->menu_class ? $args->menu_class : '';
    /**
     * Filter the HTML list content for navigation menus.
     *
     * @since 0.0.1
     *
     * @see hq_nav_menu()
     *
     * @param string $items The HTML list content for the menu items.
     * @param object $args  An object containing hq_nav_menu() arguments.
     */
    $items = apply_filters('hq_nav_menu_items', $items, $args);
    /**
     * Filter the HTML list content for a specific navigation menu.
     *
     * @since 0.0.1
     *
     * @see hq_nav_menu()
     *
     * @param string $items The HTML list content for the menu items.
     * @param object $args  An object containing hq_nav_menu() arguments.
     */
    $items = apply_filters("hq_nav_menu_{$menu->slug}_items", $items, $args);
    // Don't print any markup if there are no items at this point.
    if (empty($items)) {
        return false;
    }
    $nav_menu .= sprintf($args->items_wrap, esc_attr($wrap_id), esc_attr($wrap_class), $items);
    unset($items);
    if ($show_container) {
        $nav_menu .= '</' . $args->container . '>';
    }
    /**
     * Filter the HTML content for navigation menus.
     *
     * @since 0.0.1
     *
     * @see hq_nav_menu()
     *
     * @param string $nav_menu The HTML content for the navigation menu.
     * @param object $args     An object containing hq_nav_menu() arguments.
     */
    $nav_menu = apply_filters('hq_nav_menu', $nav_menu, $args);
    if ($args->echo) {
        echo $nav_menu;
    } else {
        return $nav_menu;
    }
}