/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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)); }
/** * 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(); }
/** * 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; }
/** * 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; }
/** * 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' => __('« Previous'), 'next_text' => __('Next »'), '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">' . __('…') . '</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; }
/** * 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); }
/** * 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' => __('← 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' => __('← 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…'), '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' => __('← 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' => __('← 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'); }
/** * 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); }
/** * @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 }
/** * 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); }
/** * 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); }
/** * 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>'; }
/** * 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(); }
/** * 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; } }