Esempio n. 1
0
 /**
  * Parse a query string and set query type booleans.
  *
  * @since 0.0.1
  * @since 0.0.1 Introduced the ability to order by specific clauses of a `$meta_query`, by passing the clause's
  *              array key to `$orderby`.
  * @access public
  *
  * @param string|array $query {
  *     Optional. Array or string of Query parameters.
  *
  *     @type int          $attachment_id           Attachment post ID. Used for 'attachment' post_type.
  *     @type int|string   $author                  Author ID, or comma-separated list of IDs.
  *     @type string       $author_name             User 'user_nicename'.
  *     @type array        $author__in              An array of author IDs to query from.
  *     @type array        $author__not_in          An array of author IDs not to query from.
  *     @type bool         $cache_results           Whether to cache post information. Default true.
  *     @type int|string   $cat                     Category ID or comma-separated list of IDs (this or any children).
  *     @type array        $category__and           An array of category IDs (AND in).
  *     @type array        $category__in            An array of category IDs (OR in, no children).
  *     @type array        $category__not_in        An array of category IDs (NOT in).
  *     @type string       $category_name           Use category slug (not name, this or any children).
  *     @type int          $comments_per_page       The number of comments to return per page.
  *                                                 Default 'comments_per_page' option.
  *     @type int|string   $comments_popup          Whether the query is within the comments popup. Default empty.
  *     @type array        $date_query              An associative array of HQ_Date_Query arguments.
  *                                                 {@see HQ_Date_Query::__construct()}
  *     @type int          $day                     Day of the month. Default empty. Accepts numbers 1-31.
  *     @type bool         $exact                   Whether to search by exact keyword. Default false.
  *     @type string|array $fields                  Which fields to return. Single field or all fields (string),
  *                                                 or array of fields. 'id=>parent' uses 'id' and 'post_parent'.
  *                                                 Default all fields. Accepts 'ids', 'id=>parent'.
  *     @type int          $hour                    Hour of the day. Default empty. Accepts numbers 0-23.
  *     @type int|bool     $ignore_sticky_posts     Whether to ignore sticky posts or not. Setting this to false
  *                                                 excludes stickies from 'post__in'. Accepts 1|true, 0|false.
  *                                                 Default 0|false.
  *     @type int          $m                       Combination YearMonth. Accepts any four-digit year and month
  *                                                 numbers 1-12. Default empty.
  *     @type string       $meta_compare            Comparison operator to test the 'meta_value'.
  *     @type string       $meta_key                Custom field key.
  *     @type array        $meta_query              An associative array of HQ_Meta_Query arguments.
  *                                                 {@see HQ_Meta_Query->queries}
  *     @type string       $meta_value              Custom field value.
  *     @type int          $meta_value_num          Custom field value number.
  *     @type int          $menu_order              The menu order of the posts.
  *     @type int          $monthnum                The two-digit month. Default empty. Accepts numbers 1-12.
  *     @type string       $name                    Post slug.
  *     @type bool         $nopaging                Show all posts (true) or paginate (false). Default false.
  *     @type bool         $no_found_rows           Whether to skip counting the total rows found. Enabling can improve
  *                                                 performance. Default false.
  *     @type int          $offset                  The number of posts to offset before retrieval.
  *     @type string       $order                   Designates ascending or descending order of posts. Default 'DESC'.
  *                                                 Accepts 'ASC', 'DESC'.
  *     @type string|array $orderby                 Sort retrieved posts by parameter. One or more options may be
  *                                                 passed. To use 'meta_value', or 'meta_value_num',
  *                                                 'meta_key=keyname' must be also be defined. To sort by a
  *                                                 specific `$meta_query` clause, use that clause's array key.
  *                                                 Default 'date'. Accepts 'none', 'name', 'author', 'date',
  *                                                 'title', 'modified', 'menu_order', 'parent', 'ID', 'rand',
  *                                                 'comment_count', 'meta_value', 'meta_value_num', and the
  *                                                 array keys of `$meta_query`.
  *     @type int          $p                       Post ID.
  *     @type int          $page                    Show the number of posts that would show up on page X of a
  *                                                 static front page.
  *     @type int          $paged                   The number of the current page.
  *     @type int          $page_id                 Page ID.
  *     @type string       $pagename                Page slug.
  *     @type string       $perm                    Show posts if user has the appropriate capability.
  *     @type array        $post__in                An array of post IDs to retrieve, sticky posts will be included
  *     @type string       $post_mime_type          The mime type of the post. Used for 'attachment' post_type.
  *     @type array        $post__not_in            An array of post IDs not to retrieve. Note: a string of comma-
  *                                                 separated IDs will NOT work.
  *     @type int          $post_parent             Page ID to retrieve child pages for. Use 0 to only retrieve
  *                                                 top-level pages.
  *     @type array        $post_parent__in         An array containing parent page IDs to query child pages from.
  *     @type array        $post_parent__not_in     An array containing parent page IDs not to query child pages from.
  *     @type string|array $post_type               A post type slug (string) or array of post type slugs.
  *                                                 Default 'any' if using 'tax_query'.
  *     @type string|array $post_status             A post status (string) or array of post statuses.
  *     @type int          $posts_per_page          The number of posts to query for. Use -1 to request all posts.
  *     @type int          $posts_per_archive_page  The number of posts to query for by archive page. Overrides
  *                                                 'posts_per_page' when is_archive(), or is_search() are true.
  *     @type string       $s                       Search keyword.
  *     @type int          $second                  Second of the minute. Default empty. Accepts numbers 0-60.
  *     @type array        $search_terms            Array of search terms.
  *     @type bool         $sentence                Whether to search by phrase. Default false.
  *     @type bool         $suppress_filters        Whether to suppress filters. Default false.
  *     @type string       $tag                     Tag slug. Comma-separated (either), Plus-separated (all).
  *     @type array        $tag__and                An array of tag ids (AND in).
  *     @type array        $tag__in                 An array of tag ids (OR in).
  *     @type array        $tag__not_in             An array of tag ids (NOT in).
  *     @type int          $tag_id                  Tag id or comma-separated list of IDs.
  *     @type array        $tag_slug__and           An array of tag slugs (AND in).
  *     @type array        $tag_slug__in            An array of tag slugs (OR in). unless 'ignore_sticky_posts' is
  *                                                 true. Note: a string of comma-separated IDs will NOT work.
  *     @type array        $tax_query               An associative array of HQ_Tax_Query arguments.
  *                                                 {@see HQ_Tax_Query->queries}
  *     @type bool         $update_post_meta_cache  Whether to update the post meta cache. Default true.
  *     @type bool         $update_post_term_cache  Whether to update the post term cache. Default true.
  *     @type int          $w                       The week number of the year. Default empty. Accepts numbers 0-53.
  *     @type int          $year                    The four-digit year. Default empty. Accepts any four-digit year.
  * }
  */
 public function parse_query($query = '')
 {
     if (!empty($query)) {
         $this->init();
         $this->query = $this->query_vars = hq_parse_args($query);
     } elseif (!isset($this->query)) {
         $this->query = $this->query_vars;
     }
     $this->query_vars = $this->fill_query_vars($this->query_vars);
     $qv =& $this->query_vars;
     $this->query_vars_changed = true;
     if (!empty($qv['robots'])) {
         $this->is_robots = true;
     }
     $qv['p'] = absint($qv['p']);
     $qv['page_id'] = absint($qv['page_id']);
     $qv['year'] = absint($qv['year']);
     $qv['monthnum'] = absint($qv['monthnum']);
     $qv['day'] = absint($qv['day']);
     $qv['w'] = absint($qv['w']);
     $qv['m'] = preg_replace('|[^0-9]|', '', $qv['m']);
     $qv['paged'] = absint($qv['paged']);
     $qv['cat'] = preg_replace('|[^0-9,-]|', '', $qv['cat']);
     // comma separated list of positive or negative integers
     $qv['author'] = preg_replace('|[^0-9,-]|', '', $qv['author']);
     // comma separated list of positive or negative integers
     $qv['pagename'] = trim($qv['pagename']);
     $qv['name'] = trim($qv['name']);
     if ('' !== $qv['hour']) {
         $qv['hour'] = absint($qv['hour']);
     }
     if ('' !== $qv['minute']) {
         $qv['minute'] = absint($qv['minute']);
     }
     if ('' !== $qv['second']) {
         $qv['second'] = absint($qv['second']);
     }
     if ('' !== $qv['menu_order']) {
         $qv['menu_order'] = absint($qv['menu_order']);
     }
     // Fairly insane upper bound for search string lengths.
     if (!is_scalar($qv['s']) || !empty($qv['s']) && strlen($qv['s']) > 1600) {
         $qv['s'] = '';
     }
     // Compat. Map subpost to attachment.
     if ('' != $qv['subpost']) {
         $qv['attachment'] = $qv['subpost'];
     }
     if ('' != $qv['subpost_id']) {
         $qv['attachment_id'] = $qv['subpost_id'];
     }
     $qv['attachment_id'] = absint($qv['attachment_id']);
     if ('' != $qv['attachment'] || !empty($qv['attachment_id'])) {
         $this->is_single = true;
         $this->is_attachment = true;
     } elseif ('' != $qv['name']) {
         $this->is_single = true;
     } elseif ($qv['p']) {
         $this->is_single = true;
     } elseif ('' !== $qv['hour'] && '' !== $qv['minute'] && '' !== $qv['second'] && '' != $qv['year'] && '' != $qv['monthnum'] && '' != $qv['day']) {
         // If year, month, day, hour, minute, and second are set, a single
         // post is being queried.
         $this->is_single = true;
     } elseif ('' != $qv['static'] || '' != $qv['pagename'] || !empty($qv['page_id'])) {
         $this->is_page = true;
         $this->is_single = false;
     } else {
         // Look for archive queries. Dates, categories, authors, search, post type archives.
         if (isset($this->query['s'])) {
             $this->is_search = true;
         }
         if ('' !== $qv['second']) {
             $this->is_time = true;
             $this->is_date = true;
         }
         if ('' !== $qv['minute']) {
             $this->is_time = true;
             $this->is_date = true;
         }
         if ('' !== $qv['hour']) {
             $this->is_time = true;
             $this->is_date = true;
         }
         if ($qv['day']) {
             if (!$this->is_date) {
                 $date = sprintf('%04d-%02d-%02d', $qv['year'], $qv['monthnum'], $qv['day']);
                 if ($qv['monthnum'] && $qv['year'] && !hq_checkdate($qv['monthnum'], $qv['day'], $qv['year'], $date)) {
                     $qv['error'] = '404';
                 } else {
                     $this->is_day = true;
                     $this->is_date = true;
                 }
             }
         }
         if ($qv['monthnum']) {
             if (!$this->is_date) {
                 if (12 < $qv['monthnum']) {
                     $qv['error'] = '404';
                 } else {
                     $this->is_month = true;
                     $this->is_date = true;
                 }
             }
         }
         if ($qv['year']) {
             if (!$this->is_date) {
                 $this->is_year = true;
                 $this->is_date = true;
             }
         }
         if ($qv['m']) {
             $this->is_date = true;
             if (strlen($qv['m']) > 9) {
                 $this->is_time = true;
             } elseif (strlen($qv['m']) > 7) {
                 $this->is_day = true;
             } elseif (strlen($qv['m']) > 5) {
                 $this->is_month = true;
             } else {
                 $this->is_year = true;
             }
         }
         if ('' != $qv['w']) {
             $this->is_date = true;
         }
         $this->query_vars_hash = false;
         //TODO: Goyo no taxonomy
         //$this->parse_tax_query( $qv );
         //TODO: Goyo no taxonomy
         /*
         foreach ( $this->tax_query->queries as $tax_query ) {
                 if ( ! is_array( $tax_query ) ) {
                         continue;
                 }
         
                 if ( isset( $tax_query['operator'] ) && 'NOT IN' != $tax_query['operator'] ) {
                         switch ( $tax_query['taxonomy'] ) {
                                 case 'category':
                                         $this->is_category = true;
                                         break;
                                 case 'post_tag':
                                         $this->is_tag = true;
                                         break;
                                 default:
                                         $this->is_tax = true;
                         }
                 }
         }
         unset( $tax_query );
         */
         if (empty($qv['author']) || $qv['author'] == '0') {
             $this->is_author = false;
         } else {
             $this->is_author = true;
         }
         if ('' != $qv['author_name']) {
             $this->is_author = true;
         }
         if (!empty($qv['post_type']) && !is_array($qv['post_type'])) {
             $post_type_obj = get_post_type_object($qv['post_type']);
             if (!empty($post_type_obj->has_archive)) {
                 $this->is_post_type_archive = true;
             }
         }
         if ($this->is_post_type_archive || $this->is_date || $this->is_author || $this->is_category || $this->is_tag || $this->is_tax) {
             $this->is_archive = true;
         }
     }
     if ('' != $qv['feed']) {
         $this->is_feed = true;
     }
     if ('' != $qv['tb']) {
         $this->is_trackback = true;
     }
     if ('' != $qv['paged'] && intval($qv['paged']) > 1) {
         $this->is_paged = true;
     }
     if ('' != $qv['comments_popup']) {
         $this->is_comments_popup = true;
     }
     // if we're previewing inside the write screen
     if ('' != $qv['preview']) {
         $this->is_preview = true;
     }
     if (is_admin()) {
         $this->is_admin = true;
     }
     if (false !== strpos($qv['feed'], 'comments-')) {
         $qv['feed'] = str_replace('comments-', '', $qv['feed']);
         $qv['withcomments'] = 1;
     }
     $this->is_singular = $this->is_single || $this->is_page || $this->is_attachment;
     if ($this->is_feed && (!empty($qv['withcomments']) || empty($qv['withoutcomments']) && $this->is_singular)) {
         $this->is_comment_feed = true;
     }
     if (!($this->is_singular || $this->is_archive || $this->is_search || $this->is_feed || $this->is_trackback || $this->is_404 || $this->is_admin || $this->is_comments_popup || $this->is_robots)) {
         $this->is_home = true;
     }
     // Correct is_* for page_on_front and page_for_posts
     if ($this->is_home && 'page' == get_option('show_on_front') && get_option('page_on_front')) {
         $_query = hq_parse_args($this->query);
         // pagename can be set and empty depending on matched rewrite rules. Ignore an empty pagename.
         if (isset($_query['pagename']) && '' == $_query['pagename']) {
             unset($_query['pagename']);
         }
         if (empty($_query) || !array_diff(array_keys($_query), array('preview', 'page', 'paged', 'cpage'))) {
             $this->is_page = true;
             $this->is_home = false;
             $qv['page_id'] = get_option('page_on_front');
             // Correct <!--nextpage--> for page_on_front
             if (!empty($qv['paged'])) {
                 $qv['page'] = $qv['paged'];
                 unset($qv['paged']);
             }
         }
     }
     if ('' != $qv['pagename']) {
         $this->queried_object = get_page_by_path($qv['pagename']);
         if (!empty($this->queried_object)) {
             $this->queried_object_id = (int) $this->queried_object->ID;
         } else {
             unset($this->queried_object);
         }
         if ('page' == get_option('show_on_front') && isset($this->queried_object_id) && $this->queried_object_id == get_option('page_for_posts')) {
             $this->is_page = false;
             $this->is_home = true;
             $this->is_posts_page = true;
         }
     }
     if ($qv['page_id']) {
         if ('page' == get_option('show_on_front') && $qv['page_id'] == get_option('page_for_posts')) {
             $this->is_page = false;
             $this->is_home = true;
             $this->is_posts_page = true;
         }
     }
     if (!empty($qv['post_type'])) {
         if (is_array($qv['post_type'])) {
             $qv['post_type'] = array_map('sanitize_key', $qv['post_type']);
         } else {
             $qv['post_type'] = sanitize_key($qv['post_type']);
         }
     }
     if (!empty($qv['post_status'])) {
         if (is_array($qv['post_status'])) {
             $qv['post_status'] = array_map('sanitize_key', $qv['post_status']);
         } else {
             $qv['post_status'] = preg_replace('|[^a-z0-9_,-]|', '', $qv['post_status']);
         }
     }
     if ($this->is_posts_page && (!isset($qv['withcomments']) || !$qv['withcomments'])) {
         $this->is_comment_feed = false;
     }
     $this->is_singular = $this->is_single || $this->is_page || $this->is_attachment;
     // Done correcting is_* for page_on_front and page_for_posts
     if ('404' == $qv['error']) {
         //print("Is set 404");
         $this->set_404();
     }
     $this->query_vars_hash = md5(serialize($this->query_vars));
     $this->query_vars_changed = false;
     /**
      * Fires after the main query vars have been parsed.
      *
      * @since 0.0.1
      *
      * @param HQ_Query &$this The HQ_Query instance (passed by reference).
      */
     do_action_ref_array('parse_query', array(&$this));
 }
Esempio n. 2
0
/**
 * Insert or update a post.
 *
 * If the $postarr parameter has 'ID' set to a value, then post will be updated.
 *
 * You can set the post date manually, by setting the values for 'post_date'
 * and 'post_date_gmt' keys. You can close the comments or open the comments by
 * setting the value for 'comment_status' key.
 *
 * @since 0.0.1
 * @since 0.0.1
 *
 * @see sanitize_post()
 * @global hqdb $hqdb HiveQueen database abstraction object.
 *
 * @param array $postarr {
 *     An array of elements that make up a post to update or insert.
 *
 *     @type int    $ID                    The post ID. If equal to something other than 0,
 *                                         the post with that ID will be updated. Default 0.
 *     @type int    $post_author           The ID of the user who added the post. Default is
 *                                         the current user ID.
 *     @type string $post_date             The date of the post. Default is the current time.
 *     @type string $post_date_gmt         The date of the post in the GMT timezone. Default is
 *                                         the value of `$post_date`.
 *     @type mixed  $post_content          The post content. Default empty.
 *     @type string $post_content_filtered The filtered post content. Default empty.
 *     @type string $post_title            The post title. Default empty.
 *     @type string $post_excerpt          The post excerpt. Default empty.
 *     @type string $post_status           The post status. Default 'draft'.
 *     @type string $post_type             The post type. Default 'post'.
 *     @type string $comment_status        Whether the post can accept comments. Accepts 'open' or 'closed'.
 *                                         Default is the value of 'default_comment_status' option.
 *     @type string $ping_status           Whether the post can accept pings. Accepts 'open' or 'closed'.
 *                                         Default is the value of 'default_ping_status' option.
 *     @type string $post_password         The password to access the post. Default empty.
 *     @type string $post_name             The post name. Default is the sanitized post title.
 *     @type string $to_ping               Space or carriage return-separated list of URLs to ping.
 *                                         Default empty.
 *     @type string $pinged                Space or carriage return-separated list of URLs that have
 *                                         been pinged. Default empty.
 *     @type string $post_modified         The date when the post was last modified. Default is
 *                                         the current time.
 *     @type string $post_modified_gmt     The date when the post was last modified in the GMT
 *                                         timezone. Default is the current time.
 *     @type int    $post_parent           Set this for the post it belongs to, if any. Default 0.
 *     @type int    $menu_order            The order the post should be displayed in. Default 0.
 *     @type string $post_mime_type        The mime type of the post. Default empty.
 *     @type string $guid                  Global Unique ID for referencing the post. Default empty.
 * }
 * @param bool  $hq_error Optional. Whether to allow return of HQ_Error on failure. Default false.
 * @return int|HQ_Error The post ID on success. The value 0 or HQ_Error on failure.
 */
function hq_insert_post($postarr, $hq_error = false)
{
    global $hqdb;
    $user_id = get_current_user_id();
    $defaults = array('post_author' => $user_id, 'post_content' => '', 'post_content_filtered' => '', 'post_title' => '', 'post_excerpt' => '', 'post_status' => 'draft', 'post_type' => 'post', 'comment_status' => '', 'ping_status' => '', 'post_password' => '', 'to_ping' => '', 'pinged' => '', 'post_parent' => 0, 'menu_order' => 0, 'guid' => '', 'import_id' => 0, 'context' => '');
    $postarr = hq_parse_args($postarr, $defaults);
    unset($postarr['filter']);
    $postarr = sanitize_post($postarr, 'db');
    // Are we updating or creating?
    $post_ID = 0;
    $update = false;
    $guid = $postarr['guid'];
    if (!empty($postarr['ID'])) {
        $update = true;
        // Get the post ID and GUID.
        $post_ID = $postarr['ID'];
        $post_before = get_post($post_ID);
        if (is_null($post_before)) {
            if ($hq_error) {
                return new HQ_Error('invalid_post', __('Invalid post ID.'));
            }
            return 0;
        }
        $guid = get_post_field('guid', $post_ID);
        $previous_status = get_post_field('post_status', $post_ID);
    } else {
        $previous_status = 'new';
    }
    $post_type = empty($postarr['post_type']) ? 'post' : $postarr['post_type'];
    $post_title = $postarr['post_title'];
    $post_content = $postarr['post_content'];
    $post_excerpt = $postarr['post_excerpt'];
    if (isset($postarr['post_name'])) {
        $post_name = $postarr['post_name'];
    }
    $maybe_empty = 'attachment' !== $post_type && !$post_content && !$post_title && !$post_excerpt && post_type_supports($post_type, 'editor') && post_type_supports($post_type, 'title') && post_type_supports($post_type, 'excerpt');
    /**
     * Filter whether the post should be considered "empty".
     *
     * The post is considered "empty" if both:
     * 1. The post type supports the title, editor, and excerpt fields
     * 2. The title, editor, and excerpt fields are all empty
     *
     * Returning a truthy value to the filter will effectively short-circuit
     * the new post being inserted, returning 0. If $hq_error is true, a HQ_Error
     * will be returned instead.
     *
     * @since 0.0.1
     *
     * @param bool  $maybe_empty Whether the post should be considered "empty".
     * @param array $postarr     Array of post data.
     */
    if (apply_filters('hq_insert_post_empty_content', $maybe_empty, $postarr)) {
        if ($hq_error) {
            return new HQ_Error('empty_content', __('Content, title, and excerpt are empty.'));
        } else {
            return 0;
        }
    }
    $post_status = empty($postarr['post_status']) ? 'draft' : $postarr['post_status'];
    if ('attachment' === $post_type && !in_array($post_status, array('inherit', 'private', 'trash'))) {
        $post_status = 'inherit';
    }
    if (!empty($postarr['post_category'])) {
        // Filter out empty terms.
        $post_category = array_filter($postarr['post_category']);
    }
    // Make sure we set a valid category.
    if (empty($post_category) || 0 == count($post_category) || !is_array($post_category)) {
        // 'post' requires at least one category.
        if ('post' == $post_type && 'auto-draft' != $post_status) {
            $post_category = array(get_option('default_category'));
        } else {
            $post_category = array();
        }
    }
    // Don't allow contributors to set the post slug for pending review posts.
    if ('pending' == $post_status && !current_user_can('publish_posts')) {
        $post_name = '';
    }
    /*
     * Create a valid post name. Drafts and pending posts are allowed to have
     * an empty post name.
     */
    if (empty($post_name)) {
        if (!in_array($post_status, array('draft', 'pending', 'auto-draft'))) {
            $post_name = sanitize_title($post_title);
        } else {
            $post_name = '';
        }
    } else {
        // On updates, we need to check to see if it's using the old, fixed sanitization context.
        $check_name = sanitize_title($post_name, '', 'old-save');
        if ($update && strtolower(urlencode($post_name)) == $check_name && get_post_field('post_name', $post_ID) == $check_name) {
            $post_name = $check_name;
        } else {
            // new post, or slug has changed.
            $post_name = sanitize_title($post_name);
        }
    }
    /*
     * If the post date is empty (due to having been new or a draft) and status
     * is not 'draft' or 'pending', set date to now.
     */
    if (empty($postarr['post_date']) || '0000-00-00 00:00:00' == $postarr['post_date']) {
        $post_date = current_time('mysql');
    } else {
        $post_date = $postarr['post_date'];
    }
    // Validate the date.
    $mm = substr($post_date, 5, 2);
    $jj = substr($post_date, 8, 2);
    $aa = substr($post_date, 0, 4);
    $valid_date = hq_checkdate($mm, $jj, $aa, $post_date);
    if (!$valid_date) {
        if ($hq_error) {
            return new HQ_Error('invalid_date', __('Whoops, the provided date is invalid.'));
        } else {
            return 0;
        }
    }
    if (empty($postarr['post_date_gmt']) || '0000-00-00 00:00:00' == $postarr['post_date_gmt']) {
        if (!in_array($post_status, array('draft', 'pending', 'auto-draft'))) {
            $post_date_gmt = get_gmt_from_date($post_date);
        } else {
            $post_date_gmt = '0000-00-00 00:00:00';
        }
    } else {
        $post_date_gmt = $postarr['post_date_gmt'];
    }
    if ($update || '0000-00-00 00:00:00' == $post_date) {
        $post_modified = current_time('mysql');
        $post_modified_gmt = current_time('mysql', 1);
    } else {
        $post_modified = $post_date;
        $post_modified_gmt = $post_date_gmt;
    }
    if ('attachment' !== $post_type) {
        if ('publish' == $post_status) {
            $now = gmdate('Y-m-d H:i:59');
            if (mysql2date('U', $post_date_gmt, false) > mysql2date('U', $now, false)) {
                $post_status = 'future';
            }
        } elseif ('future' == $post_status) {
            $now = gmdate('Y-m-d H:i:59');
            if (mysql2date('U', $post_date_gmt, false) <= mysql2date('U', $now, false)) {
                $post_status = 'publish';
            }
        }
    }
    // Comment status.
    if (empty($postarr['comment_status'])) {
        if ($update) {
            $comment_status = 'closed';
        } else {
            $comment_status = get_default_comment_status($post_type);
        }
    } else {
        $comment_status = $postarr['comment_status'];
    }
    // These variables are needed by compact() later.
    $post_content_filtered = $postarr['post_content_filtered'];
    $post_author = empty($postarr['post_author']) ? $user_id : $postarr['post_author'];
    $ping_status = empty($postarr['ping_status']) ? get_default_comment_status($post_type, 'pingback') : $postarr['ping_status'];
    $to_ping = isset($postarr['to_ping']) ? sanitize_trackback_urls($postarr['to_ping']) : '';
    $pinged = isset($postarr['pinged']) ? $postarr['pinged'] : '';
    $import_id = isset($postarr['import_id']) ? $postarr['import_id'] : 0;
    /*
     * The 'hq_insert_post_parent' filter expects all variables to be present.
     * Previously, these variables would have already been extracted
     */
    if (isset($postarr['menu_order'])) {
        $menu_order = (int) $postarr['menu_order'];
    } else {
        $menu_order = 0;
    }
    $post_password = isset($postarr['post_password']) ? $postarr['post_password'] : '';
    if ('private' == $post_status) {
        $post_password = '';
    }
    if (isset($postarr['post_parent'])) {
        $post_parent = (int) $postarr['post_parent'];
    } else {
        $post_parent = 0;
    }
    /**
     * Filter the post parent -- used to check for and prevent hierarchy loops.
     *
     * @since 0.0.1
     *
     * @param int   $post_parent Post parent ID.
     * @param int   $post_ID     Post ID.
     * @param array $new_postarr Array of parsed post data.
     * @param array $postarr     Array of sanitized, but otherwise unmodified post data.
     */
    $post_parent = apply_filters('hq_insert_post_parent', $post_parent, $post_ID, compact(array_keys($postarr)), $postarr);
    $post_name = hq_unique_post_slug($post_name, $post_ID, $post_status, $post_type, $post_parent);
    // Don't unslash.
    $post_mime_type = isset($postarr['post_mime_type']) ? $postarr['post_mime_type'] : '';
    // Expected_slashed (everything!).
    $data = compact('post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_content_filtered', 'post_title', 'post_excerpt', 'post_status', 'post_type', 'comment_status', 'ping_status', 'post_password', 'post_name', 'to_ping', 'pinged', 'post_modified', 'post_modified_gmt', 'post_parent', 'menu_order', 'post_mime_type', 'guid');
    $emoji_fields = array('post_title', 'post_content', 'post_excerpt');
    foreach ($emoji_fields as $emoji_field) {
        if (isset($data[$emoji_field])) {
            $charset = $hqdb->get_col_charset($hqdb->posts, $emoji_field);
            if ('utf8' === $charset) {
                $data[$emoji_field] = hq_encode_emoji($data[$emoji_field]);
            }
        }
    }
    if ('attachment' === $post_type) {
        /**
         * Filter attachment post data before it is updated in or added to the database.
         *
         * @since 0.0.1
         *
         * @param array $data    An array of sanitized attachment post data.
         * @param array $postarr An array of unsanitized attachment post data.
         */
        $data = apply_filters('hq_insert_attachment_data', $data, $postarr);
    } else {
        /**
         * Filter slashed post data just before it is inserted into the database.
         *
         * @since 0.0.1
         *
         * @param array $data    An array of slashed post data.
         * @param array $postarr An array of sanitized, but otherwise unmodified post data.
         */
        $data = apply_filters('hq_insert_post_data', $data, $postarr);
    }
    $data = hq_unslash($data);
    $where = array('ID' => $post_ID);
    if ($update) {
        /**
         * Fires immediately before an existing post is updated in the database.
         *
         * @since 0.0.1
         *
         * @param int   $post_ID Post ID.
         * @param array $data    Array of unslashed post data.
         */
        do_action('pre_post_update', $post_ID, $data);
        if (false === $hqdb->update($hqdb->posts, $data, $where)) {
            if ($hq_error) {
                return new HQ_Error('db_update_error', __('Could not update post in the database'), $hqdb->last_error);
            } else {
                return 0;
            }
        }
    } else {
        // If there is a suggested ID, use it if not already present.
        if (!empty($import_id)) {
            $import_id = (int) $import_id;
            if (!$hqdb->get_var($hqdb->prepare("SELECT ID FROM {$hqdb->posts} WHERE ID = %d", $import_id))) {
                $data['ID'] = $import_id;
            }
        }
        if (false === $hqdb->insert($hqdb->posts, $data)) {
            if ($hq_error) {
                return new HQ_Error('db_insert_error', __('Could not insert post into the database'), $hqdb->last_error);
            } else {
                return 0;
            }
        }
        $post_ID = (int) $hqdb->insert_id;
        // Use the newly generated $post_ID.
        $where = array('ID' => $post_ID);
    }
    if (empty($data['post_name']) && !in_array($data['post_status'], array('draft', 'pending', 'auto-draft'))) {
        $data['post_name'] = hq_unique_post_slug(sanitize_title($data['post_title'], $post_ID), $post_ID, $data['post_status'], $post_type, $post_parent);
        $hqdb->update($hqdb->posts, array('post_name' => $data['post_name']), $where);
        clean_post_cache($post_ID);
    }
    if (is_object_in_taxonomy($post_type, 'category')) {
        hq_set_post_categories($post_ID, $post_category);
    }
    if (isset($postarr['tags_input']) && is_object_in_taxonomy($post_type, 'post_tag')) {
        hq_set_post_tags($post_ID, $postarr['tags_input']);
    }
    // New-style support for all custom taxonomies.
    if (!empty($postarr['tax_input'])) {
        foreach ($postarr['tax_input'] as $taxonomy => $tags) {
            $taxonomy_obj = get_taxonomy($taxonomy);
            // array = hierarchical, string = non-hierarchical.
            if (is_array($tags)) {
                $tags = array_filter($tags);
            }
            if (current_user_can($taxonomy_obj->cap->assign_terms)) {
                hq_set_post_terms($post_ID, $tags, $taxonomy);
            }
        }
    }
    $current_guid = get_post_field('guid', $post_ID);
    // Set GUID.
    if (!$update && '' == $current_guid) {
        $hqdb->update($hqdb->posts, array('guid' => get_permalink($post_ID)), $where);
    }
    if ('attachment' === $postarr['post_type']) {
        if (!empty($postarr['file'])) {
            update_attached_file($post_ID, $postarr['file']);
        }
        if (!empty($postarr['context'])) {
            add_post_meta($post_ID, '_hq_attachment_context', $postarr['context'], true);
        }
    }
    //TODO: Goyo no cache
    //clean_post_cache( $post_ID );
    $post = get_post($post_ID);
    if (!empty($postarr['page_template']) && 'page' == $data['post_type']) {
        $post->page_template = $postarr['page_template'];
        $page_templates = hq_get_theme()->get_page_templates($post);
        if ('default' != $postarr['page_template'] && !isset($page_templates[$postarr['page_template']])) {
            if ($hq_error) {
                return new HQ_Error('invalid_page_template', __('The page template is invalid.'));
            }
            update_post_meta($post_ID, '_hq_page_template', 'default');
        } else {
            update_post_meta($post_ID, '_hq_page_template', $postarr['page_template']);
        }
    }
    if ('attachment' !== $postarr['post_type']) {
        hq_transition_post_status($data['post_status'], $previous_status, $post);
    } else {
        if ($update) {
            /**
             * Fires once an existing attachment has been updated.
             *
             * @since 0.0.1
             *
             * @param int $post_ID Attachment ID.
             */
            do_action('edit_attachment', $post_ID);
        } else {
            /**
             * Fires once an attachment has been added.
             *
             * @since 0.0.1
             *
             * @param int $post_ID Attachment ID.
             */
            do_action('add_attachment', $post_ID);
        }
        return $post_ID;
    }
    if ($update) {
        /**
         * Fires once an existing post has been updated.
         *
         * @since 0.0.1
         *
         * @param int     $post_ID Post ID.
         * @param HQ_Post $post    Post object.
         */
        do_action('edit_post', $post_ID, $post);
        $post_after = get_post($post_ID);
        /**
         * Fires once an existing post has been updated.
         *
         * @since 0.0.1
         *
         * @param int     $post_ID      Post ID.
         * @param HQ_Post $post_after   Post object following the update.
         * @param HQ_Post $post_before  Post object before the update.
         */
        do_action('post_updated', $post_ID, $post_after, $post_before);
    }
    /**
     * Fires once a post has been saved.
     *
     * The dynamic portion of the hook name, `$post->post_type`, refers to
     * the post type slug.
     *
     * @since 0.0.1
     *
     * @param int     $post_ID Post ID.
     * @param HQ_Post $post    Post object.
     * @param bool    $update  Whether this is an existing post being updated or not.
     */
    do_action("save_post_{$post->post_type}", $post_ID, $post, $update);
    /**
     * Fires once a post has been saved.
     *
     * @since 0.0.1
     *
     * @param int     $post_ID Post ID.
     * @param HQ_Post $post    Post object.
     * @param bool    $update  Whether this is an existing post being updated or not.
     */
    do_action('save_post', $post_ID, $post, $update);
    /**
     * Fires once a post has been saved.
     *
     * @since 0.0.1
     *
     * @param int     $post_ID Post ID.
     * @param HQ_Post $post    Post object.
     * @param bool    $update  Whether this is an existing post being updated or not.
     */
    do_action('hq_insert_post', $post_ID, $post, $update);
    return $post_ID;
}