From 3d3317a80824cb8ace6704f800721d45e8b41e1f Mon Sep 17 00:00:00 2001 From: vnmedeiros Date: Fri, 18 Mar 2022 11:02:28 -0300 Subject: [PATCH] feat: initial structure of metadata section files --- ...nacan-rest-metadata-section-controller.php | 589 ++++++++++++++++++ src/classes/api/tainacan-rest-creator.php | 1 + .../class-tainacan-metadatum-section.php | 114 ++++ .../class-tainacan-metadata-section.php | 288 +++++++++ tests/bootstrap.php | 3 +- 5 files changed, 994 insertions(+), 1 deletion(-) create mode 100644 src/classes/api/endpoints/class-tainacan-rest-metadata-section-controller.php create mode 100644 src/classes/entities/class-tainacan-metadatum-section.php create mode 100644 src/classes/repositories/class-tainacan-metadata-section.php diff --git a/src/classes/api/endpoints/class-tainacan-rest-metadata-section-controller.php b/src/classes/api/endpoints/class-tainacan-rest-metadata-section-controller.php new file mode 100644 index 000000000..43c01c0a0 --- /dev/null +++ b/src/classes/api/endpoints/class-tainacan-rest-metadata-section-controller.php @@ -0,0 +1,589 @@ +rest_base = 'metadatasection'; + parent::__construct(); + add_action('init', array(&$this, 'init_objects'), 11); + } + + /** + * Initialize objects after post_type register + * + * @throws \Exception + */ + public function init_objects() { + $this->metadatum_repository = Repositories\Metadata::get_instance(); + } + + /** + * If POST on metadatum/collection/, then + * a metadatum will be created in matched collection and all your item will receive this metadatum + * + * If POST on metadatum/item/, then a value will be added in a metadatum and metadatum passed + * id body of requisition + * + * Both of GETs return the metadatum of matched objects + * + * @throws \Exception + */ + public function register_routes() { + register_rest_route($this->namespace, '/collection/(?P[\d]+)/' . $this->rest_base . '/(?P[\d]+)', + array( + array( + 'methods' => \WP_REST_Server::READABLE, + 'callback' => array($this, 'get_item'), + 'permission_callback' => array($this, 'get_item_permissions_check'), + 'args' => array( + 'context' => array( + 'type' => 'string', + 'default' => 'view', + 'description' => 'The context in which the request is made.', + 'enum' => array( + 'view', + 'edit' + ) + ), + ), + ), + array( + 'methods' => \WP_REST_Server::EDITABLE, + 'callback' => array($this, 'update_item'), + 'permission_callback' => array($this, 'update_item_permissions_check'), + 'args' => $this->get_endpoint_args_for_item_schema(\WP_REST_Server::EDITABLE) + ), + array( + 'methods' => \WP_REST_Server::DELETABLE, + 'callback' => array($this, 'delete_item'), + 'permission_callback' => array($this, 'delete_item_permissions_check'), + ), + 'schema' => [$this, 'get_schema'] + ) + ); + register_rest_route($this->namespace, '/collection/(?P[\d]+)/' . $this->rest_base, + array( + array( + 'methods' => \WP_REST_Server::READABLE, + 'callback' => array($this, 'get_items'), + 'permission_callback' => array($this, 'get_items_permissions_check'), + 'args' => $this->get_wp_query_params(), + ), + array( + 'methods' => \WP_REST_Server::CREATABLE, + 'callback' => array($this, 'create_item'), + 'permission_callback' => array($this, 'create_item_permissions_check'), + 'args' => $this->get_endpoint_args_for_item_schema(\WP_REST_Server::CREATABLE), + ), + 'schema' => [$this, 'get_schema'] + ) + ); + } + + /** + * @param \WP_REST_Request $request + * + * @return \WP_Error|\WP_REST_Response + */ + public function get_item( $request ) { + $collection_id = isset($request['collection_id']) ? $request['collection_id'] : false; + $metadatum_id = $request['metadatum_id']; + + $offset = ''; + $number = ''; + if($request['offset'] >= 0 && $request['number'] >= 1){ + $offset = $request['offset']; + $number = $request['number']; + } + + $result = $this->metadatum_repository->fetch($metadatum_id, 'OBJECT'); + + if (! $result instanceof Entities\Metadatum) { + return new \WP_REST_Response([ + 'error_message' => __('Metadata with this ID was not found', 'tainacan'), + 'item_id' => $item_id + ], 400); + } + + return new \WP_REST_Response($this->prepare_item_for_response($result, $request), 200); + } + + /** + * @param \WP_REST_Request $request + * + * @return bool|\WP_Error + * @throws \Exception + */ + public function get_item_permissions_check( $request ) { + $metadatum = $this->metadatum_repository->fetch($request['metadatum_id']); + + if ( $metadatum instanceof Entities\Metadatum ) { + return $metadatum->can_read(); + } + + return false; + } + + /** + * @param \WP_REST_Request $request + * + * @param null $collection_id + * + * @return object|void|\WP_Error + * @throws \Exception + */ + public function prepare_item_for_database( $request, $collection_id = null ) { + $metadatum = new Entities\Metadatum(); + + $meta = json_decode( $request, true ); + foreach ( $meta as $key => $value ) { + $set_ = 'set_' . $key; + $metadatum->$set_( $value ); + } + + if($collection_id) { + $collection = new Entities\Collection( $collection_id ); + $metadatum->set_collection( $collection ); + } else { + $metadatum->set_collection_id( 'default' ); + } + + return $metadatum; + } + + /** + * @param \WP_REST_Request $request + * + * @return \WP_Error|\WP_REST_Response + * @throws \Exception + */ + public function create_item( $request ) { + if(!empty($request->get_body()) && isset($request['collection_id'])){ + $collection_id = $request['collection_id']; + + try { + $prepared = $this->prepare_item_for_database( $request->get_body(), $collection_id ); + } catch (\Exception $exception){ + return new \WP_REST_Response($exception->getMessage(), 400); + } + + if($prepared->validate()) { + $metadatum = $this->metadatum_repository->insert( $prepared); + + $response = $this->prepare_item_for_response($metadatum, $request); + + return new \WP_REST_Response($response, 201); + } else { + return new \WP_REST_Response([ + 'error_message' => __('One or more values are invalid.', 'tainacan'), + 'errors' => $prepared->get_errors(), + 'metadatum' => $this->prepare_item_for_response($prepared, $request), + ], 400); + } + } elseif (!empty($request->get_body())) { + try { + $prepared = $this->prepare_item_for_database( $request->get_body() ); + } catch ( \Exception $exception ) { + return new \WP_REST_Response( $exception->getMessage(), 400 ); + } + + if ( $prepared->validate() ) { + $metadatum = $this->metadatum_repository->insert( $prepared ); + + $response = $this->prepare_item_for_response($metadatum, $request); + + return new \WP_REST_Response($response, 201); + } else { + return new \WP_REST_Response([ + 'error_message' => __('One or more values are invalid.', 'tainacan'), + 'errors' => $prepared->get_errors(), + 'metadatum' => $this->prepare_item_for_response($prepared, $request), + ], 400); + } + + } + + return new \WP_REST_Response([ + 'error_message' => __('Body cannot be empty.', 'tainacan'), + 'item' => $request->get_body() + ], 400); + + } + + /** + * @param $request + * + * @return bool|\WP_Error + * @throws \Exception + */ + public function create_item_permissions_check( $request ) { + + if( isset($request['collection_id']) ) { + $collection = $this->collection_repository->fetch( $request['collection_id'] ); + + if ( $collection instanceof Entities\Collection ) { + return $collection->user_can( 'edit_metadata' ); + } + + } else { + + return current_user_can( 'tnc_rep_edit_metadata' ); + + } + + return false; + + } + + /** + * @param mixed $item + * @param \WP_REST_Request $request + * + * @return array|\WP_Error|\WP_REST_Response + */ + public function prepare_item_for_response( $item, $request ) { + if(!empty($item)){ + $item_arr = $item->_toArray(); + $item_arr['metadata_type_object'] = $item->get_metadata_type_object()->_toArray(); + + if ( isset($request['include_options_as_html']) && $request['include_options_as_html'] == 'yes' ) + $item_arr['options_as_html'] = $item->get_metadata_type_object()->get_options_as_html(); + + if ( isset($item_arr['metadata_type_options']) && isset($item_arr['metadata_type_options']['taxonomy_id']) ) { + $taxonomy = Repositories\Taxonomies::get_instance()->get_db_identifier_by_id( $item_arr['metadata_type_options']['taxonomy_id'] ); + //$taxonomy = new Entities\Taxonomy($item_arr['metadata_type_options']['taxonomy_id']); + //$item_arr['metadata_type_options']['taxonomy'] = $taxonomy->get_db_identifier(); + $item_arr['metadata_type_options']['taxonomy'] = $taxonomy; + } + + if ($request['context'] === 'edit') { + $item_arr['current_user_can_edit'] = $item->can_edit(); + $item_arr['current_user_can_delete'] = $item->can_delete(); + ob_start(); + $item->get_metadata_type_object()->form(); + $form = ob_get_clean(); + $item_arr['edit_form'] = $form; + $item_arr['enabled'] = $item->get_enabled_for_collection(); + + if(isset($item_arr['metadata_type_options']) && isset($item_arr['metadata_type_options']['children_objects'])) { + foreach ($item_arr['metadata_type_options']['children_objects'] as $index => $children) { + $item_arr['metadata_type_options']['children_objects'][$index]['current_user_can_edit'] = $item->can_edit(); + $item_arr['metadata_type_options']['children_objects'][$index]['current_user_can_delete'] = $item->can_delete(); + } + } + } + + /** + * Use this filter to add additional post_meta to the api response + * Use the $request object to get the context of the request and other variables + * For example, id context is edit, you may want to add your meta or not. + * + * Also take care to do any permissions verification before exposing the data + */ + $extra_metadata = apply_filters('tainacan-api-response-metadatum-meta', [], $request); + + foreach ($extra_metadata as $extra_meta) { + $item_arr[$extra_meta] = get_post_meta($item_arr['id'], $extra_meta, true); + } + $item_arr['inherited'] = $item_arr['collection_id'] != $request['collection_id']; + + return $item_arr; + } + + return $item; + } + + /** + * @param \WP_REST_Request $request + * + * @return \WP_Error|\WP_REST_Response + * @throws \Exception + */ + public function get_items( $request ) { + if(isset($request['collection_id'])) { + $collection_id = $request['collection_id']; + + $args = $this->prepare_filters( $request ); + + if ($request['include_disabled'] === 'true') { + $args['include_disabled'] = true; + } + + if ($request['include_control_metadata_types'] === 'true') { + $args['include_control_metadata_types'] = true; + } + + $collection = new Entities\Collection( $collection_id ); + + $result = $this->metadatum_repository->fetch_by_collection( $collection, $args ); + } else { + $args = [ + 'meta_query' => [ + [ + 'key' => 'collection_id', + 'value' => 'default', + 'compare' => '=' + ] + ] + ]; + + if ($request['include_control_metadata_types'] === 'true') { + $args['include_control_metadata_types'] = true; + } + + $result = $this->metadatum_repository->fetch( $args, 'OBJECT' ); + } + + $prepared_item = []; + foreach ( $result as $item ) { + $prepared_item[] = $this->prepare_item_for_response( $item, $request ); + } + + return new \WP_REST_Response($prepared_item, 200); + } + + /** + * @param \WP_REST_Request $request + * + * @return bool|\WP_Error + * @throws \Exception + */ + public function get_items_permissions_check( $request ) { + + + if(!isset($request['collection_id'])) { + return true; + } + + $collection = $this->collection_repository->fetch($request['collection_id']); + + if($collection instanceof Entities\Collection){ + if ( ! $collection->can_read() ) { + return false; + } + + return true; + } + + return false; + + } + + /** + * @param \WP_REST_Request $request + * + * @return \WP_Error|\WP_REST_Response + */ + public function delete_item( $request ) { + $metadatum_id = $request['metadatum_id']; + + $metadatum = $this->metadatum_repository->fetch($metadatum_id); + + if (! $metadatum instanceof Entities\Metadatum) { + return new \WP_REST_Response([ + 'error_message' => __('Metadata with this ID was not found', 'tainacan'), + 'item_id' => $item_id + ], 400); + } + + $metadatum_trashed = $this->metadatum_repository->trash($metadatum); + + $prepared = $this->prepare_item_for_response($metadatum_trashed, $request); + + return new \WP_REST_Response($prepared, 200); + } + + /** + * @param \WP_REST_Request $request + * + * @return bool|\WP_Error + * @throws \Exception + */ + public function delete_item_permissions_check( $request ) { + $metadatum = $this->metadatum_repository->fetch($request['metadatum_id']); + + if ($metadatum instanceof Entities\Metadatum) { + return $metadatum->can_delete(); + } + + return false; + + } + + /** + * @param \WP_REST_Request $request + * + * @return \WP_Error|\WP_REST_Response + */ + public function update_item( $request ) { + $collection_id = is_numeric($request['collection_id']) ? $request['collection_id'] : null; + $body = json_decode($request->get_body(), true); + + if(!empty($body)){ + $attributes = []; + + $metadatum_id = $request['metadatum_id']; + $confirm_repository = false; + foreach ($body as $att => $value){ + if ($att === "repository_level" && $value === "yes") { + $confirm_repository = true; + continue; + } + $attributes[$att] = $value; + } + + $metadatum = $this->metadatum_repository->fetch($metadatum_id); + + $error_message = __('Metadata with this ID was not found', 'tainacan'); + + if ($metadatum) { + // These conditions are for verify if endpoints are used correctly + if(!$collection_id && $metadatum->get_collection_id() !== 'default') { + $error_message = __('This metadata is not a default metadata', 'tainacan'); + + return new \WP_REST_Response( [ + 'error_message' => $error_message, + 'metadatum_id' => $metadatum_id + ] ); + } elseif ($collection_id && $metadatum->get_collection_id() === 'default'){ + $error_message = __('This metadata is not a collection metadata', 'tainacan'); + + return new \WP_REST_Response( [ + 'error_message' => $error_message, + 'metadatum_id' => $metadatum_id + ] ); + } + + if (isset($request['repository_level']) && $confirm_repository) { + $attributes['collection_id'] = "default"; + } + + $prepared_metadata = $this->prepare_item_for_updating($metadatum, $attributes); + + if($prepared_metadata->validate()){ + $updated_metadata = $this->metadatum_repository->update($prepared_metadata); + + $response = $this->prepare_item_for_response($updated_metadata, $request); + + return new \WP_REST_Response($response, 200); + } + + return new \WP_REST_Response([ + 'error_message' => __('One or more values are invalid.', 'tainacan'), + 'errors' => $prepared_metadata->get_errors(), + 'metadatum' => $this->prepare_item_for_response($prepared_metadata, $request) + ], 400); + } + + return new \WP_REST_Response( [ + 'error_message' => $error_message, + 'metadatum_id' => $metadatum_id + ] ); + } + + return new \WP_REST_Response([ + 'error_message' => __('The body could not be empty', 'tainacan'), + 'body' => $body + ], 400); + } + + /** + * @param \WP_REST_Request $request + * + * @return bool|\WP_Error + * @throws \Exception + */ + public function update_item_permissions_check( $request ) { + $metadatum = $this->metadatum_repository->fetch($request['metadatum_id']); + + if ($metadatum instanceof Entities\Metadatum) { + return $metadatum->can_edit(); + } + + return false; + } + + /** + * @param null $object_name + * + * @return array|void + */ + public function get_wp_query_params() { + $query_params['context']['default'] = 'view'; + + $query_params = array_merge($query_params, parent::get_wp_query_params()); + + $query_params['name'] = array( + 'description' => __('Limits the result set to metadata with a specific name'), + 'type' => 'string', + ); + + $query_params = array_merge($query_params, parent::get_meta_queries_params()); + + return $query_params; + } + + /** + * @param null $method + * + * @return array + * @throws \Exception + */ + public function get_endpoint_args_for_item_schema( $method = null ) { + $endpoint_args = []; + if($method === \WP_REST_Server::READABLE) { + $endpoint_args = array_merge( + $endpoint_args, + parent::get_wp_query_params() + ); + } elseif ($method === \WP_REST_Server::CREATABLE || $method === \WP_REST_Server::EDITABLE) { + $map = $this->metadatum_repository->get_map(); + + foreach ($map as $mapped => $value){ + $set_ = 'set_'. $mapped; + + // Show only args that has a method set + if( !method_exists(new Entities\Metadatum(), "$set_") ){ + unset($map[$mapped]); + } + } + + $endpoint_args = $map; + } + + return $endpoint_args; + } + + function get_schema() { + $schema = [ + '$schema' => 'http://json-schema.org/draft-04/schema#', + 'title' => 'metadatum', + 'type' => 'object' + ]; + + $main_schema = parent::get_repository_schema( $this->metadatum_repository ); + $permissions_schema = parent::get_permissions_schema(); + + // $item_metadata_scheme = parent::get_repository_schema( $this->item_metadata_repository ); + // $item_scheme = parent::get_repository_schema( $this->item_repository ); + // $collection_scheme = parent::get_repository_schema( $this->collection_repository ); + + $schema['properties'] = array_merge( + parent::get_base_properties_schema(), + $main_schema, + $permissions_schema + // $item_metadata_scheme, + // $item_scheme, + // $collection_scheme + ); + + return $schema; + } +} + +?> diff --git a/src/classes/api/tainacan-rest-creator.php b/src/classes/api/tainacan-rest-creator.php index adb894efb..e7c301fec 100644 --- a/src/classes/api/tainacan-rest-creator.php +++ b/src/classes/api/tainacan-rest-creator.php @@ -22,6 +22,7 @@ $rest_oaipmh_expose_controller = new \Tainacan\API\EndPoints\REST_Oaipmh_ $rest_item_metadata_controller = new \Tainacan\API\EndPoints\REST_Item_Metadata_Controller(); $rest_sequence_edit_controller = new \Tainacan\API\EndPoints\REST_Sequence_Edit_Controller(); $rest_metadata_types_controller = new \Tainacan\API\EndPoints\REST_Metadata_Types_Controller(); +$rest_metadata_section_controller = new \Tainacan\API\EndPoints\REST_Metadata_Section_Controller(); $rest_metadatum_mappers_controller = new \Tainacan\API\EndPoints\REST_Metadatum_Mappers_Controller(); $rest_background_processes_controller = new \Tainacan\API\EndPoints\REST_Background_Processes_Controller(); // Add here other endpoints imports diff --git a/src/classes/entities/class-tainacan-metadatum-section.php b/src/classes/entities/class-tainacan-metadatum-section.php new file mode 100644 index 000000000..ed860d6d0 --- /dev/null +++ b/src/classes/entities/class-tainacan-metadatum-section.php @@ -0,0 +1,114 @@ +get_name(), $this); + } + + /** + * Return the metadatum name + * + * @return string + */ + function get_name() { + return $this->get_mapped_property('name'); + } + + /** + * Get metadatum slug + * + * @return string + */ + function get_slug() { + return $this->get_mapped_property('slug'); + } + + /** + * Return the metadatum description + * + * @return string + */ + function get_description() { + return $this->get_mapped_property('description'); + } + + /** + * Set the metadatum name + * + * @param [string] $value + * @return void + */ + function set_name($value) { + $this->set_mapped_property('name', $value); + } + + /** + * Set the metadatum section slug + * + * If you dont set the metadatum slug, it will be set automatically based on the name and + * following WordPress default behavior of creating slugs for posts. + * + * If you set the slug for an existing one, WordPress will append a number at the end of in order + * to make it unique (e.g slug-1, slug-2) + * + * @param [string] $value + * @return void + */ + function set_slug($value) { + $this->set_mapped_property('slug', $value); + } + + /** + * Set metadatum description + * + * @param [string] $value The text description + * @return void + */ + function set_description($value) { + $this->set_mapped_property('description', $value); + } + + /** + * {@inheritdoc } + * + * Also validates the metadatum, calling the validate_options callback of the Metadatum Type + * + * @return bool valid or not + * @throws \Exception + */ + public function validate() { + $this->add_error($this->get_id(), __("Error", 'tainacan')); + return false; + } +} diff --git a/src/classes/repositories/class-tainacan-metadata-section.php b/src/classes/repositories/class-tainacan-metadata-section.php new file mode 100644 index 000000000..68be3deaf --- /dev/null +++ b/src/classes/repositories/class-tainacan-metadata-section.php @@ -0,0 +1,288 @@ +get_name(), [ + 'name' => [ + 'map' => 'post_title', + 'title' => __( 'Name', 'tainacan' ), + 'type' => 'string', + 'description' => __( 'Name of the metadata section', 'tainacan' ), + 'on_error' => __( 'The name should be a text value and not empty', 'tainacan' ), + 'validation' => v::stringType()->notEmpty(), + ], + 'slug' => [ + 'map' => 'post_name', + 'title' => __( 'Slug', 'tainacan' ), + 'type' => 'string', + 'description' => __( 'A unique and sanitized string representation of the metadata sction', 'tainacan' ), + ], + 'description' => [ + 'map' => 'post_content', + 'title' => __( 'Description', 'tainacan' ), + 'type' => 'string', + 'description' => __( 'The metadatum section description.', 'tainacan' ), + 'default' => '', + ], + 'collection_id' => [ + 'map' => 'meta', + 'title' => __( 'Collection', 'tainacan' ), + 'type' => ['integer', 'string'], + 'description' => __( 'The collection ID', 'tainacan' ), + ] + ] ); + } + + /** + * Get the labels for the custom post type of this repository + * + * @return array Labels in the format expected by register_post_type() + */ + public function get_cpt_labels() { + return array( + 'name' => __( 'Metadata Section', 'tainacan' ), + 'singular_name' => __( 'Metadata Section', 'tainacan' ), + 'add_new' => __( 'Add new', 'tainacan' ), + 'add_new_item' => __( 'Add new Metadata Section', 'tainacan' ), + 'edit_item' => __( 'Edit Metadata Section', 'tainacan' ), + 'new_item' => __( 'New Metadata Section', 'tainacan' ), + 'view_item' => __( 'View Metadata Section', 'tainacan' ), + 'search_items' => __( 'Search Metadata Section', 'tainacan' ), + 'not_found' => __( 'No Metadata Section found ', 'tainacan' ), + 'not_found_in_trash' => __( 'No Metadata Section found in trash', 'tainacan' ), + 'parent_item_colon' => __( 'Parent Metadata Section:', 'tainacan' ), + 'menu_name' => __( 'Metadata Section', 'tainacan' ) + ); + } + + public function register_post_type() { + $labels = $this->get_cpt_labels(); + $args = array( + 'labels' => $labels, + 'hierarchical' => true, + 'public' => true, + 'show_ui' => tnc_enable_dev_wp_interface(), + 'show_in_menu' => tnc_enable_dev_wp_interface(), + 'publicly_queryable' => true, + 'exclude_from_search' => true, + 'has_archive' => false, + 'query_var' => true, + 'can_export' => true, + 'rewrite' => true, + 'map_meta_cap' => true, + 'show_in_nav_menus' => false, + 'capabilities' => (array) $this->get_capabilities(), + 'supports' => [ + 'title', + 'editor', + 'page-attributes' + ] + ); + register_post_type( Entities\Metadatum_Section::get_post_type(), $args ); + } + + /** + * fetch metadatum section based on ID or WP_Query args + * + * metadatum section are stored as posts. Check WP_Query docs + * to learn all args accepted in the $args parameter (@see https://developer.wordpress.org/reference/classes/wp_query/) + * You can also use a mapped property, such as name and description, as an argument and it will be mapped to the + * appropriate WP_Query argument + * + * If a number is passed to $args, it will return a \Tainacan\Entities\Metadatum_Section object. But if the post is not found or + * does not match the entity post type, it will return an empty array + * + * @param array $args WP_Query args || int $args the metadatum section id + * @param string $output The desired output format (@see \Tainacan\Repositories\Repository::fetch_output() for possible values) + * + * @return Entities\Metadatum_Section|\WP_Query|Array an instance of wp query OR array of entities; + * @throws \Exception + */ + public function fetch( $args, $output = null ) { + + if ( is_numeric( $args ) ) { + $existing_post = get_post( $args ); + if ( $existing_post instanceof \WP_Post ) { + try { + return new Entities\Metadatum_Section( $existing_post ); + } catch (\Exception $e) { + return []; + } + } else { + return []; + } + } elseif ( is_array( $args ) ) { + $args = array_merge( [ + 'posts_per_page' => - 1, + ], $args ); + + $args = $this->parse_fetch_args( $args ); + $args['post_type'] = Entities\Metadatum_Section::get_post_type(); + $args = apply_filters( 'tainacan_fetch_args', $args, 'metadata-section' ); + + $wp_query = new \WP_Query( $args ); + + return $this->fetch_output( $wp_query, $output ); + } + } + + /** + * fetch metadata sections IDs based on WP_Query args + * + * to learn all args accepted in the $args parameter (@see https://developer.wordpress.org/reference/classes/wp_query/) + * You can also use a mapped property, such as name and description, as an argument and it will be mapped to the + * appropriate WP_Query argument + * + * @param array $args WP_Query args || int $args the item id + * + * @return Array array of IDs; + * @throws \Exception + */ + public function fetch_ids( $args = [] ) { + + $args['fields'] = 'ids'; + + return $this->fetch( $args )->get_posts(); + } + + /** + * fetch metadatum section by collection + * + * @param Entities\Collection $collection + * @param array $args WP_Query args + * + * @return array Entities\Metadatum_Section + * @throws \Exception + */ + public function fetch_by_collection( Entities\Collection $collection, $args = [] ) { + $collection_id = $collection->get_id(); + + //get parent collections + $parents = get_post_ancestors( $collection_id ); + + //insert the actual collection + if ( is_numeric($collection_id) ) { + $parents[] = $collection_id; + } + + $results = []; + + $args = array_merge( [ + 'parent' => 0 + ], $args ); + + $original_meta_q = isset( $args['meta_query'] ) ? $args['meta_query'] : []; + + /** + * Since we introduced roles & capabalities management, we cannot rely + * on WordPress behavior when handling default post status values. + * WordPress checks if the current user can read_priva_posts, but this is + * not enough for us. We have to handle this ourselves to mimic WordPress behavior + * considering how tainacan manages metadata capabilities + */ + if ( ! isset($args['post_status']) ) { + + foreach ( $parents as $parent_id ) { + + // Add public states. + $statuses = get_post_stati( array( 'public' => true ) ); + + $read_private_cap = $this->get_default_metadata_attribute() == $parent_id ? 'tnc_rep_read_private_metadata_section' : 'tnc_col_' . $parent_id . '_read_private_metadata_section'; + if ( current_user_can($read_private_cap) ) { + $statuses = array_merge( $statuses, get_post_stati( array( 'private' => true ) ) ); + } + + $args['post_status'] = $statuses; + + $meta_query = array( + 'key' => 'collection_id', + 'value' => $parent_id, + ); + + $args['meta_query'] = $original_meta_q; + $args['meta_query'][] = $meta_query; + + $results = array_merge($results, $this->fetch( $args, 'OBJECT' )); + } + + } else { + $meta_query = array( + 'key' => 'collection_id', + 'value' => $parents, + 'compare' => 'IN', + ); + $args['meta_query'] = $original_meta_q; + $args['meta_query'][] = $meta_query; + $results = $this->fetch( $args, 'OBJECT' ); + } + + return $results; + // return $this->order_result( + // $results, + // $collection, + // isset( $args['include_disabled'] ) ? $args['include_disabled'] : false + // ); + } + + /** + * @param \Tainacan\Entities\Metadatum_Section $metadatum_section + * + * @return \Tainacan\Entities\Metadatum_Section + * {@inheritDoc} + * @see \Tainacan\Repositories\Repository::insert() + */ + public function insert( $metadatum_section ) { + $new_metadatum_section = parent::insert( $metadatum_section ); + return $new_metadatum_section; + } + + /** + * @param \Tainacan\Entities\Metadatum_Section $object + * @param $new_values + * + * @return mixed|string|Entities\Entity + * @throws \Exception + */ + public function update( $object, $new_values = null ) { + return $this->insert( $object ); + } + + /** + * @inheritDoc + */ + public function delete( Entities\Entity $entity, $permanent = true ) { + //test if not exist a metadata using this section + return parent::delete($entity, $permanent); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 26935e2d2..32d902b02 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -6,7 +6,8 @@ */ $bootstrap_cfg = require('bootstrap-config.php'); -$_tests_dir = getenv( 'WP_TESTS_DIR' ); +// $_tests_dir = getenv( 'WP_TESTS_DIR' ); +$_tests_dir = '/tainacan_test/wordpress-tests-lib'; if ( ! $_tests_dir ) { $_tests_dir = $bootstrap_cfg['tests_dir']; }