mirror of
				https://github.com/mashirozx/sakura.git
				synced 2025-05-29 01:49:21 +08:00 
			
		
		
		
	Add tags and categories page
wip tags & categories
This commit is contained in:
		
							parent
							
								
									e9d5c98b6d
								
							
						
					
					
						commit
						6f396c25ba
					
				| @ -13,6 +13,7 @@ new \Sakura\Helpers\WhoopsHelper(); | |||||||
| new \Sakura\Helpers\ViteRequireHelper(); | new \Sakura\Helpers\ViteRequireHelper(); | ||||||
| new \Sakura\Helpers\CustomMenuMetaFieldsHelper(); | new \Sakura\Helpers\CustomMenuMetaFieldsHelper(); | ||||||
| new \Sakura\Helpers\CommentHelper(); | new \Sakura\Helpers\CommentHelper(); | ||||||
|  | new \Sakura\Helpers\PostQueryHelper('post'); | ||||||
| 
 | 
 | ||||||
| new \Sakura\Routers\ApiRouter(); | new \Sakura\Routers\ApiRouter(); | ||||||
| new \Sakura\Routers\PagesRouter(); | new \Sakura\Routers\PagesRouter(); | ||||||
|  | |||||||
							
								
								
									
										51
									
								
								app/helpers/post-query-helper.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								app/helpers/post-query-helper.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | |||||||
|  | <?php | ||||||
|  | 
 | ||||||
|  | namespace Sakura\Helpers; | ||||||
|  | 
 | ||||||
|  | class PostQueryHelper | ||||||
|  | { | ||||||
|  |   /** | ||||||
|  |    * Post type. | ||||||
|  |    * | ||||||
|  |    * @since 5.0.0 | ||||||
|  |    * @var string | ||||||
|  |    */ | ||||||
|  |   protected $post_type; | ||||||
|  | 
 | ||||||
|  |   public function __construct(string $post_type) | ||||||
|  |   { | ||||||
|  |     $this->post_type = $post_type; | ||||||
|  |     add_filter("rest_{$post_type}_query", [$this, 'filter_rest_post_query'], 10, 2); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   /** | ||||||
|  |    * Filter rest posts by category slug | ||||||
|  |    * | ||||||
|  |    * @param array $args | ||||||
|  |    * @param WP_Rest_Rquest $request | ||||||
|  |    * @return array $args | ||||||
|  |    */ | ||||||
|  |   public function filter_rest_post_query($args, $request) | ||||||
|  |   { | ||||||
|  |     $args['tax_query'] = []; | ||||||
|  | 
 | ||||||
|  |     $taxonomies = wp_list_filter(get_object_taxonomies($this->post_type, 'objects'), array('show_in_rest' => true)); | ||||||
|  | 
 | ||||||
|  |     foreach ($taxonomies as $taxonomy) { | ||||||
|  |       $base = !empty($taxonomy->rest_base) ? $taxonomy->rest_base : $taxonomy->name; | ||||||
|  | 
 | ||||||
|  |       if (!isset($request["{$base}_slug"])) { | ||||||
|  |         continue; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       array_push($args['tax_query'], [ | ||||||
|  |         'taxonomy'         => $taxonomy->name, | ||||||
|  |         'field'            => 'slug', | ||||||
|  |         'terms'            => explode(',', $request["{$base}_slug"]), | ||||||
|  |         'include_children' => true, | ||||||
|  |         'operator'         => 'IN', | ||||||
|  |       ]); | ||||||
|  |     } | ||||||
|  |     return $args; | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										58
									
								
								app/helpers/rest-api-filter-helper.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								app/helpers/rest-api-filter-helper.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | |||||||
|  | <?php | ||||||
|  | 
 | ||||||
|  | namespace Sakura\Helpers; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * @deprecated use apply_filters( "rest_{$this->post_type}_query", array $args, WP_REST_Request $request ) or filter instead | ||||||
|  |  */ | ||||||
|  | class RestApiFilterHelper | ||||||
|  | { | ||||||
|  |   public function __construct() | ||||||
|  |   { | ||||||
|  |     add_action('rest_api_init', [$this, 'rest_api_filter_add_filters']); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   /** | ||||||
|  |    * Add the necessary filter to each post type | ||||||
|  |    **/ | ||||||
|  |   public function rest_api_filter_add_filters() | ||||||
|  |   { | ||||||
|  |     foreach (get_post_types(array('show_in_rest' => true), 'objects') as $post_type) { | ||||||
|  |       add_filter('rest_' . $post_type->name . '_query', [$this, 'rest_api_filter_add_filter_param'], 10, 2); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   /** | ||||||
|  |    * Add the filter parameter | ||||||
|  |    * | ||||||
|  |    * @param  array           $args    The query arguments. | ||||||
|  |    * @param  WP_REST_Request $request Full details about the request. | ||||||
|  |    * @return array $args. | ||||||
|  |    **/ | ||||||
|  |   public function rest_api_filter_add_filter_param($args, $request) | ||||||
|  |   { | ||||||
|  |     // Bail out if no filter parameter is set.
 | ||||||
|  |     if (empty($request['filter']) || !is_array($request['filter'])) { | ||||||
|  |       return $args; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     $filter = $request['filter']; | ||||||
|  | 
 | ||||||
|  |     if (isset($filter['posts_per_page']) && ((int) $filter['posts_per_page'] >= 1 && (int) $filter['posts_per_page'] <= 100)) { | ||||||
|  |       $args['posts_per_page'] = $filter['posts_per_page']; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     global $wp; | ||||||
|  |     $vars = apply_filters('rest_query_vars', $wp->public_query_vars); | ||||||
|  | 
 | ||||||
|  |     // Allow valid meta query vars.
 | ||||||
|  |     $vars = array_unique(array_merge($vars, array('meta_query', 'meta_key', 'meta_value', 'meta_compare'))); | ||||||
|  | 
 | ||||||
|  |     foreach ($vars as $var) { | ||||||
|  |       if (isset($filter[$var])) { | ||||||
|  |         $args[$var] = $filter[$var]; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     return $args; | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										357
									
								
								app/lib/class-wp-rest-posts-controller.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										357
									
								
								app/lib/class-wp-rest-posts-controller.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,357 @@ | |||||||
|  | <?php | ||||||
|  | 
 | ||||||
|  | namespace Sakura\Lib; | ||||||
|  | 
 | ||||||
|  | use WP_REST_Posts_Controller; | ||||||
|  | use WP_REST_Request; | ||||||
|  | use WP_Error; | ||||||
|  | use WP_Query; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * @deprecated use apply_filters( "rest_{$this->post_type}_query", array $args, WP_REST_Request $request ) instead | ||||||
|  |  */ | ||||||
|  | class ClassWpRestPostsController extends WP_REST_Posts_Controller | ||||||
|  | { | ||||||
|  |   /** | ||||||
|  |    * Retrieves a collection of posts. | ||||||
|  |    * Source: https://github.com/WordPress/wordpress-develop/blob/master/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php | ||||||
|  |    * Memo: only change $registered = $this->get_collection_params_mod(); | ||||||
|  |    * Based on commit 5383af8 | ||||||
|  |    * | ||||||
|  |    * @since 4.7.0 | ||||||
|  |    * | ||||||
|  |    * @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_items($request) | ||||||
|  |   { | ||||||
|  |     // Ensure a search string is set in case the orderby is set to 'relevance'.
 | ||||||
|  |     if (!empty($request['orderby']) && 'relevance' === $request['orderby'] && empty($request['search'])) { | ||||||
|  |       return new WP_Error( | ||||||
|  |         'rest_no_search_term_defined', | ||||||
|  |         __('You need to define a search term to order by relevance.'), | ||||||
|  |         array('status' => 400) | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Ensure an include parameter is set in case the orderby is set to 'include'.
 | ||||||
|  |     if (!empty($request['orderby']) && 'include' === $request['orderby'] && empty($request['include'])) { | ||||||
|  |       return new WP_Error( | ||||||
|  |         'rest_orderby_include_missing_include', | ||||||
|  |         __('You need to define an include parameter to order by include.'), | ||||||
|  |         array('status' => 400) | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Retrieve the list of registered collection query parameters.
 | ||||||
|  |     $registered = $this->get_collection_params_mod(); | ||||||
|  |     $args       = array(); | ||||||
|  | 
 | ||||||
|  |     /* | ||||||
|  | 		 * This array defines mappings between public API query parameters whose | ||||||
|  | 		 * values are accepted as-passed, and their internal WP_Query parameter | ||||||
|  | 		 * name equivalents (some are the same). Only values which are also | ||||||
|  | 		 * present in $registered will be set. | ||||||
|  | 		 */ | ||||||
|  |     $parameter_mappings = array( | ||||||
|  |       'author'         => 'author__in', | ||||||
|  |       'author_exclude' => 'author__not_in', | ||||||
|  |       'exclude'        => 'post__not_in', | ||||||
|  |       'include'        => 'post__in', | ||||||
|  |       'menu_order'     => 'menu_order', | ||||||
|  |       'offset'         => 'offset', | ||||||
|  |       'order'          => 'order', | ||||||
|  |       'orderby'        => 'orderby', | ||||||
|  |       'page'           => 'paged', | ||||||
|  |       'parent'         => 'post_parent__in', | ||||||
|  |       'parent_exclude' => 'post_parent__not_in', | ||||||
|  |       'search'         => 's', | ||||||
|  |       'slug'           => 'post_name__in', | ||||||
|  |       'status'         => 'post_status', | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     /* | ||||||
|  | 		 * For each known parameter which is both registered and present in the request, | ||||||
|  | 		 * set the parameter's value on the query $args. | ||||||
|  | 		 */ | ||||||
|  |     foreach ($parameter_mappings as $api_param => $wp_param) { | ||||||
|  |       if (isset($registered[$api_param], $request[$api_param])) { | ||||||
|  |         $args[$wp_param] = $request[$api_param]; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Check for & assign any parameters which require special handling or setting.
 | ||||||
|  |     $args['date_query'] = array(); | ||||||
|  | 
 | ||||||
|  |     if (isset($registered['before'], $request['before'])) { | ||||||
|  |       $args['date_query'][] = array( | ||||||
|  |         'before' => $request['before'], | ||||||
|  |         'column' => 'post_date', | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (isset($registered['modified_before'], $request['modified_before'])) { | ||||||
|  |       $args['date_query'][] = array( | ||||||
|  |         'before' => $request['modified_before'], | ||||||
|  |         'column' => 'post_modified', | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (isset($registered['after'], $request['after'])) { | ||||||
|  |       $args['date_query'][] = array( | ||||||
|  |         'after'  => $request['after'], | ||||||
|  |         'column' => 'post_date', | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (isset($registered['modified_after'], $request['modified_after'])) { | ||||||
|  |       $args['date_query'][] = array( | ||||||
|  |         'after'  => $request['modified_after'], | ||||||
|  |         'column' => 'post_modified', | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Ensure our per_page parameter overrides any provided posts_per_page filter.
 | ||||||
|  |     if (isset($registered['per_page'])) { | ||||||
|  |       $args['posts_per_page'] = $request['per_page']; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (isset($registered['sticky'], $request['sticky'])) { | ||||||
|  |       $sticky_posts = get_option('sticky_posts', array()); | ||||||
|  |       if (!is_array($sticky_posts)) { | ||||||
|  |         $sticky_posts = array(); | ||||||
|  |       } | ||||||
|  |       if ($request['sticky']) { | ||||||
|  |         /* | ||||||
|  | 				 * As post__in will be used to only get sticky posts, | ||||||
|  | 				 * we have to support the case where post__in was already | ||||||
|  | 				 * specified. | ||||||
|  | 				 */ | ||||||
|  |         $args['post__in'] = $args['post__in'] ? array_intersect($sticky_posts, $args['post__in']) : $sticky_posts; | ||||||
|  | 
 | ||||||
|  |         /* | ||||||
|  | 				 * If we intersected, but there are no post IDs in common, | ||||||
|  | 				 * WP_Query won't return "no posts" for post__in = array() | ||||||
|  | 				 * so we have to fake it a bit. | ||||||
|  | 				 */ | ||||||
|  |         if (!$args['post__in']) { | ||||||
|  |           $args['post__in'] = array(0); | ||||||
|  |         } | ||||||
|  |       } elseif ($sticky_posts) { | ||||||
|  |         /* | ||||||
|  | 				 * As post___not_in will be used to only get posts that | ||||||
|  | 				 * are not sticky, we have to support the case where post__not_in | ||||||
|  | 				 * was already specified. | ||||||
|  | 				 */ | ||||||
|  |         $args['post__not_in'] = array_merge($args['post__not_in'], $sticky_posts); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     $args = $this->prepare_tax_query($args, $request); | ||||||
|  | 
 | ||||||
|  |     // Force the post_type argument, since it's not a user input variable.
 | ||||||
|  |     $args['post_type'] = $this->post_type; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Filters WP_Query arguments when querying posts via the REST API. | ||||||
|  |      * | ||||||
|  |      * The dynamic portion of the hook name, `$this->post_type`, refers to the post type slug. | ||||||
|  |      * | ||||||
|  |      * Possible hook names include: | ||||||
|  |      * | ||||||
|  |      *  - `rest_post_query` | ||||||
|  |      *  - `rest_page_query` | ||||||
|  |      *  - `rest_attachment_query` | ||||||
|  |      * | ||||||
|  |      * Enables adding extra arguments or setting defaults for a post collection request. | ||||||
|  |      * | ||||||
|  |      * @since 4.7.0 | ||||||
|  |      * @since 5.7.0 Moved after the `tax_query` query arg is generated. | ||||||
|  |      * | ||||||
|  |      * @link https://developer.wordpress.org/reference/classes/wp_query/ | ||||||
|  |      * | ||||||
|  |      * @param array           $args    Array of arguments for WP_Query. | ||||||
|  |      * @param WP_REST_Request $request The REST API request. | ||||||
|  |      */ | ||||||
|  |     $args       = apply_filters("rest_{$this->post_type}_query", $args, $request); | ||||||
|  |     $query_args = $this->prepare_items_query($args, $request); | ||||||
|  |     $posts_query  = new WP_Query(); | ||||||
|  |     $query_result = $posts_query->query($query_args); | ||||||
|  | 
 | ||||||
|  |     // Allow access to all password protected posts if the context is edit.
 | ||||||
|  |     if ('edit' === $request['context']) { | ||||||
|  |       add_filter('post_password_required', array($this, 'check_password_required'), 10, 2); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     $posts = array(); | ||||||
|  | 
 | ||||||
|  |     foreach ($query_result as $post) { | ||||||
|  |       if (!$this->check_read_permission($post)) { | ||||||
|  |         continue; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       $data    = $this->prepare_item_for_response($post, $request); | ||||||
|  |       $posts[] = $this->prepare_response_for_collection($data); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Reset filter.
 | ||||||
|  |     if ('edit' === $request['context']) { | ||||||
|  |       remove_filter('post_password_required', array($this, 'check_password_required')); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     $page        = (int) $query_args['paged']; | ||||||
|  |     $total_posts = $posts_query->found_posts; | ||||||
|  | 
 | ||||||
|  |     if ($total_posts < 1) { | ||||||
|  |       // Out-of-bounds, run the query again without LIMIT for total count.
 | ||||||
|  |       unset($query_args['paged']); | ||||||
|  | 
 | ||||||
|  |       $count_query = new WP_Query(); | ||||||
|  |       $count_query->query($query_args); | ||||||
|  |       $total_posts = $count_query->found_posts; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     $max_pages = ceil($total_posts / (int) $posts_query->query_vars['posts_per_page']); | ||||||
|  | 
 | ||||||
|  |     if ($page > $max_pages && $total_posts > 0) { | ||||||
|  |       return new WP_Error( | ||||||
|  |         'rest_post_invalid_page_number', | ||||||
|  |         __('The page number requested is larger than the number of pages available.'), | ||||||
|  |         array('status' => 400) | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     $response = rest_ensure_response($posts); | ||||||
|  | 
 | ||||||
|  |     $response->header('X-WP-Total', (int) $total_posts); | ||||||
|  |     $response->header('X-WP-TotalPages', (int) $max_pages); | ||||||
|  | 
 | ||||||
|  |     $request_params = $request->get_query_params(); | ||||||
|  |     $base           = add_query_arg(urlencode_deep($request_params), rest_url(sprintf('%s/%s', $this->namespace, $this->rest_base))); | ||||||
|  | 
 | ||||||
|  |     if ($page > 1) { | ||||||
|  |       $prev_page = $page - 1; | ||||||
|  | 
 | ||||||
|  |       if ($prev_page > $max_pages) { | ||||||
|  |         $prev_page = $max_pages; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       $prev_link = add_query_arg('page', $prev_page, $base); | ||||||
|  |       $response->link_header('prev', $prev_link); | ||||||
|  |     } | ||||||
|  |     if ($max_pages > $page) { | ||||||
|  |       $next_page = $page + 1; | ||||||
|  |       $next_link = add_query_arg('page', $next_page, $base); | ||||||
|  | 
 | ||||||
|  |       $response->link_header('next', $next_link); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return $response; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   /** | ||||||
|  |    * Prepares the 'tax_query' for a collection of posts. | ||||||
|  |    * | ||||||
|  |    * @since 5.7.0 | ||||||
|  |    * | ||||||
|  |    * @param array           $args    WP_Query arguments. | ||||||
|  |    * @param WP_REST_Request $request Full details about the request. | ||||||
|  |    * @return array Updated query arguments. | ||||||
|  |    */ | ||||||
|  |   private function prepare_tax_query(array $args, WP_REST_Request $request) | ||||||
|  |   { | ||||||
|  |     $relation = $request['tax_relation']; | ||||||
|  | 
 | ||||||
|  |     if ($relation) { | ||||||
|  |       $args['tax_query'] = array('relation' => $relation); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     $taxonomies = wp_list_filter( | ||||||
|  |       get_object_taxonomies($this->post_type, 'objects'), | ||||||
|  |       array('show_in_rest' => true) | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     foreach ($taxonomies as $taxonomy) { | ||||||
|  |       $base = !empty($taxonomy->rest_base) ? $taxonomy->rest_base : $taxonomy->name; | ||||||
|  | 
 | ||||||
|  |       $tax_include = $request[$base]; | ||||||
|  |       $tax_exclude = $request[$base . '_exclude']; | ||||||
|  | 
 | ||||||
|  |       if ($tax_include) { | ||||||
|  |         $terms            = array(); | ||||||
|  |         $include_children = false; | ||||||
|  |         $operator         = 'IN'; | ||||||
|  | 
 | ||||||
|  |         if (rest_is_array($tax_include)) { | ||||||
|  |           $terms = $tax_include; | ||||||
|  |         } elseif (rest_is_object($tax_include)) { | ||||||
|  |           $terms            = empty($tax_include['terms']) ? array() : $tax_include['terms']; | ||||||
|  |           $include_children = !empty($tax_include['include_children']); | ||||||
|  | 
 | ||||||
|  |           if (isset($tax_include['operator']) && 'AND' === $tax_include['operator']) { | ||||||
|  |             $operator = 'AND'; | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if ($terms) { | ||||||
|  |           $args['tax_query'][] = array( | ||||||
|  |             'taxonomy'         => $taxonomy->name, | ||||||
|  |             'field'            => 'slug', // 'term_id',
 | ||||||
|  |             'terms'            => $terms, | ||||||
|  |             'include_children' => $include_children, | ||||||
|  |             'operator'         => $operator, | ||||||
|  |           ); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if ($tax_exclude) { | ||||||
|  |         $terms            = array(); | ||||||
|  |         $include_children = false; | ||||||
|  | 
 | ||||||
|  |         if (rest_is_array($tax_exclude)) { | ||||||
|  |           $terms = $tax_exclude; | ||||||
|  |         } elseif (rest_is_object($tax_exclude)) { | ||||||
|  |           $terms            = empty($tax_exclude['terms']) ? array() : $tax_exclude['terms']; | ||||||
|  |           $include_children = !empty($tax_exclude['include_children']); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if ($terms) { | ||||||
|  |           $args['tax_query'][] = array( | ||||||
|  |             'taxonomy'         => $taxonomy->name, | ||||||
|  |             'field'            => 'term_id', | ||||||
|  |             'terms'            => $terms, | ||||||
|  |             'include_children' => $include_children, | ||||||
|  |             'operator'         => 'NOT IN', | ||||||
|  |           ); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return $args; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   public function get_public_item_schema_mod() | ||||||
|  |   { | ||||||
|  |     $schema = $this->get_public_item_schema(); | ||||||
|  |     $schema['properties']['categories']['items']['type'] = [ | ||||||
|  |       "string", | ||||||
|  |       "integer" | ||||||
|  |     ]; | ||||||
|  |     return $schema; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   public function get_collection_params_mod() | ||||||
|  |   { | ||||||
|  |     $params = $this->get_collection_params(); | ||||||
|  |     $new  = [ | ||||||
|  |       "title" => "Term Slug", | ||||||
|  |       "description" => "Match terms with the listed Slug.", | ||||||
|  |       "type" => "array", | ||||||
|  |       "items" => [ | ||||||
|  |         "type" => "string" | ||||||
|  |       ] | ||||||
|  |     ]; | ||||||
|  |     $params['categories']['oneOf'][0] = $new; | ||||||
|  |     return $params; | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -13,6 +13,7 @@ use Sakura\Controllers\CategoryController; | |||||||
| use Sakura\Controllers\TagController; | use Sakura\Controllers\TagController; | ||||||
| use Sakura\Controllers\CommentController; | use Sakura\Controllers\CommentController; | ||||||
| use Sakura\Lib\ClassWpRestCommentsController; | use Sakura\Lib\ClassWpRestCommentsController; | ||||||
|  | use Sakura\Lib\ClassWpRestPostsController; | ||||||
| 
 | 
 | ||||||
| class ApiRouter extends WP_REST_Controller | class ApiRouter extends WP_REST_Controller | ||||||
| { | { | ||||||
| @ -135,6 +136,29 @@ class ApiRouter extends WP_REST_Controller | |||||||
|           'schema' => array($this, 'get_public_item_schema'), |           'schema' => array($this, 'get_public_item_schema'), | ||||||
|         ) |         ) | ||||||
|       ); |       ); | ||||||
|  | 
 | ||||||
|  |       // @deprecated using PostQueryHelper instaed
 | ||||||
|  |       // $rest_posts_controller = new ClassWpRestPostsController('post');
 | ||||||
|  |       // custom get posts by category slugs
 | ||||||
|  |       // register_rest_route(
 | ||||||
|  |       //   $this->namespace,
 | ||||||
|  |       //   '/posts',
 | ||||||
|  |       //   array(
 | ||||||
|  |       //     array(
 | ||||||
|  |       //       'methods'             => WP_REST_Server::READABLE,
 | ||||||
|  |       //       'callback'            => array($rest_posts_controller, 'get_items'),
 | ||||||
|  |       //       'permission_callback' => array($rest_posts_controller, 'get_items_permissions_check'),
 | ||||||
|  |       //       'args'                => $rest_posts_controller->get_collection_params_mod(),
 | ||||||
|  |       //     ),
 | ||||||
|  |       //     array(
 | ||||||
|  |       //       'methods'             => WP_REST_Server::CREATABLE,
 | ||||||
|  |       //       'callback'            => array($rest_posts_controller, 'create_item'),
 | ||||||
|  |       //       'permission_callback' => array($rest_posts_controller, 'create_item_permissions_check'),
 | ||||||
|  |       //       'args'                => $rest_posts_controller->get_endpoint_args_for_item_schema(WP_REST_Server::CREATABLE),
 | ||||||
|  |       //     ),
 | ||||||
|  |       //     'schema' => array($rest_posts_controller, 'get_public_item_schema_mod'),
 | ||||||
|  |       //   )
 | ||||||
|  |       // );
 | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,8 +1,6 @@ | |||||||
| import request, { AxiosPromise } from '@/utils/http' | import request, { AxiosPromise } from '@/utils/http' | ||||||
| import snakecaseKeys from 'snakecase-keys' | import snakecaseKeys from 'snakecase-keys' | ||||||
| 
 | 
 | ||||||
| type WpPostObjectFilter = number | string | number[] | string[] |  | ||||||
| 
 |  | ||||||
| /** | /** | ||||||
|  * GET /wp/v2/posts |  * GET /wp/v2/posts | ||||||
|  * https://developer.wordpress.org/rest-api/reference/posts/#arguments
 |  * https://developer.wordpress.org/rest-api/reference/posts/#arguments
 | ||||||
| @ -16,8 +14,8 @@ export interface GetPostParams { | |||||||
|   author?: string | number |   author?: string | number | ||||||
|   authorExclude?: string | number |   authorExclude?: string | number | ||||||
|   before?: string // ISO8601
 |   before?: string // ISO8601
 | ||||||
|   exclude?: WpPostObjectFilter // TODO: check this
 |   exclude?: number | number[] | ||||||
|   include?: WpPostObjectFilter // TODO: check this
 |   include?: number | number[] | ||||||
|   offset?: number |   offset?: number | ||||||
|   order?: 'asc' | 'desc' // default: desc
 |   order?: 'asc' | 'desc' // default: desc
 | ||||||
|   orderby?: |   orderby?: | ||||||
| @ -31,13 +29,15 @@ export interface GetPostParams { | |||||||
|     | 'slug' |     | 'slug' | ||||||
|     | 'include_slugs' |     | 'include_slugs' | ||||||
|     | 'title' // default: date
 |     | 'title' // default: date
 | ||||||
|   slug?: WpPostObjectFilter // TODO: check this
 |   slug?: string | ||||||
|   status?: string // default: 'publish'
 |   status?: string // default: 'publish'
 | ||||||
|   taxRelation?: 'AND' | 'OR' |   taxRelation?: 'AND' | 'OR' | ||||||
|   categories?: WpPostObjectFilter // TODO: check this
 |   categories?: number | number[] | ||||||
|   categoriesExclude?: WpPostObjectFilter // TODO: check this
 |   categoriesExclude?: number | number[] | ||||||
|   tags?: WpPostObjectFilter // TODO: check this
 |   categoriesSlug?: string | ||||||
|   tagsExclude?: WpPostObjectFilter // TODO: check this
 |   tags?: number | number[] | ||||||
|  |   tagsExclude?: number | number[] | ||||||
|  |   tagsSlug?: string | ||||||
|   sticky?: boolean // TODO: check this
 |   sticky?: boolean // TODO: check this
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -48,8 +48,10 @@ export interface GetPageParams | |||||||
|     | 'taxRelation' |     | 'taxRelation' | ||||||
|     | 'categories' |     | 'categories' | ||||||
|     | 'categoriesExclude' |     | 'categoriesExclude' | ||||||
|  |     | 'categoriesSlug' | ||||||
|     | 'tags' |     | 'tags' | ||||||
|     | 'tagsExclude' |     | 'tagsExclude' | ||||||
|  |     | 'tagsSlug' | ||||||
|     | 'sticky' |     | 'sticky' | ||||||
|   > { |   > { | ||||||
|   menuOrder: any // TODO: check this
 |   menuOrder: any // TODO: check this
 | ||||||
| @ -79,8 +81,8 @@ export interface GetCommentParams { | |||||||
|   authorExclude?: string | number |   authorExclude?: string | number | ||||||
|   author_email?: string |   author_email?: string | ||||||
|   before?: string // ISO8601
 |   before?: string // ISO8601
 | ||||||
|   exclude?: WpPostObjectFilter // TODO: check this
 |   exclude?: number | number[] // TODO: check this
 | ||||||
|   include?: WpPostObjectFilter // TODO: check this
 |   include?: number | number[] // TODO: check this
 | ||||||
|   offset?: number |   offset?: number | ||||||
|   order?: 'asc' | 'desc' // default: desc
 |   order?: 'asc' | 'desc' // default: desc
 | ||||||
|   orderby?: 'date' | 'date_gmt' | 'id' | 'include' | 'post' | 'parent' | 'type' // default: date
 |   orderby?: 'date' | 'date_gmt' | 'id' | 'include' | 'post' | 'parent' | 'type' // default: date
 | ||||||
|  | |||||||
| @ -8,7 +8,13 @@ | |||||||
|       @error="handleError" |       @error="handleError" | ||||||
|       @load="handleLoad" |       @load="handleLoad" | ||||||
|     /> |     /> | ||||||
|     <img v-if="placeholderImage" class="default" :src="placeholderImage" :alt="$props.alt" /> |     <img | ||||||
|  |       v-if="placeholderImage" | ||||||
|  |       class="default" | ||||||
|  |       :src="placeholderImage" | ||||||
|  |       :alt="$props.alt" | ||||||
|  |       :draggable="$props.draggable" | ||||||
|  |     /> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -29,6 +29,12 @@ export default defineComponent({ | |||||||
|     page: { type: Number, default: 1 }, |     page: { type: Number, default: 1 }, | ||||||
|     perPage: { type: Number, default: 10 }, |     perPage: { type: Number, default: 10 }, | ||||||
|     autoLoad: { type: Boolean, default: true }, |     autoLoad: { type: Boolean, default: true }, | ||||||
|  |     fetchParameters: { | ||||||
|  |       type: Object, | ||||||
|  |       default: () => { | ||||||
|  |         return {} | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|   }, |   }, | ||||||
|   setup(props) { |   setup(props) { | ||||||
|     const [listContainerRef, setListContainerRef] = useElementRef() |     const [listContainerRef, setListContainerRef] = useElementRef() | ||||||
| @ -64,7 +70,12 @@ export default defineComponent({ | |||||||
|       fetchPost({ |       fetchPost({ | ||||||
|         state: postsStore, |         state: postsStore, | ||||||
|         namespace: props.namespace, |         namespace: props.namespace, | ||||||
|         opts: { page: currentPage.value, perPage: props.perPage, context: 'embed' }, |         opts: { | ||||||
|  |           page: currentPage.value, | ||||||
|  |           perPage: props.perPage, | ||||||
|  |           context: 'embed', | ||||||
|  |           ...props.fetchParameters, | ||||||
|  |         }, | ||||||
|       }).then(() => { |       }).then(() => { | ||||||
|         get() |         get() | ||||||
|         setFetchStatus('done') |         setFetchStatus('done') | ||||||
| @ -1,11 +1,31 @@ | |||||||
| <template> | <template> | ||||||
|   <h1>Category</h1> |   <Base class="base"> | ||||||
|  |     <div class="main__content"> | ||||||
|  |       <div class="content__wrapper"> | ||||||
|  |         <PostThumbList :namespace="namespace" :fetchParameters="fetchParameters"></PostThumbList> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   </Base> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
| import { defineComponent } from 'vue' | import { defineComponent } from 'vue' | ||||||
|  | import { useRoute } from '@/hooks' | ||||||
|  | import Base from '@/layouts/Base.vue' | ||||||
|  | import PostThumbList from '@/components/lists/postThumbList/PostThumbList.vue' | ||||||
| 
 | 
 | ||||||
| export default defineComponent({ | export default defineComponent({ | ||||||
|   setup() {}, |   components: { Base, PostThumbList }, | ||||||
|  |   setup() { | ||||||
|  |     const route = useRoute() | ||||||
|  |     const { cat1, cat2, cat3 } = route.params | ||||||
|  |     const categories = [cat1, cat2, cat3].filter((cat) => cat) | ||||||
|  |     const namespace = ['categories', ...categories].join('-') | ||||||
|  |     const fetchParameters = { categoriesSlug: categories.join(',') } | ||||||
|  |     return { | ||||||
|  |       namespace, | ||||||
|  |       fetchParameters, | ||||||
|  |     } | ||||||
|  |   }, | ||||||
| }) | }) | ||||||
| </script> | </script> | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ | |||||||
|     <div class="main__content"> |     <div class="main__content"> | ||||||
|       <div class="cover__wrapper"> </div> |       <div class="cover__wrapper"> </div> | ||||||
|       <div class="content__wrapper"> |       <div class="content__wrapper"> | ||||||
|         <PostThumbList></PostThumbList> |         <PostThumbList namespace="homepage"></PostThumbList> | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|   </Base> |   </Base> | ||||||
| @ -11,21 +11,11 @@ | |||||||
| 
 | 
 | ||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
| import { defineComponent } from 'vue' | import { defineComponent } from 'vue' | ||||||
| import { useInjector, useRoute } from '@/hooks' |  | ||||||
| import { posts } from '@/store' |  | ||||||
| import Base from '@/layouts/Base.vue' | import Base from '@/layouts/Base.vue' | ||||||
| import PostThumbList from '@/components/lists/postThembList/PostThumbList.vue' | import PostThumbList from '@/components/lists/postThumbList/PostThumbList.vue' | ||||||
| 
 | 
 | ||||||
| export default defineComponent({ | export default defineComponent({ | ||||||
|   components: { Base, PostThumbList }, |   components: { Base, PostThumbList }, | ||||||
|   setup() { |  | ||||||
|     // const route = useRoute() |  | ||||||
|     // console.log(route.params) |  | ||||||
|     // const { postsStore, fetchPost } = useInjector(posts) |  | ||||||
|     // fetchPost(postsStore, { perPage: 1, page: 10 }).then(async () => { |  | ||||||
|     //   console.log(postsStore.value) |  | ||||||
|     // }) |  | ||||||
|   }, |  | ||||||
| }) | }) | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,11 +1,32 @@ | |||||||
| <template> | <template> | ||||||
|   <h1>Tag</h1> |   <Base class="base"> | ||||||
|  |     <div class="main__content"> | ||||||
|  |       <div class="content__wrapper"> | ||||||
|  |         <PostThumbList :namespace="namespace" :fetchParameters="fetchParameters"></PostThumbList> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   </Base> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
| import { defineComponent } from 'vue' | import { defineComponent } from 'vue' | ||||||
|  | import { useRoute } from '@/hooks' | ||||||
|  | import Base from '@/layouts/Base.vue' | ||||||
|  | import PostThumbList from '@/components/lists/postThumbList/PostThumbList.vue' | ||||||
| 
 | 
 | ||||||
| export default defineComponent({ | export default defineComponent({ | ||||||
|   setup() {}, |   components: { Base, PostThumbList }, | ||||||
|  |   setup() { | ||||||
|  |     const route = useRoute() | ||||||
|  |     console.log(route.params) | ||||||
|  | 
 | ||||||
|  |     const { tag } = route.params | ||||||
|  |     const namespace = ['tags', tag].join('-') | ||||||
|  |     const fetchParameters = { tagsSlug: tag } | ||||||
|  |     return { | ||||||
|  |       namespace, | ||||||
|  |       fetchParameters, | ||||||
|  |     } | ||||||
|  |   }, | ||||||
| }) | }) | ||||||
| </script> | </script> | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user