/** * Register a post type. Do not use before init. * * A function for creating or modifying a post type based on the * parameters given. The function will accept an array (second optional * parameter), along with a string for the post type name. * * @since 2.9.0 * @since 3.0.0 The `show_ui` argument is now enforced on the new post screen. * @since 4.4.0 The `show_ui` argument is now enforced on the post type listing screen and post editing screen. * * @global array $wp_post_types List of post types. * @global WP_Rewrite $wp_rewrite Used for default feeds. * @global WP $wp Used to add query vars. * * @param string $post_type Post type key, must not exceed 20 characters. * @param array|string $args { * Array or string of arguments for registering a post type. * * @type string $label Name of the post type shown in the menu. Usually plural. * Default is value of $labels['name']. * @type array $labels An array of labels for this post type. If not set, post * labels are inherited for non-hierarchical types and page * labels for hierarchical ones. {@see get_post_type_labels()}. * @type string $description A short descriptive summary of what the post type is. * Default empty. * @type bool $public Whether a post type is intended for use publicly either via * the admin interface or by front-end users. While the default * settings of $exclude_from_search, $publicly_queryable, $show_ui, * and $show_in_nav_menus are inherited from public, each does not * rely on this relationship and controls a very specific intention. * Default false. * @type bool $hierarchical Whether the post type is hierarchical (e.g. page). Default false. * @type bool $exclude_from_search Whether to exclude posts with this post type from front end search * results. Default is the opposite value of $public. * @type bool $publicly_queryable Whether queries can be performed on the front end for the post type * as part of {@see parse_request()}. Endpoints would include: * * ?post_type={post_type_key} * * ?{post_type_key}={single_post_slug} * * ?{post_type_query_var}={single_post_slug} * If not set, the default is inherited from $public. * @type bool $show_ui Whether to generate and allow a UI for managing this post type in the * admin. Default is value of $public. * @type bool $show_in_menu Where to show the post type in the admin menu. To work, $show_ui * must be true. If true, the post type is shown in its own top level * menu. If false, no menu is shown. If a string of an existing top * level menu (eg. 'tools.php' or 'edit.php?post_type=page'), the post * type will be placed as a sub-menu of that. * Default is value of $show_ui. * @type bool $show_in_nav_menus Makes this post type available for selection in navigation menus. * Default is value $public. * @type bool $show_in_admin_bar Makes this post type available via the admin bar. Default is value * of $show_in_menu. * @type int $menu_position The position in the menu order the post type should appear. To work, * $show_in_menu must be true. Default null (at the bottom). * @type string $menu_icon The url to the icon to be used for this menu. Pass a base64-encoded * SVG using a data URI, which will be colored to match the color scheme * -- this should begin with 'data:image/svg+xml;base64,'. Pass the name * of a Dashicons helper class to use a font icon, e.g. * 'dashicons-chart-pie'. Pass 'none' to leave div.wp-menu-image empty * so an icon can be added via CSS. Defaults to use the posts icon. * @type string $capability_type The string to use to build the read, edit, and delete capabilities. * May be passed as an array to allow for alternative plurals when using * this argument as a base to construct the capabilities, e.g. * array('story', 'stories'). Default 'post'. * @type array $capabilities Array of capabilities for this post type. $capability_type is used * as a base to construct capabilities by default. * {@see get_post_type_capabilities()}. * @type bool $map_meta_cap Whether to use the internal default meta capability handling. * Default false. * @type array $supports An alias for calling {@see add_post_type_support()} directly. * Defaults to array containing 'title' & 'editor'. * @type callable $register_meta_box_cb Provide a callback function that sets up the meta boxes for the * edit form. Do remove_meta_box() and add_meta_box() calls in the * callback. Default null. * @type array $taxonomies An array of taxonomy identifiers that will be registered for the * post type. Taxonomies can be registered later with * {@see register_taxonomy()} or {@see register_taxonomy_for_object_type()}. * Default empty array. * @type bool|string $has_archive Whether there should be post type archives, or if a string, the * archive slug to use. Will generate the proper rewrite rules if * $rewrite is enabled. Default false. * @type bool|array $rewrite { * Triggers the handling of rewrites for this post type. To prevent rewrite, set to false. * Defaults to true, using $post_type as slug. To specify rewrite rules, an array can be * passed with any of these keys: * * @type string $slug Customize the permastruct slug. Defaults to $post_type key. * @type bool $with_front Whether the permastruct should be prepended with WP_Rewrite::$front. * Default true. * @type bool $feeds Whether the feed permastruct should be built for this post type. * Default is value of $has_archive. * @type bool $pages Whether the permastruct should provide for pagination. Default true. * @type const $ep_mask Endpoint mask to assign. If not specified and permalink_epmask is set, * inherits from $permalink_epmask. If not specified and permalink_epmask * is not set, defaults to EP_PERMALINK. * } * @type string|bool $query_var Sets the query_var key for this post type. Defaults to $post_type * key. If false, a post type cannot be loaded at * ?{query_var}={post_slug}. If specified as a string, the query * ?{query_var_string}={post_slug} will be valid. * @type bool $can_export Whether to allow this post type to be exported. Default true. * @type bool $delete_with_user Whether to delete posts of this type when deleting a user. If true, * posts of this type belonging to the user will be moved to trash * when then user is deleted. If false, posts of this type belonging * to the user will *not* be trashed or deleted. If not set (the default), * posts are trashed if post_type_supports('author'). Otherwise posts * are not trashed or deleted. Default null. * @type bool $_builtin FOR INTERNAL USE ONLY! True if this post type is a native or * "built-in" post_type. Default false. * @type string $_edit_link FOR INTERNAL USE ONLY! URL segment to use for edit link of * this post type. Default 'post.php?post=%d'. * } * @return object|WP_Error The registered post type object, or an error object. */ function register_post_type($post_type, $args = array()) { global $wp_post_types, $wp_rewrite, $wp; if (!is_array($wp_post_types)) { $wp_post_types = array(); } // Sanitize post type name $post_type = sanitize_key($post_type); $args = wp_parse_args($args); /** * Filter the arguments for registering a post type. * * @since 4.4.0 * * @param array $args Array of arguments for registering a post type. * @param string $post_type Post type key. */ $args = apply_filters('register_post_type_args', $args, $post_type); $has_edit_link = !empty($args['_edit_link']); // Args prefixed with an underscore are reserved for internal use. $defaults = array('labels' => array(), 'description' => '', 'public' => false, 'hierarchical' => false, 'exclude_from_search' => null, 'publicly_queryable' => null, 'show_ui' => null, 'show_in_menu' => null, 'show_in_nav_menus' => null, 'show_in_admin_bar' => null, 'menu_position' => null, 'menu_icon' => null, 'capability_type' => 'post', 'capabilities' => array(), 'map_meta_cap' => null, 'supports' => array(), 'register_meta_box_cb' => null, 'taxonomies' => array(), 'has_archive' => false, 'rewrite' => true, 'query_var' => true, 'can_export' => true, 'delete_with_user' => null, '_builtin' => false, '_edit_link' => 'post.php?post=%d'); $args = array_merge($defaults, $args); $args = (object) $args; $args->name = $post_type; if (empty($post_type) || strlen($post_type) > 20) { _doing_it_wrong(__FUNCTION__, __('Post type names must be between 1 and 20 characters in length.'), '4.2'); return new WP_Error('post_type_length_invalid', __('Post type names must be between 1 and 20 characters in length.')); } // If not set, default to the setting for public. if (null === $args->publicly_queryable) { $args->publicly_queryable = $args->public; } // If not set, default to the setting for public. if (null === $args->show_ui) { $args->show_ui = $args->public; } // If not set, default to the setting for show_ui. if (null === $args->show_in_menu || !$args->show_ui) { $args->show_in_menu = $args->show_ui; } // If not set, default to the whether the full UI is shown. if (null === $args->show_in_admin_bar) { $args->show_in_admin_bar = (bool) $args->show_in_menu; } // If not set, default to the setting for public. if (null === $args->show_in_nav_menus) { $args->show_in_nav_menus = $args->public; } // If not set, default to true if not public, false if public. if (null === $args->exclude_from_search) { $args->exclude_from_search = !$args->public; } // Back compat with quirky handling in version 3.0. #14122. if (empty($args->capabilities) && null === $args->map_meta_cap && in_array($args->capability_type, array('post', 'page'))) { $args->map_meta_cap = true; } // If not set, default to false. if (null === $args->map_meta_cap) { $args->map_meta_cap = false; } // If there's no specified edit link and no UI, remove the edit link. if (!$args->show_ui && !$has_edit_link) { $args->_edit_link = ''; } $args->cap = get_post_type_capabilities($args); unset($args->capabilities); if (is_array($args->capability_type)) { $args->capability_type = $args->capability_type[0]; } if (!empty($args->supports)) { add_post_type_support($post_type, $args->supports); unset($args->supports); } elseif (false !== $args->supports) { // Add default features add_post_type_support($post_type, array('title', 'editor')); } if (false !== $args->query_var) { if (true === $args->query_var) { $args->query_var = $post_type; } else { $args->query_var = sanitize_title_with_dashes($args->query_var); } if ($wp && is_post_type_viewable($args)) { $wp->add_query_var($args->query_var); } } if (false !== $args->rewrite && (is_admin() || '' != get_option('permalink_structure'))) { if (!is_array($args->rewrite)) { $args->rewrite = array(); } if (empty($args->rewrite['slug'])) { $args->rewrite['slug'] = $post_type; } if (!isset($args->rewrite['with_front'])) { $args->rewrite['with_front'] = true; } if (!isset($args->rewrite['pages'])) { $args->rewrite['pages'] = true; } if (!isset($args->rewrite['feeds']) || !$args->has_archive) { $args->rewrite['feeds'] = (bool) $args->has_archive; } if (!isset($args->rewrite['ep_mask'])) { if (isset($args->permalink_epmask)) { $args->rewrite['ep_mask'] = $args->permalink_epmask; } else { $args->rewrite['ep_mask'] = EP_PERMALINK; } } if ($args->hierarchical) { add_rewrite_tag("%{$post_type}%", '(.+?)', $args->query_var ? "{$args->query_var}=" : "post_type={$post_type}&pagename="); } else { add_rewrite_tag("%{$post_type}%", '([^/]+)', $args->query_var ? "{$args->query_var}=" : "post_type={$post_type}&name="); } if ($args->has_archive) { $archive_slug = $args->has_archive === true ? $args->rewrite['slug'] : $args->has_archive; if ($args->rewrite['with_front']) { $archive_slug = substr($wp_rewrite->front, 1) . $archive_slug; } else { $archive_slug = $wp_rewrite->root . $archive_slug; } add_rewrite_rule("{$archive_slug}/?\$", "index.php?post_type={$post_type}", 'top'); if ($args->rewrite['feeds'] && $wp_rewrite->feeds) { $feeds = '(' . trim(implode('|', $wp_rewrite->feeds)) . ')'; add_rewrite_rule("{$archive_slug}/feed/{$feeds}/?\$", "index.php?post_type={$post_type}" . '&feed=$matches[1]', 'top'); add_rewrite_rule("{$archive_slug}/{$feeds}/?\$", "index.php?post_type={$post_type}" . '&feed=$matches[1]', 'top'); } if ($args->rewrite['pages']) { add_rewrite_rule("{$archive_slug}/{$wp_rewrite->pagination_base}/([0-9]{1,})/?\$", "index.php?post_type={$post_type}" . '&paged=$matches[1]', 'top'); } } $permastruct_args = $args->rewrite; $permastruct_args['feed'] = $permastruct_args['feeds']; add_permastruct($post_type, "{$args->rewrite['slug']}/%{$post_type}%", $permastruct_args); } // Register the post type meta box if a custom callback was specified. if ($args->register_meta_box_cb) { add_action('add_meta_boxes_' . $post_type, $args->register_meta_box_cb, 10, 1); } $args->labels = get_post_type_labels($args); $args->label = $args->labels->name; $wp_post_types[$post_type] = $args; add_action('future_' . $post_type, '_future_post_hook', 5, 2); foreach ($args->taxonomies as $taxonomy) { register_taxonomy_for_object_type($taxonomy, $post_type); } /** * Fires after a post type is registered. * * @since 3.3.0 * * @param string $post_type Post type. * @param object $args Arguments used to register the post type. */ do_action('registered_post_type', $post_type, $args); return $args; }
/** * Generates and displays row action links. * * @since 4.3.0 * @access protected * * @param object $post Post being acted upon. * @param string $column_name Current column name. * @param string $primary Primary column name. * @return string Row actions output for posts. */ protected function handle_row_actions($post, $column_name, $primary) { if ($primary !== $column_name) { return ''; } $post_type_object = get_post_type_object($post->post_type); $can_edit_post = current_user_can('edit_post', $post->ID); $actions = array(); if ($can_edit_post && 'trash' != $post->post_status) { $actions['edit'] = '<a href="' . get_edit_post_link($post->ID) . '" title="' . esc_attr__('Edit this item') . '">' . __('Edit') . '</a>'; $actions['inline hide-if-no-js'] = '<a href="#" class="editinline" title="' . esc_attr__('Edit this item inline') . '">' . __('Quick Edit') . '</a>'; } if (current_user_can('delete_post', $post->ID)) { if ('trash' == $post->post_status) { $actions['untrash'] = "<a title='" . esc_attr__('Restore this item from the Trash') . "' href='" . wp_nonce_url(admin_url(sprintf($post_type_object->_edit_link . '&action=untrash', $post->ID)), 'untrash-post_' . $post->ID) . "'>" . __('Restore') . "</a>"; } elseif (EMPTY_TRASH_DAYS) { $actions['trash'] = "<a class='submitdelete' title='" . esc_attr__('Move this item to the Trash') . "' href='" . get_delete_post_link($post->ID) . "'>" . __('Trash') . "</a>"; } if ('trash' == $post->post_status || !EMPTY_TRASH_DAYS) { $actions['delete'] = "<a class='submitdelete' title='" . esc_attr__('Delete this item permanently') . "' href='" . get_delete_post_link($post->ID, '', true) . "'>" . __('Delete Permanently') . "</a>"; } } if (is_post_type_viewable($post_type_object)) { $title = _draft_or_post_title(); if (in_array($post->post_status, array('pending', 'draft', 'future'))) { if ($can_edit_post) { $preview_link = set_url_scheme(get_permalink($post->ID)); /** This filter is documented in wp-admin/includes/meta-boxes.php */ $preview_link = apply_filters('preview_post_link', add_query_arg('preview', 'true', $preview_link), $post); $actions['view'] = '<a href="' . esc_url($preview_link) . '" title="' . esc_attr(sprintf(__('Preview “%s”'), $title)) . '" rel="permalink">' . __('Preview') . '</a>'; } } elseif ('trash' != $post->post_status) { $actions['view'] = '<a href="' . get_permalink($post->ID) . '" title="' . esc_attr(sprintf(__('View “%s”'), $title)) . '" rel="permalink">' . __('View') . '</a>'; } } if (is_post_type_hierarchical($post->post_type)) { /** * Filter the array of row action links on the Pages list table. * * The filter is evaluated only for hierarchical post types. * * @since 2.8.0 * * @param array $actions An array of row action links. Defaults are * 'Edit', 'Quick Edit', 'Restore, 'Trash', * 'Delete Permanently', 'Preview', and 'View'. * @param WP_Post $post The post object. */ $actions = apply_filters('page_row_actions', $actions, $post); } else { /** * Filter the array of row action links on the Posts list table. * * The filter is evaluated only for non-hierarchical post types. * * @since 2.8.0 * * @param array $actions An array of row action links. Defaults are * 'Edit', 'Quick Edit', 'Restore, 'Trash', * 'Delete Permanently', 'Preview', and 'View'. * @param WP_Post $post The post object. */ $actions = apply_filters('post_row_actions', $actions, $post); } return $this->row_actions($actions); }
/** * Generates and displays row action links. * * @since 4.3.0 * @access protected * * @param object $post Post being acted upon. * @param string $column_name Current column name. * @param string $primary Primary column name. * @return string Row actions output for posts. */ protected function handle_row_actions($post, $column_name, $primary) { if ($primary !== $column_name) { return ''; } $post_type_object = get_post_type_object($post->post_type); $can_edit_post = current_user_can('edit_post', $post->ID); $actions = array(); $title = _draft_or_post_title(); if ($can_edit_post && 'trash' != $post->post_status) { $actions['edit'] = sprintf('<a href="%s" aria-label="%s">%s</a>', get_edit_post_link($post->ID), esc_attr(sprintf(__('Edit “%s”'), $title)), __('Edit')); $actions['inline hide-if-no-js'] = sprintf('<a href="#" class="editinline" aria-label="%s">%s</a>', esc_attr(sprintf(__('Quick edit “%s” inline'), $title)), __('Quick Edit')); } if (current_user_can('delete_post', $post->ID)) { if ('trash' === $post->post_status) { $actions['untrash'] = sprintf('<a href="%s" aria-label="%s">%s</a>', wp_nonce_url(admin_url(sprintf($post_type_object->_edit_link . '&action=untrash', $post->ID)), 'untrash-post_' . $post->ID), esc_attr(sprintf(__('Restore “%s” from the Trash'), $title)), __('Restore')); } elseif (EMPTY_TRASH_DAYS) { $actions['trash'] = sprintf('<a href="%s" class="submitdelete" aria-label="%s">%s</a>', get_delete_post_link($post->ID), esc_attr(sprintf(__('Move “%s” to the Trash'), $title)), _x('Trash', 'verb')); } if ('trash' === $post->post_status || !EMPTY_TRASH_DAYS) { $actions['delete'] = sprintf('<a href="%s" class="submitdelete" aria-label="%s">%s</a>', get_delete_post_link($post->ID, '', true), esc_attr(sprintf(__('Delete “%s” permanently'), $title)), __('Delete Permanently')); } } if (is_post_type_viewable($post_type_object)) { if (in_array($post->post_status, array('pending', 'draft', 'future'))) { if ($can_edit_post) { $unpublished_link = set_url_scheme(get_permalink($post)); $preview_link = get_preview_post_link($post, array(), $unpublished_link); $actions['view'] = sprintf('<a href="%s" rel="permalink" aria-label="%s">%s</a>', esc_url($preview_link), esc_attr(sprintf(__('Preview “%s”'), $title)), __('Preview')); } } elseif ('trash' != $post->post_status) { $actions['view'] = sprintf('<a href="%s" rel="permalink" aria-label="%s">%s</a>', get_permalink($post->ID), esc_attr(sprintf(__('View “%s”'), $title)), __('View')); } } if (is_post_type_hierarchical($post->post_type)) { /** * Filter the array of row action links on the Pages list table. * * The filter is evaluated only for hierarchical post types. * * @since 2.8.0 * * @param array $actions An array of row action links. Defaults are * 'Edit', 'Quick Edit', 'Restore, 'Trash', * 'Delete Permanently', 'Preview', and 'View'. * @param WP_Post $post The post object. */ $actions = apply_filters('page_row_actions', $actions, $post); } else { /** * Filter the array of row action links on the Posts list table. * * The filter is evaluated only for non-hierarchical post types. * * @since 2.8.0 * * @param array $actions An array of row action links. Defaults are * 'Edit', 'Quick Edit', 'Restore, 'Trash', * 'Delete Permanently', 'Preview', and 'View'. * @param WP_Post $post The post object. */ $actions = apply_filters('post_row_actions', $actions, $post); } return $this->row_actions($actions); }
/** * Retrieve URL used for the post preview. * * Get the preview post URL. Allows additional query args to be appended. * * @since 4.4.0 * * @param int|WP_Post $post Optional. Post ID or `WP_Post` object. Defaults to global post. * @param array $query_args Optional. Array of additional query args to be appended to the link. * @param string $preview_link Optional. Base preview link to be used if it should differ from the post permalink. * @return string URL used for the post preview. */ function get_preview_post_link($post = null, $query_args = array(), $preview_link = '') { $post = get_post($post); if (!$post) { return; } $post_type_object = get_post_type_object($post->post_type); if (is_post_type_viewable($post_type_object)) { if (!$preview_link) { $preview_link = get_permalink($post); } $query_args['preview'] = 'true'; $preview_link = add_query_arg($query_args, $preview_link); } /** * Filter the URL used for a post preview. * * @since 2.0.5 * @since 4.0.0 Added the `$post` parameter. * * @param string $preview_link URL used for the post preview. * @param WP_Post $post Post object. */ return apply_filters('preview_post_link', $preview_link, $post); }
wp_enqueue_media(array('post' => $post_ID)); } // Add the local autosave notice HTML add_action('admin_footer', '_local_storage_notice'); /* * @todo Document the $messages array(s). */ $permalink = get_permalink($post_ID); if (!$permalink) { $permalink = ''; } $messages = array(); $preview_post_link_html = $scheduled_post_link_html = $view_post_link_html = ''; $preview_page_link_html = $scheduled_page_link_html = $view_page_link_html = ''; $preview_url = get_preview_post_link($post); $viewable = is_post_type_viewable($post_type_object); if ($viewable) { // Preview post link. $preview_post_link_html = sprintf(' <a target="_blank" href="%1$s">%2$s</a>', esc_url($preview_url), __('Preview post')); // Scheduled post preview link. $scheduled_post_link_html = sprintf(' <a target="_blank" href="%1$s">%2$s</a>', esc_url($permalink), __('Preview post')); // View post link. $view_post_link_html = sprintf(' <a href="%1$s">%2$s</a>', esc_url($permalink), __('View post')); // Preview page link. $preview_page_link_html = sprintf(' <a target="_blank" href="%1$s">%2$s</a>', esc_url($preview_url), __('Preview page')); // Scheduled page preview link. $scheduled_page_link_html = sprintf(' <a target="_blank" href="%1$s">%2$s</a>', esc_url($permalink), __('Preview page')); // View page link. $view_page_link_html = sprintf(' <a href="%1$s">%2$s</a>', esc_url($permalink), __('View page')); } /* translators: Publish box date format, see https://secure.php.net/date */
/** * Displays post submit form fields. * * @since 2.7.0 * * @global string $action * * @param WP_Post $post Current post object. * @param array $args { * Array of arguments for building the post submit meta box. * * @type string $id Meta box ID. * @type string $title Meta box title. * @type callable $callback Meta box display callback. * @type array $args Extra meta box arguments. * } */ function post_submit_meta_box($post, $args = array()) { global $action; $post_type = $post->post_type; $post_type_object = get_post_type_object($post_type); $can_publish = current_user_can($post_type_object->cap->publish_posts); ?> <div class="submitbox" id="submitpost"> <div id="minor-publishing"> <?php // Hidden submit button early on so that the browser chooses the right button when form is submitted with Return key ?> <div style="display:none;"> <?php submit_button(__('Save'), 'button', 'save'); ?> </div> <div id="minor-publishing-actions"> <div id="save-action"> <?php if ('publish' != $post->post_status && 'future' != $post->post_status && 'pending' != $post->post_status) { ?> <input <?php if ('private' == $post->post_status) { ?> style="display:none"<?php } ?> type="submit" name="save" id="save-post" value="<?php esc_attr_e('Save Draft'); ?> " class="button" /> <span class="spinner"></span> <?php } elseif ('pending' == $post->post_status && $can_publish) { ?> <input type="submit" name="save" id="save-post" value="<?php esc_attr_e('Save as Pending'); ?> " class="button" /> <span class="spinner"></span> <?php } ?> </div> <?php if (is_post_type_viewable($post_type_object)) { ?> <div id="preview-action"> <?php $preview_link = esc_url(get_preview_post_link($post)); if ('publish' == $post->post_status) { $preview_button = __('Preview Changes'); } else { $preview_button = __('Preview'); } ?> <a class="preview button" href="<?php echo $preview_link; ?> " target="wp-preview-<?php echo (int) $post->ID; ?> " id="post-preview"><?php echo $preview_button; ?> </a> <input type="hidden" name="wp-preview" id="wp-preview" value="" /> </div> <?php } // public post type /** * Fires before the post time/date setting in the Publish meta box. * * @since 4.4.0 * * @param WP_Post $post WP_Post object for the current post. */ do_action('post_submitbox_minor_actions', $post); ?> <div class="clear"></div> </div><!-- #minor-publishing-actions --> <div id="misc-publishing-actions"> <div class="misc-pub-section misc-pub-post-status"><label for="post_status"><?php _e('Status:'); ?> </label> <span id="post-status-display"> <?php switch ($post->post_status) { case 'private': _e('Privately Published'); break; case 'publish': _e('Published'); break; case 'future': _e('Scheduled'); break; case 'pending': _e('Pending Review'); break; case 'draft': case 'auto-draft': _e('Draft'); break; } ?> </span> <?php if ('publish' == $post->post_status || 'private' == $post->post_status || $can_publish) { ?> <a href="#post_status" <?php if ('private' == $post->post_status) { ?> style="display:none;" <?php } ?> class="edit-post-status hide-if-no-js"><span aria-hidden="true"><?php _e('Edit'); ?> </span> <span class="screen-reader-text"><?php _e('Edit status'); ?> </span></a> <div id="post-status-select" class="hide-if-js"> <input type="hidden" name="hidden_post_status" id="hidden_post_status" value="<?php echo esc_attr('auto-draft' == $post->post_status ? 'draft' : $post->post_status); ?> " /> <select name='post_status' id='post_status'> <?php if ('publish' == $post->post_status) { ?> <option<?php selected($post->post_status, 'publish'); ?> value='publish'><?php _e('Published'); ?> </option> <?php } elseif ('private' == $post->post_status) { ?> <option<?php selected($post->post_status, 'private'); ?> value='publish'><?php _e('Privately Published'); ?> </option> <?php } elseif ('future' == $post->post_status) { ?> <option<?php selected($post->post_status, 'future'); ?> value='future'><?php _e('Scheduled'); ?> </option> <?php } ?> <option<?php selected($post->post_status, 'pending'); ?> value='pending'><?php _e('Pending Review'); ?> </option> <?php if ('auto-draft' == $post->post_status) { ?> <option<?php selected($post->post_status, 'auto-draft'); ?> value='draft'><?php _e('Draft'); ?> </option> <?php } else { ?> <option<?php selected($post->post_status, 'draft'); ?> value='draft'><?php _e('Draft'); ?> </option> <?php } ?> </select> <a href="#post_status" class="save-post-status hide-if-no-js button"><?php _e('OK'); ?> </a> <a href="#post_status" class="cancel-post-status hide-if-no-js button-cancel"><?php _e('Cancel'); ?> </a> </div> <?php } ?> </div><!-- .misc-pub-section --> <div class="misc-pub-section misc-pub-visibility" id="visibility"> <?php _e('Visibility:'); ?> <span id="post-visibility-display"><?php if ('private' == $post->post_status) { $post->post_password = ''; $visibility = 'private'; $visibility_trans = __('Private'); } elseif (!empty($post->post_password)) { $visibility = 'password'; $visibility_trans = __('Password protected'); } elseif ($post_type == 'post' && is_sticky($post->ID)) { $visibility = 'public'; $visibility_trans = __('Public, Sticky'); } else { $visibility = 'public'; $visibility_trans = __('Public'); } echo esc_html($visibility_trans); ?> </span> <?php if ($can_publish) { ?> <a href="#visibility" class="edit-visibility hide-if-no-js"><span aria-hidden="true"><?php _e('Edit'); ?> </span> <span class="screen-reader-text"><?php _e('Edit visibility'); ?> </span></a> <div id="post-visibility-select" class="hide-if-js"> <input type="hidden" name="hidden_post_password" id="hidden-post-password" value="<?php echo esc_attr($post->post_password); ?> " /> <?php if ($post_type == 'post') { ?> <input type="checkbox" style="display:none" name="hidden_post_sticky" id="hidden-post-sticky" value="sticky" <?php checked(is_sticky($post->ID)); ?> /> <?php } ?> <input type="hidden" name="hidden_post_visibility" id="hidden-post-visibility" value="<?php echo esc_attr($visibility); ?> " /> <input type="radio" name="visibility" id="visibility-radio-public" value="public" <?php checked($visibility, 'public'); ?> /> <label for="visibility-radio-public" class="selectit"><?php _e('Public'); ?> </label><br /> <?php if ($post_type == 'post' && current_user_can('edit_others_posts')) { ?> <span id="sticky-span"><input id="sticky" name="sticky" type="checkbox" value="sticky" <?php checked(is_sticky($post->ID)); ?> /> <label for="sticky" class="selectit"><?php _e('Stick this post to the front page'); ?> </label><br /></span> <?php } ?> <input type="radio" name="visibility" id="visibility-radio-password" value="password" <?php checked($visibility, 'password'); ?> /> <label for="visibility-radio-password" class="selectit"><?php _e('Password protected'); ?> </label><br /> <span id="password-span"><label for="post_password"><?php _e('Password:'******'private'); ?> /> <label for="visibility-radio-private" class="selectit"><?php _e('Private'); ?> </label><br /> <p> <a href="#visibility" class="save-post-visibility hide-if-no-js button"><?php _e('OK'); ?> </a> <a href="#visibility" class="cancel-post-visibility hide-if-no-js button-cancel"><?php _e('Cancel'); ?> </a> </p> </div> <?php } ?> </div><!-- .misc-pub-section --> <?php /* translators: Publish box date format, see http://php.net/date */ $datef = __('M j, Y @ H:i'); if (0 != $post->ID) { if ('future' == $post->post_status) { // scheduled for publishing at a future date $stamp = __('Scheduled for: <b>%1$s</b>'); } elseif ('publish' == $post->post_status || 'private' == $post->post_status) { // already published $stamp = __('Published on: <b>%1$s</b>'); } elseif ('0000-00-00 00:00:00' == $post->post_date_gmt) { // draft, 1 or more saves, no date specified $stamp = __('Publish <b>immediately</b>'); } elseif (time() < strtotime($post->post_date_gmt . ' +0000')) { // draft, 1 or more saves, future date specified $stamp = __('Schedule for: <b>%1$s</b>'); } else { // draft, 1 or more saves, date specified $stamp = __('Publish on: <b>%1$s</b>'); } $date = date_i18n($datef, strtotime($post->post_date)); } else { // draft (no saves, and thus no date specified) $stamp = __('Publish <b>immediately</b>'); $date = date_i18n($datef, strtotime(current_time('mysql'))); } if (!empty($args['args']['revisions_count'])) { $revisions_to_keep = wp_revisions_to_keep($post); ?> <div class="misc-pub-section misc-pub-revisions"> <?php if ($revisions_to_keep > 0 && $revisions_to_keep <= $args['args']['revisions_count']) { echo '<span title="' . esc_attr(sprintf(__('Your site is configured to keep only the last %s revisions.'), number_format_i18n($revisions_to_keep))) . '">'; printf(__('Revisions: %s'), '<b>' . number_format_i18n($args['args']['revisions_count']) . '+</b>'); echo '</span>'; } else { printf(__('Revisions: %s'), '<b>' . number_format_i18n($args['args']['revisions_count']) . '</b>'); } ?> <a class="hide-if-no-js" href="<?php echo esc_url(get_edit_post_link($args['args']['revision_id'])); ?> "><span aria-hidden="true"><?php _ex('Browse', 'revisions'); ?> </span> <span class="screen-reader-text"><?php _e('Browse revisions'); ?> </span></a> </div> <?php } if ($can_publish) { // Contributors don't get to choose the date of publish ?> <div class="misc-pub-section curtime misc-pub-curtime"> <span id="timestamp"> <?php printf($stamp, $date); ?> </span> <a href="#edit_timestamp" class="edit-timestamp hide-if-no-js"><span aria-hidden="true"><?php _e('Edit'); ?> </span> <span class="screen-reader-text"><?php _e('Edit date and time'); ?> </span></a> <fieldset id="timestampdiv" class="hide-if-js"> <legend class="screen-reader-text"><?php _e('Date and time'); ?> </legend> <?php touch_time($action === 'edit', 1); ?> </fieldset> </div><?php // /misc-pub-section } ?> <?php /** * Fires after the post time/date setting in the Publish meta box. * * @since 2.9.0 * @since 4.4.0 Added the `$post` parameter. * * @param WP_Post $post WP_Post object for the current post. */ do_action('post_submitbox_misc_actions', $post); ?> </div> <div class="clear"></div> </div> <div id="major-publishing-actions"> <?php /** * Fires at the beginning of the publishing actions section of the Publish meta box. * * @since 2.7.0 */ do_action('post_submitbox_start'); ?> <div id="delete-action"> <?php if (current_user_can("delete_post", $post->ID)) { if (!EMPTY_TRASH_DAYS) { $delete_text = __('Delete Permanently'); } else { $delete_text = __('Move to Trash'); } ?> <a class="submitdelete deletion" href="<?php echo get_delete_post_link($post->ID); ?> "><?php echo $delete_text; ?> </a><?php } ?> </div> <div id="publishing-action"> <span class="spinner"></span> <?php if (!in_array($post->post_status, array('publish', 'future', 'private')) || 0 == $post->ID) { if ($can_publish) { if (!empty($post->post_date_gmt) && time() < strtotime($post->post_date_gmt . ' +0000')) { ?> <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Schedule'); ?> " /> <?php submit_button(__('Schedule'), 'primary button-large', 'publish', false); } else { ?> <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Publish'); ?> " /> <?php submit_button(__('Publish'), 'primary button-large', 'publish', false); } } else { ?> <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Submit for Review'); ?> " /> <?php submit_button(__('Submit for Review'), 'primary button-large', 'publish', false); } } else { ?> <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Update'); ?> " /> <input name="save" type="submit" class="button button-primary button-large" id="publish" value="<?php esc_attr_e('Update'); ?> " /> <?php } ?> </div> <div class="clear"></div> </div> </div> <?php }
function _cleanup_query_vars() { // clean out globals to stop them polluting wp and wp_query foreach ($GLOBALS['wp']->public_query_vars as $v) { unset($GLOBALS[$v]); } foreach ($GLOBALS['wp']->private_query_vars as $v) { unset($GLOBALS[$v]); } foreach (get_taxonomies(array(), 'objects') as $t) { if ($t->publicly_queryable && !empty($t->query_var)) { $GLOBALS['wp']->add_query_var($t->query_var); } } foreach (get_post_types(array(), 'objects') as $t) { if (is_post_type_viewable($t) && !empty($t->query_var)) { $GLOBALS['wp']->add_query_var($t->query_var); } } }
/** * Display archive links based on type and format. * * @since 1.2.0 * @since 4.4.0 $post_type arg was added. * * @see get_archives_link() * * @global wpdb $wpdb * @global WP_Locale $wp_locale * * @param string|array $args { * Default archive links arguments. Optional. * * @type string $type Type of archive to retrieve. Accepts 'daily', 'weekly', 'monthly', * 'yearly', 'postbypost', or 'alpha'. Both 'postbypost' and 'alpha' * display the same archive link list as well as post titles instead * of displaying dates. The difference between the two is that 'alpha' * will order by post title and 'postbypost' will order by post date. * Default 'monthly'. * @type string|int $limit Number of links to limit the query to. Default empty (no limit). * @type string $format Format each link should take using the $before and $after args. * Accepts 'link' (`<link>` tag), 'option' (`<option>` tag), 'html' * (`<li>` tag), or a custom format, which generates a link anchor * with $before preceding and $after succeeding. Default 'html'. * @type string $before Markup to prepend to the beginning of each link. Default empty. * @type string $after Markup to append to the end of each link. Default empty. * @type bool $show_post_count Whether to display the post count alongside the link. Default false. * @type bool|int $echo Whether to echo or return the links list. Default 1|true to echo. * @type string $order Whether to use ascending or descending order. Accepts 'ASC', or 'DESC'. * Default 'DESC'. * @type string $post_type Post type. Default 'post'. * } * @return string|void String when retrieving. */ function wp_get_archives($args = '') { global $wpdb, $wp_locale; $defaults = array('type' => 'monthly', 'limit' => '', 'format' => 'html', 'before' => '', 'after' => '', 'show_post_count' => false, 'echo' => 1, 'order' => 'DESC', 'post_type' => 'post'); $r = wp_parse_args($args, $defaults); $post_type_object = get_post_type_object($r['post_type']); if (!is_post_type_viewable($post_type_object)) { return; } $r['post_type'] = $post_type_object->name; if ('' == $r['type']) { $r['type'] = 'monthly'; } if (!empty($r['limit'])) { $r['limit'] = absint($r['limit']); $r['limit'] = ' LIMIT ' . $r['limit']; } $order = strtoupper($r['order']); if ($order !== 'ASC') { $order = 'DESC'; } // this is what will separate dates on weekly archive links $archive_week_separator = '–'; // over-ride general date format ? 0 = no: use the date format set in Options, 1 = yes: over-ride $archive_date_format_over_ride = 0; // options for daily archive (only if you over-ride the general date format) $archive_day_date_format = 'Y/m/d'; // options for weekly archive (only if you over-ride the general date format) $archive_week_start_date_format = 'Y/m/d'; $archive_week_end_date_format = 'Y/m/d'; if (!$archive_date_format_over_ride) { $archive_day_date_format = get_option('date_format'); $archive_week_start_date_format = get_option('date_format'); $archive_week_end_date_format = get_option('date_format'); } $sql_where = $wpdb->prepare("WHERE post_type = %s AND post_status = 'publish'", $r['post_type']); /** * Filter the SQL WHERE clause for retrieving archives. * * @since 2.2.0 * * @param string $sql_where Portion of SQL query containing the WHERE clause. * @param array $r An array of default arguments. */ $where = apply_filters('getarchives_where', $sql_where, $r); /** * Filter the SQL JOIN clause for retrieving archives. * * @since 2.2.0 * * @param string $sql_join Portion of SQL query containing JOIN clause. * @param array $r An array of default arguments. */ $join = apply_filters('getarchives_join', '', $r); $output = ''; $last_changed = wp_cache_get('last_changed', 'posts'); if (!$last_changed) { $last_changed = microtime(); wp_cache_set('last_changed', $last_changed, 'posts'); } $limit = $r['limit']; if ('monthly' == $r['type']) { $query = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM {$wpdb->posts} {$join} {$where} GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date {$order} {$limit}"; $key = md5($query); $key = "wp_get_archives:{$key}:{$last_changed}"; if (!($results = wp_cache_get($key, 'posts'))) { $results = $wpdb->get_results($query); wp_cache_set($key, $results, 'posts'); } if ($results) { $after = $r['after']; foreach ((array) $results as $result) { $url = get_month_link($result->year, $result->month); if ('post' !== $r['post_type']) { $url = add_query_arg('post_type', $r['post_type'], $url); } /* translators: 1: month name, 2: 4-digit year */ $text = sprintf(__('%1$s %2$d'), $wp_locale->get_month($result->month), $result->year); if ($r['show_post_count']) { $r['after'] = ' (' . $result->posts . ')' . $after; } $output .= get_archives_link($url, $text, $r['format'], $r['before'], $r['after']); } } } elseif ('yearly' == $r['type']) { $query = "SELECT YEAR(post_date) AS `year`, count(ID) as posts FROM {$wpdb->posts} {$join} {$where} GROUP BY YEAR(post_date) ORDER BY post_date {$order} {$limit}"; $key = md5($query); $key = "wp_get_archives:{$key}:{$last_changed}"; if (!($results = wp_cache_get($key, 'posts'))) { $results = $wpdb->get_results($query); wp_cache_set($key, $results, 'posts'); } if ($results) { $after = $r['after']; foreach ((array) $results as $result) { $url = get_year_link($result->year); if ('post' !== $r['post_type']) { $url = add_query_arg('post_type', $r['post_type'], $url); } $text = sprintf('%d', $result->year); if ($r['show_post_count']) { $r['after'] = ' (' . $result->posts . ')' . $after; } $output .= get_archives_link($url, $text, $r['format'], $r['before'], $r['after']); } } } elseif ('daily' == $r['type']) { $query = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, DAYOFMONTH(post_date) AS `dayofmonth`, count(ID) as posts FROM {$wpdb->posts} {$join} {$where} GROUP BY YEAR(post_date), MONTH(post_date), DAYOFMONTH(post_date) ORDER BY post_date {$order} {$limit}"; $key = md5($query); $key = "wp_get_archives:{$key}:{$last_changed}"; if (!($results = wp_cache_get($key, 'posts'))) { $results = $wpdb->get_results($query); wp_cache_set($key, $results, 'posts'); } if ($results) { $after = $r['after']; foreach ((array) $results as $result) { $url = get_day_link($result->year, $result->month, $result->dayofmonth); if ('post' !== $r['post_type']) { $url = add_query_arg('post_type', $r['post_type'], $url); } $date = sprintf('%1$d-%2$02d-%3$02d 00:00:00', $result->year, $result->month, $result->dayofmonth); $text = mysql2date($archive_day_date_format, $date); if ($r['show_post_count']) { $r['after'] = ' (' . $result->posts . ')' . $after; } $output .= get_archives_link($url, $text, $r['format'], $r['before'], $r['after']); } } } elseif ('weekly' == $r['type']) { $week = _wp_mysql_week('`post_date`'); $query = "SELECT DISTINCT {$week} AS `week`, YEAR( `post_date` ) AS `yr`, DATE_FORMAT( `post_date`, '%Y-%m-%d' ) AS `yyyymmdd`, count( `ID` ) AS `posts` FROM `{$wpdb->posts}` {$join} {$where} GROUP BY {$week}, YEAR( `post_date` ) ORDER BY `post_date` {$order} {$limit}"; $key = md5($query); $key = "wp_get_archives:{$key}:{$last_changed}"; if (!($results = wp_cache_get($key, 'posts'))) { $results = $wpdb->get_results($query); wp_cache_set($key, $results, 'posts'); } $arc_w_last = ''; if ($results) { $after = $r['after']; foreach ((array) $results as $result) { if ($result->week != $arc_w_last) { $arc_year = $result->yr; $arc_w_last = $result->week; $arc_week = get_weekstartend($result->yyyymmdd, get_option('start_of_week')); $arc_week_start = date_i18n($archive_week_start_date_format, $arc_week['start']); $arc_week_end = date_i18n($archive_week_end_date_format, $arc_week['end']); $url = sprintf('%1$s/%2$s%3$sm%4$s%5$s%6$sw%7$s%8$d', home_url(), '', '?', '=', $arc_year, '&', '=', $result->week); if ('post' !== $r['post_type']) { $url = add_query_arg('post_type', $r['post_type'], $url); } $text = $arc_week_start . $archive_week_separator . $arc_week_end; if ($r['show_post_count']) { $r['after'] = ' (' . $result->posts . ')' . $after; } $output .= get_archives_link($url, $text, $r['format'], $r['before'], $r['after']); } } } } elseif ('postbypost' == $r['type'] || 'alpha' == $r['type']) { $orderby = 'alpha' == $r['type'] ? 'post_title ASC ' : 'post_date DESC, ID DESC '; $query = "SELECT * FROM {$wpdb->posts} {$join} {$where} ORDER BY {$orderby} {$limit}"; $key = md5($query); $key = "wp_get_archives:{$key}:{$last_changed}"; if (!($results = wp_cache_get($key, 'posts'))) { $results = $wpdb->get_results($query); wp_cache_set($key, $results, 'posts'); } if ($results) { foreach ((array) $results as $result) { if ($result->post_date != '0000-00-00 00:00:00') { $url = get_permalink($result); if ($result->post_title) { /** This filter is documented in wp-includes/post-template.php */ $text = strip_tags(apply_filters('the_title', $result->post_title, $result->ID)); } else { $text = $result->ID; } $output .= get_archives_link($url, $text, $r['format'], $r['before'], $r['after']); } } } } if ($r['echo']) { echo $output; } else { return $output; } }
/** * Parse request to find correct WordPress query. * * Sets up the query variables based on the request. There are also many * filters and actions that can be used to further manipulate the result. * * @since 2.0.0 * @access public * * @global WP_Rewrite $wp_rewrite * * @param array|string $extra_query_vars Set the extra query variables. */ public function parse_request($extra_query_vars = '') { global $wp_rewrite; /** * Filter whether to parse the request. * * @since 3.5.0 * * @param bool $bool Whether or not to parse the request. Default true. * @param WP $this Current WordPress environment instance. * @param array|string $extra_query_vars Extra passed query variables. */ if (!apply_filters('do_parse_request', true, $this, $extra_query_vars)) { return; } $this->query_vars = array(); $post_type_query_vars = array(); if (is_array($extra_query_vars)) { $this->extra_query_vars =& $extra_query_vars; } elseif (!empty($extra_query_vars)) { parse_str($extra_query_vars, $this->extra_query_vars); } // Process PATH_INFO, REQUEST_URI, and 404 for permalinks. // Fetch the rewrite rules. $rewrite = $wp_rewrite->wp_rewrite_rules(); if (!empty($rewrite)) { // If we match a rewrite rule, this will be cleared. $error = '404'; $this->did_permalink = true; $pathinfo = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : ''; list($pathinfo) = explode('?', $pathinfo); $pathinfo = str_replace("%", "%25", $pathinfo); list($req_uri) = explode('?', $_SERVER['REQUEST_URI']); $self = $_SERVER['PHP_SELF']; $home_path = trim(parse_url(home_url(), PHP_URL_PATH), '/'); $home_path_regex = sprintf('|^%s|i', preg_quote($home_path, '|')); // Trim path info from the end and the leading home path from the // front. For path info requests, this leaves us with the requesting // filename, if any. For 404 requests, this leaves us with the // requested permalink. $req_uri = str_replace($pathinfo, '', $req_uri); $req_uri = trim($req_uri, '/'); $req_uri = preg_replace($home_path_regex, '', $req_uri); $req_uri = trim($req_uri, '/'); $pathinfo = trim($pathinfo, '/'); $pathinfo = preg_replace($home_path_regex, '', $pathinfo); $pathinfo = trim($pathinfo, '/'); $self = trim($self, '/'); $self = preg_replace($home_path_regex, '', $self); $self = trim($self, '/'); // The requested permalink is in $pathinfo for path info requests and // $req_uri for other requests. if (!empty($pathinfo) && !preg_match('|^.*' . $wp_rewrite->index . '$|', $pathinfo)) { $requested_path = $pathinfo; } else { // If the request uri is the index, blank it out so that we don't try to match it against a rule. if ($req_uri == $wp_rewrite->index) { $req_uri = ''; } $requested_path = $req_uri; } $requested_file = $req_uri; $this->request = $requested_path; // Look for matches. $request_match = $requested_path; if (empty($request_match)) { // An empty request could only match against ^$ regex if (isset($rewrite['$'])) { $this->matched_rule = '$'; $query = $rewrite['$']; $matches = array(''); } } else { foreach ((array) $rewrite as $match => $query) { // If the requested file is the anchor of the match, prepend it to the path info. if (!empty($requested_file) && strpos($match, $requested_file) === 0 && $requested_file != $requested_path) { $request_match = $requested_file . '/' . $requested_path; } if (preg_match("#^{$match}#", $request_match, $matches) || preg_match("#^{$match}#", urldecode($request_match), $matches)) { if ($wp_rewrite->use_verbose_page_rules && preg_match('/pagename=\\$matches\\[([0-9]+)\\]/', $query, $varmatch)) { // This is a verbose page match, let's check to be sure about it. $page = get_page_by_path($matches[$varmatch[1]]); if (!$page) { continue; } $post_status_obj = get_post_status_object($page->post_status); if (!$post_status_obj->public && !$post_status_obj->protected && !$post_status_obj->private && $post_status_obj->exclude_from_search) { continue; } } // Got a match. $this->matched_rule = $match; break; } } } if (isset($this->matched_rule)) { // Trim the query of everything up to the '?'. $query = preg_replace("!^.+\\?!", '', $query); // Substitute the substring matches into the query. $query = addslashes(WP_MatchesMapRegex::apply($query, $matches)); $this->matched_query = $query; // Parse the query. parse_str($query, $perma_query_vars); // If we're processing a 404 request, clear the error var since we found something. if ('404' == $error) { unset($error, $_GET['error']); } } // If req_uri is empty or if it is a request for ourself, unset error. if (empty($requested_path) || $requested_file == $self || strpos($_SERVER['PHP_SELF'], 'wp-admin/') !== false) { unset($error, $_GET['error']); if (isset($perma_query_vars) && strpos($_SERVER['PHP_SELF'], 'wp-admin/') !== false) { unset($perma_query_vars); } $this->did_permalink = false; } } /** * Filter the query variables whitelist before processing. * * Allows (publicly allowed) query vars to be added, removed, or changed prior * to executing the query. Needed to allow custom rewrite rules using your own arguments * to work, or any other custom query variables you want to be publicly available. * * @since 1.5.0 * * @param array $public_query_vars The array of whitelisted query variables. */ $this->public_query_vars = apply_filters('query_vars', $this->public_query_vars); foreach (get_post_types(array(), 'objects') as $post_type => $t) { if (is_post_type_viewable($t) && $t->query_var) { $post_type_query_vars[$t->query_var] = $post_type; } } foreach ($this->public_query_vars as $wpvar) { if (isset($this->extra_query_vars[$wpvar])) { $this->query_vars[$wpvar] = $this->extra_query_vars[$wpvar]; } elseif (isset($_POST[$wpvar])) { $this->query_vars[$wpvar] = $_POST[$wpvar]; } elseif (isset($_GET[$wpvar])) { $this->query_vars[$wpvar] = $_GET[$wpvar]; } elseif (isset($perma_query_vars[$wpvar])) { $this->query_vars[$wpvar] = $perma_query_vars[$wpvar]; } if (!empty($this->query_vars[$wpvar])) { if (!is_array($this->query_vars[$wpvar])) { $this->query_vars[$wpvar] = (string) $this->query_vars[$wpvar]; } else { foreach ($this->query_vars[$wpvar] as $vkey => $v) { if (!is_object($v)) { $this->query_vars[$wpvar][$vkey] = (string) $v; } } } if (isset($post_type_query_vars[$wpvar])) { $this->query_vars['post_type'] = $post_type_query_vars[$wpvar]; $this->query_vars['name'] = $this->query_vars[$wpvar]; } } } // Convert urldecoded spaces back into + foreach (get_taxonomies(array(), 'objects') as $taxonomy => $t) { if ($t->query_var && isset($this->query_vars[$t->query_var])) { $this->query_vars[$t->query_var] = str_replace(' ', '+', $this->query_vars[$t->query_var]); } } // Don't allow non-publicly queryable taxonomies to be queried from the front end. if (!is_admin()) { foreach (get_taxonomies(array('publicly_queryable' => false), 'objects') as $taxonomy => $t) { /* * Disallow when set to the 'taxonomy' query var. * Non-publicly queryable taxonomies cannot register custom query vars. See register_taxonomy(). */ if (isset($this->query_vars['taxonomy']) && $taxonomy === $this->query_vars['taxonomy']) { unset($this->query_vars['taxonomy'], $this->query_vars['term']); } } } // Limit publicly queried post_types to those that are publicly_queryable if (isset($this->query_vars['post_type'])) { $queryable_post_types = get_post_types(array('publicly_queryable' => true)); if (!is_array($this->query_vars['post_type'])) { if (!in_array($this->query_vars['post_type'], $queryable_post_types)) { unset($this->query_vars['post_type']); } } else { $this->query_vars['post_type'] = array_intersect($this->query_vars['post_type'], $queryable_post_types); } } // Resolve conflicts between posts with numeric slugs and date archive queries. $this->query_vars = wp_resolve_numeric_slug_conflicts($this->query_vars); foreach ((array) $this->private_query_vars as $var) { if (isset($this->extra_query_vars[$var])) { $this->query_vars[$var] = $this->extra_query_vars[$var]; } } if (isset($error)) { $this->query_vars['error'] = $error; } /** * Filter the array of parsed query variables. * * @since 2.1.0 * * @param array $query_vars The array of requested query variables. */ $this->query_vars = apply_filters('request', $this->query_vars); /** * Fires once all query variables for the current request have been parsed. * * @since 2.1.0 * * @param WP &$this Current WordPress environment instance (passed by reference). */ do_action_ref_array('parse_request', array(&$this)); }
/** * @ticket 35609 */ public function test_should_return_false_for_bad_post_type_name() { $this->assertFalse(is_post_type_viewable('foo')); }
/** * Retrieves a single post. * * @since 4.7.0 * @access public * * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. */ public function get_item($request) { $id = (int) $request['id']; $post = get_post($id); if (empty($id) || empty($post->ID) || $this->post_type !== $post->post_type) { return new WP_Error('rest_post_invalid_id', __('Invalid post ID.'), array('status' => 404)); } $data = $this->prepare_item_for_response($post, $request); $response = rest_ensure_response($data); if (is_post_type_viewable(get_post_type_object($post->post_type))) { $response->link_header('alternate', get_permalink($id), array('type' => 'text/html')); } return $response; }
/** * Adds the necessary rewrite rules for the post type. * * @since 4.6.0 * @access public * * @global WP_Rewrite $wp_rewrite WordPress Rewrite Component. * @global WP $wp Current WordPress environment instance. */ public function add_rewrite_rules() { global $wp_rewrite, $wp; if (false !== $this->query_var && $wp && is_post_type_viewable($this)) { $wp->add_query_var($this->query_var); } if (false !== $this->rewrite && (is_admin() || '' != get_option('permalink_structure'))) { if ($this->hierarchical) { add_rewrite_tag("%{$this->name}%", '(.+?)', $this->query_var ? "{$this->query_var}=" : "post_type={$this->name}&pagename="); } else { add_rewrite_tag("%{$this->name}%", '([^/]+)', $this->query_var ? "{$this->query_var}=" : "post_type={$this->name}&name="); } if ($this->has_archive) { $archive_slug = true === $this->has_archive ? $this->rewrite['slug'] : $this->has_archive; if ($this->rewrite['with_front']) { $archive_slug = substr($wp_rewrite->front, 1) . $archive_slug; } else { $archive_slug = $wp_rewrite->root . $archive_slug; } add_rewrite_rule("{$archive_slug}/?\$", "index.php?post_type={$this->name}", 'top'); if ($this->rewrite['feeds'] && $wp_rewrite->feeds) { $feeds = '(' . trim(implode('|', $wp_rewrite->feeds)) . ')'; add_rewrite_rule("{$archive_slug}/feed/{$feeds}/?\$", "index.php?post_type={$this->name}" . '&feed=$matches[1]', 'top'); add_rewrite_rule("{$archive_slug}/{$feeds}/?\$", "index.php?post_type={$this->name}" . '&feed=$matches[1]', 'top'); } if ($this->rewrite['pages']) { add_rewrite_rule("{$archive_slug}/{$wp_rewrite->pagination_base}/([0-9]{1,})/?\$", "index.php?post_type={$this->name}" . '&paged=$matches[1]', 'top'); } } $permastruct_args = $this->rewrite; $permastruct_args['feed'] = $permastruct_args['feeds']; add_permastruct($this->name, "{$this->rewrite['slug']}/%{$this->name}%", $permastruct_args); } }
/** * Get the formatted date & time for the activity * * @since 0.1.0 * * @param int $post_id * * @return string */ protected function get_how_long_ago($post_id = 0) { // Get the post $post = get_post($post_id); $date = get_the_date(get_option('date_format'), $post->ID); $time = get_the_time(get_option('time_format'), $post->ID); $both = "{$date} {$time}"; // Get the human readable difference $pt = strtotime($post->post_date_gmt); $human = wp_user_activity_human_diff_time($pt, current_time('timestamp', true)); // Start with the timestamp $classes = get_post_class('wp-user-activity', $post->ID); $url = false; $retval = '<time class="diff-time" pubdate datetime="' . esc_attr($both) . '" title="' . esc_attr($both) . '">' . sprintf('%s ago', $human) . '</time>'; // Edit link if (is_admin() && current_user_can('edit_activity', $post->ID)) { $classes[] = 'edit-link'; $url = get_edit_post_link($post->ID); // View link } elseif (is_post_type_viewable(get_post_type_object($post->post_type))) { $classes[] = 'view-link'; $url = get_post_permalink($post->ID); } // Wrap time in anchor tag if (!empty($url)) { $retval = '<a href="' . esc_url($url) . '" class="' . join(' ', $classes) . '">' . $retval . '</a>'; } return $retval; }
$post->post_type = $post_type; $post->post_parent = $post_parent; } $post->post_status = 'publish'; $post->post_name = $slug; if ($post->post_type === 'page') { } $desired_permalink = get_permalink($post); $parsed = parse_url($desired_permalink); $desired_path = trim($parsed['path'], '/'); /* * Copied from $wp->parse_request(). This function seems to do a lot of housekeeping * which should probably be accessible if other things should be able to mock out and fake requests. */ foreach (get_post_types(array(), 'objects') as $post_type => $t) { if (is_post_type_viewable($t) && $t->query_var) { $post_type_query_vars[$t->query_var] = $post_type; } } // Find a rewrite. Depends on #18877. $rewrite = $wp_rewrite->wp_rewrite_rules(); $found_rewrite_match = $wp_rewrite->find_match($desired_path, $desired_path, $rewrite); if ($found_rewrite_match) { $query_string = $found_rewrite_match[1]; parse_str($query_string, $query_args); foreach ($wp->public_query_vars as $wpvar) { if (!empty($query_args[$wpvar])) { if (isset($post_type_query_vars[$wpvar])) { $query_args['post_type'] = $post_type_query_vars[$wpvar]; $query_args['name'] = $query_args[$wpvar]; // Unset the `{post_type_name}` query variable, as the `name` qv will suffice.
public function queue_post_purge($post_id) { if ($this->site_cache_purged) { return false; } if (defined('WP_IMPORTING')) { $this->purge_site_cache(); return false; } $post = get_post($post_id); if (empty($post) || 'revision' === $post->post_type || !in_array(get_post_status($post_id), array('publish', 'inherit', 'trash'), true)) { return false; } if (!is_post_type_viewable($post->post_type)) { return; } $post_purge_urls = array(); $post_purge_urls[] = get_permalink($post_id); $post_purge_urls[] = home_url('/'); // Don't just purge the attachment page, but also include the file itself if ('attachment' === $post->post_type) { $this->purge_urls[] = wp_get_attachment_url($post_id); } $taxonomies = get_object_taxonomies($post, 'object'); foreach ($taxonomies as $taxonomy) { if (true !== $taxonomy->public) { continue; } $taxonomy_name = $taxonomy->name; $terms = get_the_terms($post_id, $taxonomy_name); if (false === $terms) { continue; } foreach ($terms as $term) { $post_purge_urls = array_merge($post_purge_urls, $this->get_purge_urls_for_term($term)); } } // Purge the standard site feeds // @TODO Do we need to PURGE the comment feeds if the post_status is publish? $site_feeds = array(get_bloginfo('rdf_url'), get_bloginfo('rss_url'), get_bloginfo('rss2_url'), get_bloginfo('atom_url'), get_bloginfo('comments_atom_url'), get_bloginfo('comments_rss2_url'), get_post_comments_feed_link($post_id)); $post_purge_urls = array_merge($post_purge_urls, $site_feeds); /** * Allows adding URLs to be PURGEd from cache when a given post ID is PURGEd * * Developers can hook this filter and check the post being purged in order * to also purge related URLs, e.g. feeds. * * Related category archives, tag archives, generic feeds, etc, are already * included to be purged (see code above). * * PLEASE NOTE: Your site benefits from the performance that our HTTP * Reverse Proxy Caching provides, and purging URLs from that cache * should be done cautiously. VIP may push back on use of this filter * during initial code review and pre-deployment review where we * see issues. * * @deprecated 1.1 Use `wpcom_vip_cache_purge_{post_type}_urls` instead * @param array $this->purge_urls { * An array of URLs for you to add to * } * @param type $post_id The ID of the post which is the primary reason for the purge */ $post_purge_urls = apply_filters('wpcom_vip_cache_purge_urls', $post_purge_urls, $post_id); $this->purge_urls = array_merge($this->purge_urls, $post_purge_urls); /** * Allows adding URLs to be PURGEd from cache when a given post ID is PURGEd * * Developers can hook this filter and check the post being purged in order * to also purge related URLs, e.g. feeds. * * Related category archives, tag archives, generic feeds, etc, are already * included to be purged (see code above). * * PLEASE NOTE: Your site benefits from the performance that our HTTP * Reverse Proxy Caching provides, and purging URLs from that cache * should be done cautiously. VIP may push back on use of this filter * during initial code review and pre-deployment review where we * see issues. * * @param array $this->purge_urls { * An array of URLs for you to add to * } * @param type $post_id The ID of the post which is the primary reason for the purge */ $this->purge_urls = apply_filters("wpcom_vip_cache_purge_{$post->post_type}_post_urls", $this->purge_urls, $post_id); $this->purge_urls = array_unique($this->purge_urls); return true; }