id = 'betterdocs/list-docs'; $this->label = __( 'List docs', 'betterdocs' ); $this->description = __( 'List and filter BetterDocs docs by search text, category, tag, knowledge base, glossary term, status, author or slug. Terms may be given by id, slug or name; a filter never creates a term. Returns a page of doc summaries. total counts every match, while items omits any doc this user may not read, so a page can be shorter than total suggests.', 'betterdocs' ); $this->capability = 'edit_docs'; } /** * @since 4.9.0 * * @return array */ public function get_annotations() { return [ 'readonly' => true, 'destructive' => false, 'idempotent' => true, 'priority' => 1.5, 'openWorldHint' => false ]; } /** * @since 4.9.0 * * @return array */ public function get_input_schema() { return [ 'type' => 'object', 'additionalProperties' => false, 'properties' => [ 'search' => [ 'type' => 'string', 'description' => __( 'Free-text search over title and content.', 'betterdocs' ) ], 'category' => [ 'type' => [ 'integer', 'string' ], 'description' => __( 'A doc category, by id, slug or name. Never created.', 'betterdocs' ) ], 'tag' => [ 'type' => [ 'integer', 'string' ], 'description' => __( 'A doc tag, by id, slug or name. Never created.', 'betterdocs' ) ], 'knowledge_base' => [ 'type' => [ 'integer', 'string' ], 'description' => __( 'A knowledge base, by id, slug or name. Never created.', 'betterdocs' ) ], 'glossary' => [ 'type' => [ 'integer', 'string' ], 'description' => __( 'A glossary term, by id, slug or name. Never created. Needs the enable_glossaries setting on.', 'betterdocs' ) ], 'status' => [ 'type' => 'string', 'enum' => self::STATUSES, 'default' => 'any', 'description' => __( 'Publication status to filter on. Defaults to any.', 'betterdocs' ) ], 'author' => [ 'type' => 'integer', 'description' => __( 'Only docs by this user id.', 'betterdocs' ) ], 'slug' => [ 'type' => 'string', 'description' => __( 'Only the doc with this exact slug.', 'betterdocs' ) ], 'orderby' => [ 'type' => 'string', 'enum' => [ 'date', 'modified', 'title', 'menu_order', 'relevance', 'id' ], 'default' => 'date', 'description' => __( 'Sort field. relevance only means anything alongside search.', 'betterdocs' ) ], 'order' => [ 'type' => 'string', 'enum' => [ 'asc', 'desc' ], 'default' => 'desc' ], 'page' => [ 'type' => 'integer', 'minimum' => 1, 'default' => 1 ], 'per_page' => [ 'type' => 'integer', 'minimum' => 1, 'maximum' => 100, 'default' => 20, 'description' => __( 'Docs per page, 1–100.', 'betterdocs' ) ] ], 'default' => [] ]; } /** * @since 4.9.0 * * @return array */ public function get_output_schema() { return [ 'type' => 'object', 'properties' => [ 'items' => [ 'type' => 'array', 'items' => [ 'type' => 'object', 'properties' => self::doc_summary_schema() ] ], 'total' => [ 'type' => 'integer' ], 'total_pages' => [ 'type' => 'integer' ], 'page' => [ 'type' => 'integer' ], 'per_page' => [ 'type' => 'integer' ] ] ]; } /** * @since 4.9.0 * * @param array $input Validated input. * @return array|\WP_Error */ public function execute( $input ) { $page = isset( $input['page'] ) ? max( 1, (int) $input['page'] ) : 1; $per_page = isset( $input['per_page'] ) ? (int) $input['per_page'] : 20; $params = [ 'context' => 'view', 'status' => isset( $input['status'] ) ? (string) $input['status'] : 'any', 'orderby' => isset( $input['orderby'] ) ? (string) $input['orderby'] : 'date', 'order' => isset( $input['order'] ) ? (string) $input['order'] : 'desc', 'page' => $page, 'per_page' => $per_page ]; foreach ( [ 'search', 'slug' ] as $field ) { if ( isset( $input[ $field ] ) && '' !== (string) $input[ $field ] ) { $params[ $field ] = (string) $input[ $field ]; } } if ( isset( $input['author'] ) ) { $params['author'] = (int) $input['author']; } $filters = [ 'category' => 'doc_category', 'tag' => 'doc_tag', 'knowledge_base' => 'knowledge_base', 'glossary' => 'glossaries' ]; foreach ( $filters as $field => $taxonomy ) { if ( ! isset( $input[ $field ] ) || '' === $input[ $field ] ) { continue; } // `false`: a filter never creates the term it is filtering on. $ids = $this->resolve_terms( [ $input[ $field ] ], $taxonomy, false ); if ( is_wp_error( $ids ) ) { return $ids; } $params[ $taxonomy ] = $ids; } $response = $this->dispatch_response( 'GET', '/docs', $params, 'wp/v2' ); if ( $response->is_error() ) { $error = $response->as_error(); // A page past the last one is an empty page, not a missing doc. if ( $this->is_page_out_of_range( $error ) ) { return $this->empty_page( '/docs', $params, $page, $per_page, 'wp/v2' ); } return $this->map_rest_error( $error, __( 'list docs', 'betterdocs' ) ); } $headers = $response->get_headers(); $items = []; foreach ( (array) $response->get_data() as $doc ) { $items[] = $this->doc_summary( (array) $doc ); } return [ 'items' => $items, 'total' => isset( $headers['X-WP-Total'] ) ? (int) $headers['X-WP-Total'] : count( $items ), 'total_pages' => isset( $headers['X-WP-TotalPages'] ) ? (int) $headers['X-WP-TotalPages'] : 1, 'page' => $page, 'per_page' => $per_page ]; } }