/** * Register importer for HiveQueen. * * @since 0.0.1 * * @global array $hq_importers * * @param string $id Importer tag. Used to uniquely identify importer. * @param string $name Importer name and title. * @param string $description Importer description. * @param callback $callback Callback to run. * @return HQ_Error Returns HQ_Error when $callback is HQ_Error. */ function register_importer($id, $name, $description, $callback) { global $hq_importers; if (is_hq_error($callback)) { return $callback; } $hq_importers[$id] = array($name, $description, $callback); }
/** * Sanitises various option values based on the nature of the option. * * This is basically a switch statement which will pass $value through a number * of functions depending on the $option. * * @since 0.0.1 * * @global hqdb $hqdb * * @param string $option The name of the option. * @param string $value The unsanitised value. * @return string Sanitized value. */ function sanitize_option($option, $value) { global $hqdb; $original_value = $value; $error = ''; switch ($option) { case 'admin_email': case 'new_admin_email': $value = $hqdb->strip_invalid_text_for_column($hqdb->options, 'option_value', $value); if (is_hq_error($value)) { $error = $value->get_error_message(); } else { $value = sanitize_email($value); if (!is_email($value)) { $error = __('The email address entered did not appear to be a valid email address. Please enter a valid email address.'); } } break; case 'thumbnail_size_w': case 'thumbnail_size_h': case 'medium_size_w': case 'medium_size_h': case 'large_size_w': case 'large_size_h': case 'mailserver_port': case 'comment_max_links': case 'page_on_front': case 'page_for_posts': case 'rss_excerpt_length': case 'default_category': case 'default_email_category': case 'default_link_category': case 'close_comments_days_old': case 'comments_per_page': case 'thread_comments_depth': case 'users_can_register': case 'start_of_week': case 'site_icon': $value = absint($value); break; case 'posts_per_page': case 'posts_per_rss': $value = (int) $value; if (empty($value)) { $value = 1; } if ($value < -1) { $value = abs($value); } break; case 'default_ping_status': case 'default_comment_status': // Options that if not there have 0 value but need to be something like "closed" if ($value == '0' || $value == '') { $value = 'closed'; } break; case 'blogdescription': case 'blogname': $value = $hqdb->strip_invalid_text_for_column($hqdb->options, 'option_value', $value); if (is_hq_error($value)) { $error = $value->get_error_message(); } else { $value = hq_kses_post($value); $value = esc_html($value); } break; case 'blog_charset': $value = preg_replace('/[^a-zA-Z0-9_-]/', '', $value); // strips slashes break; case 'blog_public': // This is the value if the settings checkbox is not checked on POST. Don't rely on this. if (null === $value) { $value = 1; } else { $value = intval($value); } break; case 'date_format': case 'time_format': case 'mailserver_url': case 'mailserver_login': case 'mailserver_pass': case 'upload_path': $value = $hqdb->strip_invalid_text_for_column($hqdb->options, 'option_value', $value); if (is_hq_error($value)) { $error = $value->get_error_message(); } else { $value = strip_tags($value); $value = hq_kses_data($value); } break; case 'ping_sites': $value = explode("\n", $value); $value = array_filter(array_map('trim', $value)); $value = array_filter(array_map('esc_url_raw', $value)); $value = implode("\n", $value); break; case 'gmt_offset': $value = preg_replace('/[^0-9:.-]/', '', $value); // strips slashes break; case 'siteurl': $value = $hqdb->strip_invalid_text_for_column($hqdb->options, 'option_value', $value); if (is_hq_error($value)) { $error = $value->get_error_message(); } else { if (preg_match('#http(s?)://(.+)#i', $value)) { $value = esc_url_raw($value); } else { $error = __('The HiveQueen address you entered did not appear to be a valid URL. Please enter a valid URL.'); } } break; case 'home': $value = $hqdb->strip_invalid_text_for_column($hqdb->options, 'option_value', $value); if (is_hq_error($value)) { $error = $value->get_error_message(); } else { if (preg_match('#http(s?)://(.+)#i', $value)) { $value = esc_url_raw($value); } else { $error = __('The Site address you entered did not appear to be a valid URL. Please enter a valid URL.'); } } break; case 'HQLANG': $allowed = get_available_languages(); //TODO: Goyo no multisite //if ( ! is_multisite() && defined( 'HQLANG' ) && '' !== HQLANG && 'en_US' !== HQLANG ) { if (defined('HQLANG') && '' !== HQLANG && 'en_US' !== HQLANG) { $allowed[] = HQLANG; } if (!in_array($value, $allowed) && !empty($value)) { $value = get_option($option); } break; case 'illegal_names': $value = $hqdb->strip_invalid_text_for_column($hqdb->options, 'option_value', $value); if (is_hq_error($value)) { $error = $value->get_error_message(); } else { if (!is_array($value)) { $value = explode(' ', $value); } $value = array_values(array_filter(array_map('trim', $value))); if (!$value) { $value = ''; } } break; case 'limited_email_domains': case 'banned_email_domains': $value = $hqdb->strip_invalid_text_for_column($hqdb->options, 'option_value', $value); if (is_hq_error($value)) { $error = $value->get_error_message(); } else { if (!is_array($value)) { $value = explode("\n", $value); } $domains = array_values(array_filter(array_map('trim', $value))); $value = array(); foreach ($domains as $domain) { if (!preg_match('/(--|\\.\\.)/', $domain) && preg_match('|^([a-zA-Z0-9-\\.])+$|', $domain)) { $value[] = $domain; } } if (!$value) { $value = ''; } } break; case 'timezone_string': $allowed_zones = timezone_identifiers_list(); if (!in_array($value, $allowed_zones) && !empty($value)) { $error = __('The timezone you have entered is not valid. Please select a valid timezone.'); } break; case 'permalink_structure': case 'category_base': case 'tag_base': $value = $hqdb->strip_invalid_text_for_column($hqdb->options, 'option_value', $value); if (is_hq_error($value)) { $error = $value->get_error_message(); } else { $value = esc_url_raw($value); $value = str_replace('http://', '', $value); } break; case 'default_role': if (!get_role($value) && get_role('subscriber')) { $value = 'subscriber'; } break; case 'moderation_keys': case 'blacklist_keys': $value = $hqdb->strip_invalid_text_for_column($hqdb->options, 'option_value', $value); if (is_hq_error($value)) { $error = $value->get_error_message(); } else { $value = explode("\n", $value); $value = array_filter(array_map('trim', $value)); $value = array_unique($value); $value = implode("\n", $value); } break; } if (!empty($error)) { $value = get_option($option); if (function_exists('add_settings_error')) { add_settings_error($option, "invalid_{$option}", $error); } } /** * Filter an option value following sanitization. * * @since 0.0.1 * @since 0.0.1 * * @param string $value The sanitized option value. * @param string $option The option name. * @param string $original_value The original value passed to the function. */ return apply_filters("sanitize_option_{$option}", $value, $option, $original_value); }
/** * Populate network settings. * * @since 0.0.1 * * @global hqdb $hqdb * @global object $current_site * @global int $hq_db_version * @global HQ_Rewrite $hq_rewrite * * @param int $network_id ID of network to populate. * @return bool|HQ_Error True on success, or HQ_Error on warning (with the install otherwise successful, * so the error code must be checked) or failure. */ function populate_network($network_id = 1, $domain = '', $email = '', $site_name = '', $path = '/', $subdomain_install = false) { global $hqdb, $current_site, $hq_db_version, $hq_rewrite; $errors = new HQ_Error(); if ('' == $domain) { $errors->add('empty_domain', __('You must provide a domain name.')); } if ('' == $site_name) { $errors->add('empty_sitename', __('You must provide a name for your network of sites.')); } // Check for network collision. if ($network_id == $hqdb->get_var($hqdb->prepare("SELECT id FROM {$hqdb->site} WHERE id = %d", $network_id))) { $errors->add('siteid_exists', __('The network already exists.')); } $site_user = get_user_by('email', $email); if (!is_email($email)) { $errors->add('invalid_email', __('You must provide a valid e-mail address.')); } if ($errors->get_error_code()) { return $errors; } // Set up site tables. $template = get_option('template'); $stylesheet = get_option('stylesheet'); $allowed_themes = array($stylesheet => true); if ($template != $stylesheet) { $allowed_themes[$template] = true; } if (HQ_DEFAULT_THEME != $stylesheet && HQ_DEFAULT_THEME != $template) { $allowed_themes[HQ_DEFAULT_THEME] = true; } if (1 == $network_id) { $hqdb->insert($hqdb->site, array('domain' => $domain, 'path' => $path)); $network_id = $hqdb->insert_id; } else { $hqdb->insert($hqdb->site, array('domain' => $domain, 'path' => $path, 'id' => $network_id)); } hq_cache_delete('networks_have_paths', 'site-options'); //TODO: no multisite //if ( !is_multisite() ) { $site_admins = array($site_user->user_login); $users = get_users(array('fields' => array('ID', 'user_login'))); if ($users) { foreach ($users as $user) { if (is_super_admin($user->ID) && !in_array($user->user_login, $site_admins)) { $site_admins[] = $user->user_login; } } } //} else { // $site_admins = get_site_option( 'site_admins' ); //} /* translators: Do not translate USERNAME, SITE_NAME, BLOG_URL, PASSWORD: those are placeholders. */ $welcome_email = __('Howdy USERNAME, Your new SITE_NAME site has been successfully set up at: BLOG_URL You can log in to the administrator account with the following information: Username: USERNAME Password: PASSWORD Log in here: BLOG_URLhq-login.php We hope you enjoy your new site. Thanks! --The Team @ SITE_NAME'); $misc_exts = array('jpg', 'jpeg', 'png', 'gif', 'mov', 'avi', 'mpg', '3gp', '3g2', 'midi', 'mid', 'pdf', 'doc', 'ppt', 'odt', 'pptx', 'docx', 'pps', 'ppsx', 'xls', 'xlsx', 'key'); $audio_exts = hq_get_audio_extensions(); $video_exts = hq_get_video_extensions(); $upload_filetypes = array_unique(array_merge($misc_exts, $audio_exts, $video_exts)); $sitemeta = array('site_name' => $site_name, 'admin_email' => $site_user->user_email, 'admin_user_id' => $site_user->ID, 'registration' => 'none', 'upload_filetypes' => implode(' ', $upload_filetypes), 'blog_upload_space' => 100, 'fileupload_maxk' => 1500, 'site_admins' => $site_admins, 'allowedthemes' => $allowed_themes, 'illegal_names' => array('www', 'web', 'root', 'admin', 'main', 'invite', 'administrator', 'files'), 'hqmu_upgrade_site' => $hq_db_version, 'welcome_email' => $welcome_email, 'first_post' => __('Welcome to <a href="SITE_URL">SITE_NAME</a>. This is your first post. Edit or delete it, then start blogging!'), 'siteurl' => get_option('siteurl') . '/', 'add_new_users' => '0', 'upload_space_check_disabled' => '1', 'subdomain_install' => intval($subdomain_install), 'global_terms_enabled' => global_terms_enabled() ? '1' : '0', 'ms_files_rewriting' => '0', 'initial_db_version' => get_option('initial_db_version'), 'active_sitewide_plugins' => array(), 'HQLANG' => get_locale()); if (!$subdomain_install) { $sitemeta['illegal_names'][] = 'blog'; } /** * Filter meta for a network on creation. * * @since 0.0.1 * * @param array $sitemeta Associative array of network meta keys and values to be inserted. * @param int $network_id ID of network to populate. */ $sitemeta = apply_filters('populate_network_meta', $sitemeta, $network_id); $insert = ''; foreach ($sitemeta as $meta_key => $meta_value) { if (is_array($meta_value)) { $meta_value = serialize($meta_value); } if (!empty($insert)) { $insert .= ', '; } $insert .= $hqdb->prepare("( %d, %s, %s)", $network_id, $meta_key, $meta_value); } $hqdb->query("INSERT INTO {$hqdb->sitemeta} ( site_id, meta_key, meta_value ) VALUES " . $insert); /* * When upgrading from single to multisite, assume the current site will * become the main site of the network. When using populate_network() * to create another network in an existing multisite environment, skip * these steps since the main site of the new network has not yet been * created. */ //TODO: no multisite //if ( ! is_multisite() ) { $current_site = new stdClass(); $current_site->domain = $domain; $current_site->path = $path; $current_site->site_name = ucfirst($domain); $hqdb->insert($hqdb->blogs, array('site_id' => $network_id, 'blog_id' => 1, 'domain' => $domain, 'path' => $path, 'registered' => current_time('mysql'))); $current_site->blog_id = $blog_id = $hqdb->insert_id; update_user_meta($site_user->ID, 'source_domain', $domain); update_user_meta($site_user->ID, 'primary_blog', $blog_id); if ($subdomain_install) { $hq_rewrite->set_permalink_structure('/%year%/%monthnum%/%day%/%postname%/'); } else { $hq_rewrite->set_permalink_structure('/blog/%year%/%monthnum%/%day%/%postname%/'); } flush_rewrite_rules(); if (!$subdomain_install) { return true; } $vhost_ok = false; $errstr = ''; $hostname = substr(md5(time()), 0, 6) . '.' . $domain; // Very random hostname! $page = hq_remote_get('http://' . $hostname, array('timeout' => 5, 'httpversion' => '1.1')); if (is_hq_error($page)) { $errstr = $page->get_error_message(); } elseif (200 == hq_remote_retrieve_response_code($page)) { $vhost_ok = true; } if (!$vhost_ok) { $msg = '<p><strong>' . __('Warning! Wildcard DNS may not be configured correctly!') . '</strong></p>'; $msg .= '<p>' . sprintf(__('The installer attempted to contact a random hostname (<code>%1$s</code>) on your domain.'), $hostname); if (!empty($errstr)) { $msg .= ' ' . sprintf(__('This resulted in an error message: %s'), '<code>' . $errstr . '</code>'); } $msg .= '</p>'; $msg .= '<p>' . __('To use a subdomain configuration, you must have a wildcard entry in your DNS. This usually means adding a <code>*</code> hostname record pointing at your web server in your DNS configuration tool.') . '</p>'; $msg .= '<p>' . __('You can still use your site but any subdomain you create may not be accessible. If you know your DNS is correct, ignore this message.') . '</p>'; return new HQ_Error('no_wildcard_dns', $msg); } //} return true; }
/** * Handles sending password retrieval email to user. * * @global hqdb $hqdb HiveQueen database abstraction object. * @global PasswordHash $hq_hasher Portable PHP password hashing framework. * * @return bool|HQ_Error True: when finish. HQ_Error on error */ function retrieve_password() { global $hqdb, $hq_hasher; $errors = new HQ_Error(); if (empty($_POST['user_login'])) { $errors->add('empty_username', __('<strong>ERROR</strong>: Enter a username or e-mail address.')); } elseif (strpos($_POST['user_login'], '@')) { $user_data = get_user_by('email', trim($_POST['user_login'])); if (empty($user_data)) { $errors->add('invalid_email', __('<strong>ERROR</strong>: There is no user registered with that email address.')); } } else { $login = trim($_POST['user_login']); $user_data = get_user_by('login', $login); } /** * Fires before errors are returned from a password reset request. * * @since 0.0.1 */ do_action('lostpassword_post'); if ($errors->get_error_code()) { return $errors; } if (!$user_data) { $errors->add('invalidcombo', __('<strong>ERROR</strong>: Invalid username or e-mail.')); return $errors; } // Redefining user_login ensures we return the right case in the email. $user_login = $user_data->user_login; $user_email = $user_data->user_email; /** * Fires before a new password is retrieved. * * @since 0.0.1 * * @param string $user_login The user login name. */ do_action('retreive_password', $user_login); /** * Fires before a new password is retrieved. * * @since 0.0.1 * * @param string $user_login The user login name. */ do_action('retrieve_password', $user_login); /** * Filter whether to allow a password to be reset. * * @since 0.0.1 * * @param bool true Whether to allow the password to be reset. Default true. * @param int $user_data->ID The ID of the user attempting to reset a password. */ $allow = apply_filters('allow_password_reset', true, $user_data->ID); if (!$allow) { return new HQ_Error('no_password_reset', __('Password reset is not allowed for this user')); } elseif (is_hq_error($allow)) { return $allow; } // Generate something random for a password reset key. $key = hq_generate_password(20, false); /** * Fires when a password reset key is generated. * * @since 0.0.1 * * @param string $user_login The username for the user. * @param string $key The generated password reset key. */ do_action('retrieve_password_key', $user_login, $key); // Now insert the key, hashed, into the DB. if (empty($hq_hasher)) { require_once ABSPATH . HQINC . '/class-phpass.php'; $hq_hasher = new PasswordHash(8, true); } $hashed = time() . ':' . $hq_hasher->HashPassword($key); $hqdb->update($hqdb->users, array('user_activation_key' => $hashed), array('user_login' => $user_login)); $message = __('Someone requested that the password be reset for the following account:') . "\r\n\r\n"; $message .= network_home_url('/') . "\r\n\r\n"; $message .= sprintf(__('Username: %s'), $user_login) . "\r\n\r\n"; $message .= __('If this was a mistake, just ignore this email and nothing will happen.') . "\r\n\r\n"; $message .= __('To reset your password, visit the following address:') . "\r\n\r\n"; $message .= '<' . network_site_url("hq-login.php?action=rp&key={$key}&login="******">\r\n"; //TODO: Goyo no multisite //if ( is_multisite() ) if (false) { $blogname = $GLOBALS['current_site']->site_name; } else { /* * The blogname option is escaped with esc_html on the way into the database * in sanitize_option we want to reverse this for the plain text arena of emails. */ $blogname = hq_specialchars_decode(get_option('blogname'), ENT_QUOTES); } $title = sprintf(__('[%s] Password Reset'), $blogname); /** * Filter the subject of the password reset email. * * @since 0.0.1 * * @param string $title Default email title. */ $title = apply_filters('retrieve_password_title', $title); /** * Filter the message body of the password reset mail. * * @since 0.0.1 * * @param string $message Default mail message. * @param string $key The activation key. * @param string $user_login The username for the user. * @param HQ_User $user_data HQ_User object. */ $message = apply_filters('retrieve_password_message', $message, $key, $user_login, $user_data); if ($message && !hq_mail($user_email, hq_specialchars_decode($title), $message)) { hq_die(__('The e-mail could not be sent.') . "<br />\n" . __('Possible reason: your host may have disabled the mail() function.')); } return true; }
/** * @param array $args * @param array $instance */ public function widget($args, $instance) { if (isset($instance['error']) && $instance['error']) { return; } $url = !empty($instance['url']) ? $instance['url'] : ''; while (stristr($url, 'http') != $url) { $url = substr($url, 1); } if (empty($url)) { return; } // self-url destruction sequence if (in_array(untrailingslashit($url), array(site_url(), home_url()))) { return; } $rss = fetch_feed($url); $title = $instance['title']; $desc = ''; $link = ''; if (!is_hq_error($rss)) { $desc = esc_attr(strip_tags(@html_entity_decode($rss->get_description(), ENT_QUOTES, get_option('blog_charset')))); if (empty($title)) { $title = esc_html(strip_tags($rss->get_title())); } $link = esc_url(strip_tags($rss->get_permalink())); while (stristr($link, 'http') != $link) { $link = substr($link, 1); } } if (empty($title)) { $title = empty($desc) ? __('Unknown Feed') : $desc; } /** This filter is documented in hq-includes/default-widgets.php */ $title = apply_filters('widget_title', $title, $instance, $this->id_base); $url = esc_url(strip_tags($url)); $icon = includes_url('images/rss.png'); if ($title) { $title = "<a class='rsswidget' href='{$url}'><img style='border:0' width='14' height='14' src='{$icon}' alt='RSS' /></a> <a class='rsswidget' href='{$link}'>{$title}</a>"; } echo $args['before_widget']; if ($title) { echo $args['before_title'] . $title . $args['after_title']; } hq_widget_rss_output($rss, $instance); echo $args['after_widget']; if (!is_hq_error($rss)) { $rss->__destruct(); } unset($rss); }
/** * Checks the version of the installed MySQL binary. * * @since 0.0.1 * * @global hqdb $hqdb */ function hq_check_mysql_version() { global $hqdb; $result = $hqdb->check_database_version(); if (is_hq_error($result)) { die($result->get_error_message()); } }
/** * Retrieve the avatar `<img>` tag for a user, email address, MD5 hash, comment, or post. * * @since 0.0.1 * @since 0.0.1 * * @param mixed $id_or_email The Gravatar to retrieve. Accepts a user_id, gravatar md5 hash, * user email, HQ_User object, HQ_Post object, or comment object. * @param int $size Optional. Height and width of the avatar image file in pixels. Default 96. * @param string $default Optional. 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'. * @param string $alt Optional. Alternative text to use in <img> tag. Default empty. * @param array $args { * Optional. Extra arguments to retrieve the avatar. * * @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 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|string $class Array or string of additional classes to add to the <img> element. * Default null. * @type bool $force_display Whether to always show the avatar - ignores the show_avatars option. * Default false. * @type string $extra_attr HTML attributes to insert in the IMG element. Is not sanitized. Default empty. * } * @return false|string `<img>` tag for the user's avatar. False on failure. */ function get_avatar($id_or_email, $size = 96, $default = '', $alt = '', $args = null) { $defaults = array('size' => 96, 'height' => null, 'width' => null, 'default' => get_option('avatar_default', 'mystery'), 'force_default' => false, 'rating' => get_option('avatar_rating'), 'scheme' => null, 'alt' => '', 'class' => null, 'force_display' => false, 'extra_attr' => ''); if (empty($args)) { $args = array(); } $args['size'] = (int) $size; $args['default'] = $default; $args['alt'] = $alt; $args = hq_parse_args($args, $defaults); if (empty($args['height'])) { $args['height'] = $args['size']; } if (empty($args['width'])) { $args['width'] = $args['size']; } /** * Filter whether to retrieve the avatar URL early. * * Passing a non-null value will effectively short-circuit get_avatar(), passing * the value through the {@see 'pre_get_avatar'} filter and returning early. * * @since 0.0.1 * * @param string $avatar HTML for the user's avatar. Default null. * @param int|object|string $id_or_email A user ID, email address, or comment object. * @param array $args Arguments passed to get_avatar_url(), after processing. */ $avatar = apply_filters('pre_get_avatar', null, $id_or_email, $args); if (!is_null($avatar)) { /** This filter is documented in hq-includes/pluggable.php */ return apply_filters('get_avatar', $avatar, $id_or_email, $args['size'], $args['default'], $args['alt'], $args); } if (!$args['force_display'] && !get_option('show_avatars')) { return false; } $url2x = get_avatar_url($id_or_email, array_merge($args, array('size' => $args['size'] * 2))); $args = get_avatar_data($id_or_email, $args); $url = $args['url']; if (!$url || is_hq_error($url)) { return false; } $class = array('avatar', 'avatar-' . (int) $args['size'], 'photo'); if (!$args['found_avatar'] || $args['force_default']) { $class[] = 'avatar-default'; } if ($args['class']) { if (is_array($args['class'])) { $class = array_merge($class, $args['class']); } else { $class[] = $args['class']; } } $avatar = sprintf("<img alt='%s' src='%s' srcset='%s' class='%s' height='%d' width='%d' %s/>", esc_attr($args['alt']), esc_url($url), esc_attr("{$url2x} 2x"), esc_attr(join(' ', $class)), (int) $args['height'], (int) $args['width'], $args['extra_attr']); /** * Filter the avatar to retrieve. * * @since 0.0.1 * @since 0.0.1 * * @param string $avatar <img> tag for the user's avatar. * @param int|object|string $id_or_email A user ID, email address, or comment object. * @param int $size Square avatar width and height in pixels to retrieve. * @param string $alt Alternative text to use in the avatar image tag. * Default empty. * @param array $args Arguments passed to get_avatar_data(), after processing. */ return apply_filters('get_avatar', $avatar, $id_or_email, $args['size'], $args['default'], $args['alt'], $args); }
/** * Generate post thumbnail attachment meta data. * * @since 0.0.1 * * @global array $_hq_additional_image_sizes * * @param int $attachment_id Attachment Id to process. * @param string $file Filepath of the Attached image. * @return mixed Metadata for attachment. */ function hq_generate_attachment_metadata($attachment_id, $file) { $attachment = get_post($attachment_id); $metadata = array(); $support = false; if (preg_match('!^image/!', get_post_mime_type($attachment)) && file_is_displayable_image($file)) { $imagesize = getimagesize($file); $metadata['width'] = $imagesize[0]; $metadata['height'] = $imagesize[1]; // Make the file path relative to the upload dir. $metadata['file'] = _hq_relative_upload_path($file); // Make thumbnails and other intermediate sizes. global $_hq_additional_image_sizes; $sizes = array(); foreach (get_intermediate_image_sizes() as $s) { $sizes[$s] = array('width' => '', 'height' => '', 'crop' => false); if (isset($_hq_additional_image_sizes[$s]['width'])) { $sizes[$s]['width'] = intval($_hq_additional_image_sizes[$s]['width']); } else { $sizes[$s]['width'] = get_option("{$s}_size_w"); } // For default sizes set in options if (isset($_hq_additional_image_sizes[$s]['height'])) { $sizes[$s]['height'] = intval($_hq_additional_image_sizes[$s]['height']); } else { $sizes[$s]['height'] = get_option("{$s}_size_h"); } // For default sizes set in options if (isset($_hq_additional_image_sizes[$s]['crop'])) { $sizes[$s]['crop'] = $_hq_additional_image_sizes[$s]['crop']; } else { $sizes[$s]['crop'] = get_option("{$s}_crop"); } // For default sizes set in options } /** * Filter the image sizes automatically generated when uploading an image. * * @since 0.0.1 * * @param array $sizes An associative array of image sizes. */ $sizes = apply_filters('intermediate_image_sizes_advanced', $sizes); if ($sizes) { $editor = hq_get_image_editor($file); if (!is_hq_error($editor)) { $metadata['sizes'] = $editor->multi_resize($sizes); } } else { $metadata['sizes'] = array(); } // Fetch additional metadata from EXIF/IPTC. $image_meta = hq_read_image_metadata($file); if ($image_meta) { $metadata['image_meta'] = $image_meta; } } elseif (hq_attachment_is('video', $attachment)) { $metadata = hq_read_video_metadata($file); $support = current_theme_supports('post-thumbnails', 'attachment:video') || post_type_supports('attachment:video', 'thumbnail'); } elseif (hq_attachment_is('audio', $attachment)) { $metadata = hq_read_audio_metadata($file); $support = current_theme_supports('post-thumbnails', 'attachment:audio') || post_type_supports('attachment:audio', 'thumbnail'); } if ($support && !empty($metadata['image']['data'])) { // Check for existing cover. $hash = md5($metadata['image']['data']); $posts = get_posts(array('fields' => 'ids', 'post_type' => 'attachment', 'post_mime_type' => $metadata['image']['mime'], 'post_status' => 'inherit', 'posts_per_page' => 1, 'meta_key' => '_cover_hash', 'meta_value' => $hash)); $exists = reset($posts); if (!empty($exists)) { update_post_meta($attachment_id, '_thumbnail_id', $exists); } else { $ext = '.jpg'; switch ($metadata['image']['mime']) { case 'image/gif': $ext = '.gif'; break; case 'image/png': $ext = '.png'; break; } $basename = str_replace('.', '-', basename($file)) . '-image' . $ext; $uploaded = hq_upload_bits($basename, '', $metadata['image']['data']); if (false === $uploaded['error']) { $image_attachment = array('post_mime_type' => $metadata['image']['mime'], 'post_type' => 'attachment', 'post_content' => ''); /** * Filter the parameters for the attachment thumbnail creation. * * @since 0.0.1 * * @param array $image_attachment An array of parameters to create the thumbnail. * @param array $metadata Current attachment metadata. * @param array $uploaded An array containing the thumbnail path and url. */ $image_attachment = apply_filters('attachment_thumbnail_args', $image_attachment, $metadata, $uploaded); $sub_attachment_id = hq_insert_attachment($image_attachment, $uploaded['file']); add_post_meta($sub_attachment_id, '_cover_hash', $hash); $attach_data = hq_generate_attachment_metadata($sub_attachment_id, $uploaded['file']); hq_update_attachment_metadata($sub_attachment_id, $attach_data); update_post_meta($attachment_id, '_thumbnail_id', $sub_attachment_id); } } } // Remove the blob of binary data from the array. unset($metadata['image']['data']); /** * Filter the generated attachment meta data. * * @since 0.0.1 * * @param array $metadata An array of attachment meta data. * @param int $attachment_id Current attachment ID. */ return apply_filters('hq_generate_attachment_metadata', $metadata, $attachment_id); }
/** * Autosave with heartbeat * * @since 0.0.1 */ function heartbeat_autosave($response, $data) { if (!empty($data['hq_autosave'])) { $saved = hq_autosave($data['hq_autosave']); if (is_hq_error($saved)) { $response['hq_autosave'] = array('success' => false, 'message' => $saved->get_error_message()); } elseif (empty($saved)) { $response['hq_autosave'] = array('success' => false, 'message' => __('Error while saving.')); } else { /* translators: draft saved date format, see http://php.net/date */ $draft_saved_date_format = __('g:i:s a'); /* translators: %s: date and time */ $response['hq_autosave'] = array('success' => true, 'message' => sprintf(__('Draft saved at %s.'), date_i18n($draft_saved_date_format))); } } return $response; }
/** * Gets attachment uploaded by Media Manager, crops it, then saves it as a * new object. Returns JSON-encoded object details. */ public function ajax_header_crop() { check_ajax_referer('image_editor-' . $_POST['id'], 'nonce'); if (!current_user_can('edit_theme_options')) { hq_send_json_error(); } if (!current_theme_supports('custom-header', 'uploads')) { hq_send_json_error(); } $crop_details = $_POST['cropDetails']; $dimensions = $this->get_header_dimensions(array('height' => $crop_details['height'], 'width' => $crop_details['width'])); $attachment_id = absint($_POST['id']); $cropped = hq_crop_image($attachment_id, (int) $crop_details['x1'], (int) $crop_details['y1'], (int) $crop_details['width'], (int) $crop_details['height'], (int) $dimensions['dst_width'], (int) $dimensions['dst_height']); if (!$cropped || is_hq_error($cropped)) { hq_send_json_error(array('message' => __('Image could not be processed. Please go back and try again.'))); } /** This filter is documented in hq-admin/custom-header.php */ $cropped = apply_filters('hq_create_file_in_uploads', $cropped, $attachment_id); // For replication $object = $this->create_attachment_object($cropped, $attachment_id); unset($object['ID']); $new_attachment_id = $this->insert_attachment($object, $cropped); $object['attachment_id'] = $new_attachment_id; $object['width'] = $dimensions['dst_width']; $object['height'] = $dimensions['dst_height']; hq_send_json_success($object); }
/** * Returns a link to a post format index. * * @since 0.0.1 * * @param string $format The post format slug. * @return string|HQ_Error|false The post format term link. */ function get_post_format_link($format) { $term = get_term_by('slug', 'post-format-' . $format, 'post_format'); if (!$term || is_hq_error($term)) { return false; } return get_term_link($term); }
/** * Displays a form to the user to request for their FTP/SSH details in order * to connect to the filesystem. * * All chosen/entered details are saved, Excluding the Password. * * Hostnames may be in the form of hostname:portnumber (eg: wordpress.org:2467) * to specify an alternate FTP/SSH port. * * Plugins may override this form by returning true|false via the * {@see 'request_filesystem_credentials'} filter. * * @since 0.0.1 * * @todo Properly mark optional arguments as such * * @param string $form_post the URL to post the form to * @param string $type the chosen Filesystem method in use * @param bool $error if the current request has failed to connect * @param string $context The directory which is needed access to, The write-test will be performed on this directory by get_filesystem_method() * @param array $extra_fields Extra POST fields which should be checked for to be included in the post. * @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable. * @return bool False on failure. True on success. */ function request_filesystem_credentials($form_post, $type = '', $error = false, $context = false, $extra_fields = null, $allow_relaxed_file_ownership = false) { /** * Filter the filesystem credentials form output. * * Returning anything other than an empty string will effectively short-circuit * output of the filesystem credentials form, returning that value instead. * * @since 0.0.1 * * @param mixed $output Form output to return instead. Default empty. * @param string $form_post URL to POST the form to. * @param string $type Chosen type of filesystem. * @param bool $error Whether the current request has failed to connect. * Default false. * @param string $context Full path to the directory that is tested for * being writable. * @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable. * @param array $extra_fields Extra POST fields. */ $req_cred = apply_filters('request_filesystem_credentials', '', $form_post, $type, $error, $context, $extra_fields, $allow_relaxed_file_ownership); if ('' !== $req_cred) { return $req_cred; } if (empty($type)) { $type = get_filesystem_method(array(), $context, $allow_relaxed_file_ownership); } if ('direct' == $type) { return true; } if (is_null($extra_fields)) { $extra_fields = array('version', 'locale'); } $credentials = get_option('ftp_credentials', array('hostname' => '', 'username' => '')); // If defined, set it to that, Else, If POST'd, set it to that, If not, Set it to whatever it previously was(saved details in option) $credentials['hostname'] = defined('FTP_HOST') ? FTP_HOST : (!empty($_POST['hostname']) ? hq_unslash($_POST['hostname']) : $credentials['hostname']); $credentials['username'] = defined('FTP_USER') ? FTP_USER : (!empty($_POST['username']) ? hq_unslash($_POST['username']) : $credentials['username']); $credentials['password'] = defined('FTP_PASS') ? FTP_PASS : (!empty($_POST['password']) ? hq_unslash($_POST['password']) : ''); // Check to see if we are setting the public/private keys for ssh $credentials['public_key'] = defined('FTP_PUBKEY') ? FTP_PUBKEY : (!empty($_POST['public_key']) ? hq_unslash($_POST['public_key']) : ''); $credentials['private_key'] = defined('FTP_PRIKEY') ? FTP_PRIKEY : (!empty($_POST['private_key']) ? hq_unslash($_POST['private_key']) : ''); // Sanitize the hostname, Some people might pass in odd-data: $credentials['hostname'] = preg_replace('|\\w+://|', '', $credentials['hostname']); //Strip any schemes off if (strpos($credentials['hostname'], ':')) { list($credentials['hostname'], $credentials['port']) = explode(':', $credentials['hostname'], 2); if (!is_numeric($credentials['port'])) { unset($credentials['port']); } } else { unset($credentials['port']); } if (defined('FTP_SSH') && FTP_SSH || defined('FS_METHOD') && 'ssh2' == FS_METHOD) { $credentials['connection_type'] = 'ssh'; } elseif (defined('FTP_SSL') && FTP_SSL && 'ftpext' == $type) { //Only the FTP Extension understands SSL $credentials['connection_type'] = 'ftps'; } elseif (!empty($_POST['connection_type'])) { $credentials['connection_type'] = hq_unslash($_POST['connection_type']); } elseif (!isset($credentials['connection_type'])) { //All else fails (And it's not defaulted to something else saved), Default to FTP $credentials['connection_type'] = 'ftp'; } if (!$error && (!empty($credentials['password']) && !empty($credentials['username']) && !empty($credentials['hostname']) || 'ssh' == $credentials['connection_type'] && !empty($credentials['public_key']) && !empty($credentials['private_key']))) { $stored_credentials = $credentials; if (!empty($stored_credentials['port'])) { //save port as part of hostname to simplify above code. $stored_credentials['hostname'] .= ':' . $stored_credentials['port']; } unset($stored_credentials['password'], $stored_credentials['port'], $stored_credentials['private_key'], $stored_credentials['public_key']); if (!defined('HQ_INSTALLING')) { update_option('ftp_credentials', $stored_credentials); } return $credentials; } $hostname = isset($credentials['hostname']) ? $credentials['hostname'] : ''; $username = isset($credentials['username']) ? $credentials['username'] : ''; $public_key = isset($credentials['public_key']) ? $credentials['public_key'] : ''; $private_key = isset($credentials['private_key']) ? $credentials['private_key'] : ''; $port = isset($credentials['port']) ? $credentials['port'] : ''; $connection_type = isset($credentials['connection_type']) ? $credentials['connection_type'] : ''; if ($error) { $error_string = __('<strong>ERROR:</strong> There was an error connecting to the server, Please verify the settings are correct.'); if (is_hq_error($error)) { $error_string = esc_html($error->get_error_message()); } echo '<div id="message" class="error"><p>' . $error_string . '</p></div>'; } $types = array(); if (extension_loaded('ftp') || extension_loaded('sockets') || function_exists('fsockopen')) { $types['ftp'] = __('FTP'); } if (extension_loaded('ftp')) { //Only this supports FTPS $types['ftps'] = __('FTPS (SSL)'); } if (extension_loaded('ssh2') && function_exists('stream_get_contents')) { $types['ssh'] = __('SSH2'); } /** * Filter the connection types to output to the filesystem credentials form. * * @since 0.0.1 * * @param array $types Types of connections. * @param array $credentials Credentials to connect with. * @param string $type Chosen filesystem method. * @param object $error Error object. * @param string $context Full path to the directory that is tested * for being writable. */ $types = apply_filters('fs_ftp_connection_types', $types, $credentials, $type, $error, $context); ?> <script type="text/javascript"> <!-- jQuery(function($){ jQuery("#ssh").click(function () { jQuery("#ssh_keys").show(); }); jQuery("#ftp, #ftps").click(function () { jQuery("#ssh_keys").hide(); }); jQuery('#request-filesystem-credentials-form input[value=""]:first').focus(); }); --> </script> <form action="<?php echo esc_url($form_post); ?> " method="post"> <div id="request-filesystem-credentials-form" class="request-filesystem-credentials-form"> <h3 id="request-filesystem-credentials-title"><?php _e('Connection Information'); ?> </h3> <p id="request-filesystem-credentials-desc"><?php $label_user = __('Username'); $label_pass = __('Password'); _e('To perform the requested action, HiveQueen needs to access your web server.'); echo ' '; if (isset($types['ftp']) || isset($types['ftps'])) { if (isset($types['ssh'])) { _e('Please enter your FTP or SSH credentials to proceed.'); $label_user = __('FTP/SSH Username'); $label_pass = __('FTP/SSH Password'); } else { _e('Please enter your FTP credentials to proceed.'); $label_user = __('FTP Username'); $label_pass = __('FTP Password'); } echo ' '; } _e('If you do not remember your credentials, you should contact your web host.'); ?> </p> <label for="hostname"> <span class="field-title"><?php _e('Hostname'); ?> </span> <input name="hostname" type="text" id="hostname" aria-describedby="request-filesystem-credentials-desc" class="code" placeholder="<?php esc_attr_e('example: www.wordpress.org'); ?> " value="<?php echo esc_attr($hostname); if (!empty($port)) { echo ":{$port}"; } ?> "<?php disabled(defined('FTP_HOST')); ?> /> </label> <div class="ftp-username"> <label for="username"> <span class="field-title"><?php echo $label_user; ?> </span> <input name="username" type="text" id="username" value="<?php echo esc_attr($username); ?> "<?php disabled(defined('FTP_USER')); ?> /> </label> </div> <div class="ftp-password"> <label for="password"> <span class="field-title"><?php echo $label_pass; ?> </span> <input name="password" type="password" id="password" value="<?php if (defined('FTP_PASS')) { echo '*****'; } ?> "<?php disabled(defined('FTP_PASS')); ?> /> <em><?php if (!defined('FTP_PASS')) { _e('This password will not be stored on the server.'); } ?> </em> </label> </div> <?php if (isset($types['ssh'])) { ?> <h4><?php _e('Authentication Keys'); ?> </h4> <label for="public_key"> <span class="field-title"><?php _e('Public Key:'); ?> </span> <input name="public_key" type="text" id="public_key" aria-describedby="auth-keys-desc" value="<?php echo esc_attr($public_key); ?> "<?php disabled(defined('FTP_PUBKEY')); ?> /> </label> <label for="private_key"> <span class="field-title"><?php _e('Private Key:'); ?> </span> <input name="private_key" type="text" id="private_key" value="<?php echo esc_attr($private_key); ?> "<?php disabled(defined('FTP_PRIKEY')); ?> /> </label> <span id="auth-keys-desc"><?php _e('Enter the location on the server where the public and private keys are located. If a passphrase is needed, enter that in the password field above.'); ?> </span> <?php } ?> <h4><?php _e('Connection Type'); ?> </h4> <fieldset><legend class="screen-reader-text"><span><?php _e('Connection Type'); ?> </span></legend> <?php $disabled = disabled(defined('FTP_SSL') && FTP_SSL || defined('FTP_SSH') && FTP_SSH, true, false); foreach ($types as $name => $text) { ?> <label for="<?php echo esc_attr($name); ?> "> <input type="radio" name="connection_type" id="<?php echo esc_attr($name); ?> " value="<?php echo esc_attr($name); ?> "<?php checked($name, $connection_type); echo $disabled; ?> /> <?php echo $text; ?> </label> <?php } ?> </fieldset> <?php foreach ((array) $extra_fields as $field) { if (isset($_POST[$field])) { echo '<input type="hidden" name="' . esc_attr($field) . '" value="' . esc_attr(hq_unslash($_POST[$field])) . '" />'; } } ?> <p class="request-filesystem-credentials-action-buttons"> <button class="button cancel-button" data-js-action="close" type="button"><?php _e('Cancel'); ?> </button> <?php submit_button(__('Proceed'), 'button', 'upgrade', false); ?> </p> </div> </form> <?php return false; }
/** * Validate active plugins * * Validate all active plugins, deactivates invalid and * returns an array of deactivated ones. * * @since 0.0.1 * @return array invalid plugins, plugin as key, error as value */ function validate_active_plugins() { $plugins = get_option('active_plugins', array()); // Validate vartype: array. if (!is_array($plugins)) { update_option('active_plugins', array()); $plugins = array(); } if (is_multisite() && current_user_can('manage_network_plugins')) { $network_plugins = (array) get_site_option('active_sitewide_plugins', array()); $plugins = array_merge($plugins, array_keys($network_plugins)); } if (empty($plugins)) { return array(); } $invalid = array(); // Invalid plugins get deactivated. foreach ($plugins as $plugin) { $result = validate_plugin($plugin); if (is_hq_error($result)) { $invalid[$plugin] = $result; deactivate_plugins($plugin, true); } } return $invalid; }
/** * Check if HiveQueen has access to the filesystem without asking for * credentials. * * @since 0.0.1 * * @return bool Returns true on success, false on failure. */ function hq_can_install_language_pack() { if (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) { return false; } require_once ABSPATH . 'hq-admin/includes/class-hq-upgrader.php'; $skin = new Automatic_Upgrader_Skin(); $upgrader = new Language_Pack_Upgrader($skin); $upgrader->init(); $check = $upgrader->fs_connect(array(HQ_CONTENT_DIR, HQ_LANG_DIR)); if (!$check || is_hq_error($check)) { return false; } return true; }
/** * Retrieve queried object. * * If queried object is not set, then the queried object will be set from * the category, tag, taxonomy, posts page, single post, page, or author * query variable. After it is set up, it will be returned. * * @since 0.0.1 * @access public * * @return object */ public function get_queried_object() { if (isset($this->queried_object)) { return $this->queried_object; } $this->queried_object = null; $this->queried_object_id = 0; if ($this->is_category || $this->is_tag || $this->is_tax) { if ($this->is_category) { if ($this->get('cat')) { $term = get_term($this->get('cat'), 'category'); } elseif ($this->get('category_name')) { $term = get_term_by('slug', $this->get('category_name'), 'category'); } } elseif ($this->is_tag) { if ($this->get('tag_id')) { $term = get_term($this->get('tag_id'), 'post_tag'); } elseif ($this->get('tag')) { $term = get_term_by('slug', $this->get('tag'), 'post_tag'); } } else { // For other tax queries, grab the first term from the first clause. $tax_query_in_and = hq_list_filter($this->tax_query->queried_terms, array('operator' => 'NOT IN'), 'NOT'); if (!empty($tax_query_in_and)) { $queried_taxonomies = array_keys($tax_query_in_and); $matched_taxonomy = reset($queried_taxonomies); $query = $tax_query_in_and[$matched_taxonomy]; if ($query['terms']) { if ('term_id' == $query['field']) { $term = get_term(reset($query['terms']), $matched_taxonomy); } else { $term = get_term_by($query['field'], reset($query['terms']), $matched_taxonomy); } } } } if (!empty($term) && !is_hq_error($term)) { $this->queried_object = $term; $this->queried_object_id = (int) $term->term_id; if ($this->is_category && 'category' === $this->queried_object->taxonomy) { _make_cat_compat($this->queried_object); } } } elseif ($this->is_post_type_archive) { $post_type = $this->get('post_type'); if (is_array($post_type)) { $post_type = reset($post_type); } $this->queried_object = get_post_type_object($post_type); } elseif ($this->is_posts_page) { $page_for_posts = get_option('page_for_posts'); $this->queried_object = get_post($page_for_posts); $this->queried_object_id = (int) $this->queried_object->ID; } elseif ($this->is_singular && !empty($this->post)) { $this->queried_object = $this->post; $this->queried_object_id = (int) $this->post->ID; } elseif ($this->is_author) { $this->queried_object_id = (int) $this->get('author'); $this->queried_object = get_userdata($this->queried_object_id); } return $this->queried_object; }
/** * Return the post's parent's post_ID * * @since 0.0.1 * * @param int $post_ID * * @return int|false Post parent ID, otherwise false. */ function hq_get_post_parent_id($post_ID) { $post = get_post($post_ID); if (!$post || is_hq_error($post)) { return false; } return (int) $post->post_parent; }
/** * Retrieve only the body from the raw response. * * @since 0.0.1 * * @param array $response HTTP response. * @return string The body of the response. Empty string if no body or incorrect parameter given. */ function hq_remote_retrieve_body($response) { if (is_hq_error($response) || !isset($response['body'])) { return ''; } return $response['body']; }
/** * Returns a HQ_Image_Editor instance and loads file into it. * * @since 0.0.1 * * @param string $path Path to the file to load. * @param array $args Optional. Additional arguments for retrieving the image editor. * Default empty array. * @return HQ_Image_Editor|HQ_Error The HQ_Image_Editor object if successful, an HQ_Error * object otherwise. */ function hq_get_image_editor($path, $args = array()) { $args['path'] = $path; if (!isset($args['mime_type'])) { $file_info = hq_check_filetype($args['path']); // If $file_info['type'] is false, then we let the editor attempt to // figure out the file type, rather than forcing a failure based on extension. if (isset($file_info) && $file_info['type']) { $args['mime_type'] = $file_info['type']; } } $implementation = _hq_image_editor_choose($args); if ($implementation) { $editor = new $implementation($path); $loaded = $editor->load(); if (is_hq_error($loaded)) { return $loaded; } return $editor; } return new HQ_Error('image_no_editor', __('No editor could be selected.')); }
/** * Authenticate the user using the username and password. * * @since 0.0.1 * * @param HQ_User|HQ_Error|null $user HQ_User or HQ_Error object from a previous callback. Default null. * @param string $username Username for authentication. * @param string $password Password for authentication. * @return HQ_User|HQ_Error HQ_User on success, HQ_Error on failure. */ function hq_authenticate_username_password($user, $username, $password) { if ($user instanceof HQ_User) { return $user; } if (empty($username) || empty($password)) { if (is_hq_error($user)) { return $user; } $error = new HQ_Error(); if (empty($username)) { $error->add('empty_username', __('<strong>ERROR</strong>: The username field is empty.')); } if (empty($password)) { $error->add('empty_password', __('<strong>ERROR</strong>: The password field is empty.')); } return $error; } $user = get_user_by('login', $username); if (!$user) { return new HQ_Error('invalid_username', sprintf(__('<strong>ERROR</strong>: Invalid username. <a href="%s">Lost your password?</a>'), hq_lostpassword_url())); } /** * Filter whether the given user can be authenticated with the provided $password. * * @since 0.0.1 * * @param HQ_User|HQ_Error $user HQ_User or HQ_Error object if a previous * callback failed authentication. * @param string $password Password to check against the user. */ $user = apply_filters('hq_authenticate_user', $user, $password); if (is_hq_error($user)) { return $user; } if (!hq_check_password($password, $user->user_pass, $user->ID)) { return new HQ_Error('incorrect_password', sprintf(__('<strong>ERROR</strong>: The password you entered for the username <strong>%1$s</strong> is incorrect. <a href="%2$s">Lost your password?</a>'), $username, hq_lostpassword_url())); } return $user; }
/** * Decorates a menu item object with the shared navigation menu item properties. * * Properties: * - ID: The term_id if the menu item represents a taxonomy term. * - attr_title: The title attribute of the link element for this menu item. * - classes: The array of class attribute values for the link element of this menu item. * - db_id: The DB ID of this item as a nav_menu_item object, if it exists (0 if it doesn't exist). * - description: The description of this menu item. * - menu_item_parent: The DB ID of the nav_menu_item that is this item's menu parent, if any. 0 otherwise. * - object: The type of object originally represented, such as "category," "post", or "attachment." * - object_id: The DB ID of the original object this menu item represents, e.g. ID for posts and term_id for categories. * - post_parent: The DB ID of the original object's parent object, if any (0 otherwise). * - post_title: A "no title" label if menu item represents a post that lacks a title. * - target: The target attribute of the link element for this menu item. * - title: The title of this menu item. * - type: The family of objects originally represented, such as "post_type" or "taxonomy." * - type_label: The singular label used to describe this type of menu item. * - url: The URL to which this menu item points. * - xfn: The XFN relationship expressed in the link of this menu item. * - _invalid: Whether the menu item represents an object that no longer exists. * * @since 0.0.1 * * @param object $menu_item The menu item to modify. * @return object $menu_item The menu item with standard menu item properties. */ function hq_setup_nav_menu_item($menu_item) { if (isset($menu_item->post_type)) { if ('nav_menu_item' == $menu_item->post_type) { $menu_item->db_id = (int) $menu_item->ID; $menu_item->menu_item_parent = !isset($menu_item->menu_item_parent) ? get_post_meta($menu_item->ID, '_menu_item_menu_item_parent', true) : $menu_item->menu_item_parent; $menu_item->object_id = !isset($menu_item->object_id) ? get_post_meta($menu_item->ID, '_menu_item_object_id', true) : $menu_item->object_id; $menu_item->object = !isset($menu_item->object) ? get_post_meta($menu_item->ID, '_menu_item_object', true) : $menu_item->object; $menu_item->type = !isset($menu_item->type) ? get_post_meta($menu_item->ID, '_menu_item_type', true) : $menu_item->type; if ('post_type' == $menu_item->type) { $object = get_post_type_object($menu_item->object); if ($object) { $menu_item->type_label = $object->labels->singular_name; } else { $menu_item->type_label = $menu_item->object; $menu_item->_invalid = true; } $menu_item->url = get_permalink($menu_item->object_id); $original_object = get_post($menu_item->object_id); $original_title = $original_object->post_title; if ('' === $original_title) { /* translators: %d: ID of a post */ $original_title = sprintf(__('#%d (no title)'), $original_object->ID); } $menu_item->title = '' == $menu_item->post_title ? $original_title : $menu_item->post_title; } elseif ('taxonomy' == $menu_item->type) { $object = get_taxonomy($menu_item->object); if ($object) { $menu_item->type_label = $object->labels->singular_name; } else { $menu_item->type_label = $menu_item->object; $menu_item->_invalid = true; } $term_url = get_term_link((int) $menu_item->object_id, $menu_item->object); $menu_item->url = !is_hq_error($term_url) ? $term_url : ''; $original_title = get_term_field('name', $menu_item->object_id, $menu_item->object, 'raw'); if (is_hq_error($original_title)) { $original_title = false; } $menu_item->title = '' == $menu_item->post_title ? $original_title : $menu_item->post_title; } else { $menu_item->type_label = __('Custom Link'); $menu_item->title = $menu_item->post_title; $menu_item->url = !isset($menu_item->url) ? get_post_meta($menu_item->ID, '_menu_item_url', true) : $menu_item->url; } $menu_item->target = !isset($menu_item->target) ? get_post_meta($menu_item->ID, '_menu_item_target', true) : $menu_item->target; /** * Filter a navigation menu item's title attribute. * * @since 0.0.1 * * @param string $item_title The menu item title attribute. */ $menu_item->attr_title = !isset($menu_item->attr_title) ? apply_filters('nav_menu_attr_title', $menu_item->post_excerpt) : $menu_item->attr_title; if (!isset($menu_item->description)) { /** * Filter a navigation menu item's description. * * @since 0.0.1 * * @param string $description The menu item description. */ $menu_item->description = apply_filters('nav_menu_description', hq_trim_words($menu_item->post_content, 200)); } $menu_item->classes = !isset($menu_item->classes) ? (array) get_post_meta($menu_item->ID, '_menu_item_classes', true) : $menu_item->classes; $menu_item->xfn = !isset($menu_item->xfn) ? get_post_meta($menu_item->ID, '_menu_item_xfn', true) : $menu_item->xfn; } else { $menu_item->db_id = 0; $menu_item->menu_item_parent = 0; $menu_item->object_id = (int) $menu_item->ID; $menu_item->type = 'post_type'; $object = get_post_type_object($menu_item->post_type); $menu_item->object = $object->name; $menu_item->type_label = $object->labels->singular_name; if ('' === $menu_item->post_title) { /* translators: %d: ID of a post */ $menu_item->post_title = sprintf(__('#%d (no title)'), $menu_item->ID); } $menu_item->title = $menu_item->post_title; $menu_item->url = get_permalink($menu_item->ID); $menu_item->target = ''; /** This filter is documented in hq-includes/nav-menu.php */ $menu_item->attr_title = apply_filters('nav_menu_attr_title', ''); /** This filter is documented in hq-includes/nav-menu.php */ $menu_item->description = apply_filters('nav_menu_description', ''); $menu_item->classes = array(); $menu_item->xfn = ''; } } elseif (isset($menu_item->taxonomy)) { $menu_item->ID = $menu_item->term_id; $menu_item->db_id = 0; $menu_item->menu_item_parent = 0; $menu_item->object_id = (int) $menu_item->term_id; $menu_item->post_parent = (int) $menu_item->parent; $menu_item->type = 'taxonomy'; $object = get_taxonomy($menu_item->taxonomy); $menu_item->object = $object->name; $menu_item->type_label = $object->labels->singular_name; $menu_item->title = $menu_item->name; $menu_item->url = get_term_link($menu_item, $menu_item->taxonomy); $menu_item->target = ''; $menu_item->attr_title = ''; $menu_item->description = get_term_field('description', $menu_item->term_id, $menu_item->taxonomy); $menu_item->classes = array(); $menu_item->xfn = ''; } /** * Filter a navigation menu item object. * * @since 0.0.1 * * @param object $menu_item The menu item object. */ return apply_filters('hq_setup_nav_menu_item', $menu_item); }
/** * Kill HiveQueen execution and display HTML message with error message. * * This is the default handler for hq_die if you want a custom one for your * site then you can overload using the hq_die_handler filter in hq_die * * @since 0.0.1 * @access private * * @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 _default_hq_die_handler($message, $title = '', $args = array()) { $defaults = array('response' => 500); $r = hq_parse_args($args, $defaults); $have_gettext = function_exists('__'); if (function_exists('is_hq_error') && is_hq_error($message)) { if (empty($title)) { $error_data = $message->get_error_data(); if (is_array($error_data) && isset($error_data['title'])) { $title = $error_data['title']; } } $errors = $message->get_error_messages(); switch (count($errors)) { case 0: $message = ''; break; case 1: $message = "<p>{$errors[0]}</p>"; break; default: $message = "<ul>\n\t\t<li>" . join("</li>\n\t\t<li>", $errors) . "</li>\n\t</ul>"; break; } } elseif (is_string($message)) { $message = "<p>{$message}</p>"; } if (isset($r['back_link']) && $r['back_link']) { $back_text = $have_gettext ? __('« Back') : '« Back'; $message .= "\n<p><a href='javascript:history.back()'>{$back_text}</a></p>"; } if (!did_action('admin_head')) { if (!headers_sent()) { status_header($r['response']); nocache_headers(); header('Content-Type: text/html; charset=utf-8'); } if (empty($title)) { $title = $have_gettext ? __('HiveQueen › Error') : 'HiveQueen › Error'; } $text_direction = 'ltr'; if (isset($r['text_direction']) && 'rtl' == $r['text_direction']) { $text_direction = 'rtl'; } elseif (function_exists('is_rtl') && is_rtl()) { $text_direction = 'rtl'; } ?> <!DOCTYPE html> <!-- Ticket #11289, IE bug fix: always pad the error page with enough characters such that it is greater than 512 bytes, even after gzip compression abcdefghijklmnopqrstuvwxyz1234567890aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz11223344556677889900abacbcbdcdcededfefegfgfhghgihihjijikjkjlklkmlmlnmnmononpopoqpqprqrqsrsrtstsubcbcdcdedefefgfabcadefbghicjkldmnoepqrfstugvwxhyz1i234j567k890laabmbccnddeoeffpgghqhiirjjksklltmmnunoovppqwqrrxsstytuuzvvw0wxx1yyz2z113223434455666777889890091abc2def3ghi4jkl5mno6pqr7stu8vwx9yz11aab2bcc3dd4ee5ff6gg7hh8ii9j0jk1kl2lmm3nnoo4p5pq6qrr7ss8tt9uuvv0wwx1x2yyzz13aba4cbcb5dcdc6dedfef8egf9gfh0ghg1ihi2hji3jik4jkj5lkl6kml7mln8mnm9ono --> <html xmlns="http://www.w3.org/1999/xhtml" <?php if (function_exists('language_attributes') && function_exists('is_rtl')) { language_attributes(); } else { echo "dir='{$text_direction}'"; } ?> > <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width"> <title><?php echo $title; ?> </title> <style type="text/css"> html { background: #f1f1f1; } body { background: #fff; color: #444; font-family: "Open Sans", sans-serif; margin: 2em auto; padding: 1em 2em; max-width: 700px; -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.13); box-shadow: 0 1px 3px rgba(0,0,0,0.13); } h1 { border-bottom: 1px solid #dadada; clear: both; color: #666; font: 24px "Open Sans", sans-serif; margin: 30px 0 0 0; padding: 0; padding-bottom: 7px; } #error-page { margin-top: 50px; } #error-page p { font-size: 14px; line-height: 1.5; margin: 25px 0 20px; } #error-page code { font-family: Consolas, Monaco, monospace; } ul li { margin-bottom: 10px; font-size: 14px ; } a { color: #21759B; text-decoration: none; } a:hover { color: #D54E21; } .button { background: #f7f7f7; border: 1px solid #cccccc; color: #555; display: inline-block; text-decoration: none; font-size: 13px; line-height: 26px; height: 28px; margin: 0; padding: 0 10px 1px; cursor: pointer; -webkit-border-radius: 3px; -webkit-appearance: none; border-radius: 3px; white-space: nowrap; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; -webkit-box-shadow: inset 0 1px 0 #fff, 0 1px 0 rgba(0,0,0,.08); box-shadow: inset 0 1px 0 #fff, 0 1px 0 rgba(0,0,0,.08); vertical-align: top; } .button.button-large { height: 29px; line-height: 28px; padding: 0 12px; } .button:hover, .button:focus { background: #fafafa; border-color: #999; color: #222; } .button:focus { -webkit-box-shadow: 1px 1px 1px rgba(0,0,0,.2); box-shadow: 1px 1px 1px rgba(0,0,0,.2); } .button:active { background: #eee; border-color: #999; color: #333; -webkit-box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 ); box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 ); } <?php if ('rtl' == $text_direction) { ?> body { font-family: Tahoma, Arial; } <?php } ?> </style> </head> <body id="error-page"> <?php } // ! did_action( 'admin_head' ) ?> <?php echo $message; ?> </body> </html> <?php die; }
/** * Strips any invalid characters from the string for a given table and column. * * @since 0.0.1 * @access public * * @param string $table Table name. * @param string $column Column name. * @param string $value The text to check. * @return string|HQ_Error The converted string, or a HQ_Error object if the conversion fails. */ public function strip_invalid_text_for_column($table, $column, $value) { if (!is_string($value)) { return $value; } $charset = $this->get_col_charset($table, $column); if (!$charset) { // Not a string column. return $value; } elseif (is_hq_error($charset)) { // Bail on real errors. return $charset; } $data = array($column => array('value' => $value, 'charset' => $charset, 'length' => $this->get_col_length($table, $column))); $data = $this->strip_invalid_text($data); if (is_hq_error($data)) { return $data; } return $data[$column]['value']; }
/** * 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); }
/** * Set the database table prefix and the format specifiers for database * table columns. * * Columns not listed here default to `%s`. * * @since 0.0.1 * @access private * * @global hqdb $hqdb The HiveQueen database class. * @global string $table_prefix The database table prefix. */ function hq_set_hqdb_vars() { global $hqdb, $table_prefix; if (!empty($hqdb->error)) { dead_db(); } //TODO: Redefine db /* $hqdb->field_types = array( 'post_author' => '%d', 'post_parent' => '%d', 'menu_order' => '%d', 'term_id' => '%d', 'term_group' => '%d', 'term_taxonomy_id' => '%d', 'parent' => '%d', 'count' => '%d','object_id' => '%d', 'term_order' => '%d', 'ID' => '%d', 'comment_ID' => '%d', 'comment_post_ID' => '%d', 'comment_parent' => '%d', 'user_id' => '%d', 'link_id' => '%d', 'link_owner' => '%d', 'link_rating' => '%d', 'option_id' => '%d', 'blog_id' => '%d', 'meta_id' => '%d', 'post_id' => '%d', 'user_status' => '%d', 'umeta_id' => '%d', 'comment_karma' => '%d', 'comment_count' => '%d', // multisite: 'active' => '%d', 'cat_id' => '%d', 'deleted' => '%d', 'lang_id' => '%d', 'mature' => '%d', 'public' => '%d', 'site_id' => '%d', 'spam' => '%d', ); */ $hqdb->field_types = array('menu_order' => '%d', 'term_id' => '%d', 'term_group' => '%d', 'parent' => '%d', 'count' => '%d', 'object_id' => '%d', 'term_order' => '%d', 'ID' => '%d', 'user_id' => '%d', 'option_id' => '%d', 'user_status' => '%d'); $prefix = $hqdb->set_prefix($table_prefix); if (is_hq_error($prefix)) { hq_load_translations_early(); hq_die(__('<strong>ERROR</strong>: <code>$table_prefix</code> in <code>hq-config.php</code> can only contain numbers, letters, and underscores.')); } }
/** * Send a Trackback. * * Updates database when sending trackback to prevent duplicates. * * @since 0.0.1 * * @global hqdb $hqdb HiveQueen database abstraction object. * * @param string $trackback_url URL to send trackbacks. * @param string $title Title of post. * @param string $excerpt Excerpt of post. * @param int $ID Post ID. * @return int|false|void Database query from update. */ function trackback($trackback_url, $title, $excerpt, $ID) { global $hqdb; if (empty($trackback_url)) { return; } $options = array(); $options['timeout'] = 4; $options['body'] = array('title' => $title, 'url' => get_permalink($ID), 'blog_name' => get_option('blogname'), 'excerpt' => $excerpt); $response = hq_safe_remote_post($trackback_url, $options); if (is_hq_error($response)) { return; } $hqdb->query($hqdb->prepare("UPDATE {$hqdb->posts} SET pinged = CONCAT(pinged, '\n', %s) WHERE ID = %d", $trackback_url, $ID)); return $hqdb->query($hqdb->prepare("UPDATE {$hqdb->posts} SET to_ping = TRIM(REPLACE(to_ping, %s, '')) WHERE ID = %d", $trackback_url, $ID)); }
/** * 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; } }