From 005d69d0dd058657dbd52ccdeac4b0a524a828e7 Mon Sep 17 00:00:00 2001 From: vnmedeiros Date: Fri, 29 Apr 2022 11:38:03 -0300 Subject: [PATCH] feat: add metadata section order --- ...s-tainacan-rest-collections-controller.php | 115 ++++++++++- ...acan-rest-metadata-sections-controller.php | 8 +- .../entities/class-tainacan-collection.php | 45 +++- .../class-tainacan-metadata-section.php | 18 +- .../class-tainacan-collections.php | 8 + .../class-tainacan-metadata-sections.php | 56 ++++- .../repositories/class-tainacan-metadata.php | 4 +- tests/test-collections.php | 194 +++++++++--------- 8 files changed, 332 insertions(+), 116 deletions(-) diff --git a/src/classes/api/endpoints/class-tainacan-rest-collections-controller.php b/src/classes/api/endpoints/class-tainacan-rest-collections-controller.php index b8db21919..ee2a951cd 100644 --- a/src/classes/api/endpoints/class-tainacan-rest-collections-controller.php +++ b/src/classes/api/endpoints/class-tainacan-rest-collections-controller.php @@ -81,14 +81,29 @@ class REST_Collections_Controller extends REST_Controller { ), 'schema' => [$this, 'get_schema'], )); - register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P[\d]+)/metadata_order', array( + register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P[\d]+)/metadata_section_order', array( + array( + 'methods' => \WP_REST_Server::EDITABLE, + 'callback' => array($this, 'update_metadata_section_order'), + 'permission_callback' => array($this, 'update_metadata_section_order_permissions_check'), + 'args' => [ + 'metadata_section_order' => [ + 'description' => __( 'The order of the metadata section in the collection, an array of objects with integer ID and bool enabled.', 'tainacan' ), + 'required' => true, + 'validate_callback' => [$this, 'validate_metadata_section_order'] + ] + ], + ), + 'schema' => [$this, 'get_schema'], + )); + register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P[\d]+)/metadata_section/(?P[\d]+)/metadata_order', array( array( 'methods' => \WP_REST_Server::EDITABLE, 'callback' => array($this, 'update_metadata_order'), 'permission_callback' => array($this, 'update_metadata_order_permissions_check'), 'args' => [ 'metadata_order' => [ - 'description' => __( 'The order of the metadata in the collection, an array of objects with integer ID and bool enabled.', 'tainacan' ), + 'description' => __( 'The order of the metadata in the section, an array of objects with integer ID and bool enabled.', 'tainacan' ), 'required' => true, 'validate_callback' => [$this, 'validate_filters_metadata_order'] ] @@ -586,6 +601,27 @@ class REST_Collections_Controller extends REST_Controller { } + public function validate_metadata_section_order($value, $request, $param) { + if ( is_array($value) ) { + foreach ($value as $val) { + if ( !is_array($val) ) { + return false; + } + if ( !isset($val['id']) || !is_numeric($val['id'])) { + return false; + } + if ( !isset($val['enabled']) || !is_bool($val['enabled']) ) { + return false; + } + if ( !isset($val['metadata_order']) || !is_array($val['metadata_order']) ) { + return false; + } + } + return true; + } + return false; + } + /** * Update a collection metadata order * @@ -595,6 +631,7 @@ class REST_Collections_Controller extends REST_Controller { */ public function update_metadata_order( $request ) { $collection_id = $request['collection_id']; + $metadata_section_id = $request['metadata_section_id']; $body = json_decode($request->get_body(), true); @@ -603,7 +640,60 @@ class REST_Collections_Controller extends REST_Controller { $collection = $this->collections_repository->fetch($collection_id); if( $collection instanceof Entities\Collection) { - $collection->set_metadata_order( $body['metadata_order'] ); + $metadata_section_order = $collection->get_metadata_section_order(); + foreach($metadata_section_order['metadata_section_order'] as $section) { + if ($section['id'] == $metadata_section_id) { + $section['metadata_order'] = $body['metadata_order']; + break; + } + } + $collection->set_metadata_section_order( $metadata_section_order ); + + if ( $collection->validate() ) { + $updated_collection = $this->collections_repository->update( $collection ); + + $response = $this->prepare_item_for_response($updated_collection, $request); + + return new \WP_REST_Response( $response, 200 ); + } + + return new \WP_REST_Response([ + 'error_message' => __('One or more values are invalid.', 'tainacan'), + 'errors' => $collection->get_errors(), + 'collection' => $this->prepare_item_for_response($collection, $request) + ], 400); + } + + return new \WP_REST_Response([ + 'error_message' => __('Collection with this ID was not found', 'tainacan' ), + 'collection_id' => $collection_id + ], 400); + } + + return new \WP_REST_Response([ + 'error_message' => __('The body could not be empty', 'tainacan'), + 'body' => $body + ], 400); + } + + /** + * Update a collection metadata section order + * + * @param \WP_REST_Request $request + * + * @return string|\WP_Error|\WP_REST_Response + */ + public function update_metadata_section_order( $request ) { + $collection_id = $request['collection_id']; + + $body = json_decode($request->get_body(), true); + + if( !empty($body) && isset($body['metadata_section_order']) ) { + + $collection = $this->collections_repository->fetch($collection_id); + + if( $collection instanceof Entities\Collection) { + $collection->set_metadata_section_order( $body['metadata_section_order'] ); if ( $collection->validate() ) { $updated_collection = $this->collections_repository->update( $collection ); @@ -651,6 +741,25 @@ class REST_Collections_Controller extends REST_Controller { return false; } + /** + * Verify if current user has permission to update metadata section order + * + * @param \WP_REST_Request $request + * + * @return bool|\WP_Error + * @throws \Exception + */ + public function update_metadata_section_order_permissions_check( $request ) { + $collection = $this->collections_repository->fetch($request['collection_id']); + + if($collection instanceof Entities\Collection) { + return $collection->user_can( 'edit_metadata' ); // && $collection->user_can( 'edit_metadata_section' ); + } + + return false; + } + + /** * Update a collection metadata order * diff --git a/src/classes/api/endpoints/class-tainacan-rest-metadata-sections-controller.php b/src/classes/api/endpoints/class-tainacan-rest-metadata-sections-controller.php index e573d0cc5..2e7aa6814 100644 --- a/src/classes/api/endpoints/class-tainacan-rest-metadata-sections-controller.php +++ b/src/classes/api/endpoints/class-tainacan-rest-metadata-sections-controller.php @@ -449,14 +449,14 @@ class REST_Metadata_Sections_Controller extends REST_Controller { ], 400); } - public function add_metadatum( $request ) { + public function add_metadata( $request ) { if( !empty($request->get_body()) && isset($request['metadata_section_id']) ){ $body = json_decode($request->get_body(), true); $metadata_section_id = $request['metadata_section_id']; $metadata_list = $body['metadata_list']; try { - $metadata_section = $this->metadata_sections_repository->add_metadatum($metadata_section_id, $metadata_list); + $metadata_section = $this->metadata_sections_repository->add_metadata($metadata_section_id, $metadata_list); if($metadata_section == false) { return new \WP_REST_Response([ 'error_message' => __('One or more values are invalid.', 'tainacan'), @@ -475,14 +475,14 @@ class REST_Metadata_Sections_Controller extends REST_Controller { ], 400); } - public function delete_metadatum( $request ) { + public function delete_metadata( $request ) { if( !empty($request->get_body()) && isset($request['metadata_section_id']) ){ $body = json_decode($request->get_body(), true); $metadata_section_id = $request['metadata_section_id']; $metadata_list = $body['metadata_list']; try { - $metadata_section = $this->metadata_sections_repository->delete_metadatum($metadata_section_id, $metadata_list); + $metadata_section = $this->metadata_sections_repository->delete_metadata($metadata_section_id, $metadata_list); if($metadata_section == false) { return new \WP_REST_Response([ 'error_message' => __('One or more values are invalid.', 'tainacan'), diff --git a/src/classes/entities/class-tainacan-collection.php b/src/classes/entities/class-tainacan-collection.php index 9c103ecfe..535892885 100644 --- a/src/classes/entities/class-tainacan-collection.php +++ b/src/classes/entities/class-tainacan-collection.php @@ -28,6 +28,7 @@ class Collection extends Entity { $default_view_mode, $enabled_view_modes, $metadata_order, + $metadata_section_order, $filters_order, $enable_cover_page, $cover_page_id, @@ -405,12 +406,21 @@ class Collection extends Entity { /** * Get collection metadata ordination * - * @return string + * @return Object | string */ function get_metadata_order() { return $this->get_mapped_property( 'metadata_order' ); } + /** + * Get collection metadata section ordination + * + * @return Array | Object | string + */ + function get_metadata_section_order() { + return $this->get_mapped_property( 'metadata_section_order' ); + } + /** * Get enable cover page attribute * @@ -721,6 +731,25 @@ class Collection extends Entity { $this->set_mapped_property( 'metadata_order', $value ); } + /** + * Set collection metadata section ordination + * + * @param [string] $value + * + * @return void + */ + function set_metadata_section_order( $value ) { + if ( isset($value['metadata_section_order']) ) { + $metadata_section_order = $value['metadata_section_order']; + $metadata_order = array('metadata_order' => array( ) ); + foreach($metadata_section_order as $section) { + $metadata_order['metadata_order'] = $section['metadata_order']; + } + $this->set_metadata_order($metadata_order); + } + $this->set_mapped_property( 'metadata_section_order', $value ); + } + /** * Set collection filters ordination * @@ -857,6 +886,20 @@ class Collection extends Entity { return false; } + $metadata_section_order = $this->get_metadata_section_order(); + if ( isset($metadata_section_order['metadata_section_order']) ) { + $section_order = $metadata_section_order['metadata_section_order']; + $metadata_order = $this->get_metadata_order(); + $order_general = array(); + foreach($section_order as $section) { + $order_general = array_merge($order_general, $section['metadata_order']); + } + + if( count($order_general) != count($metadata_order) ) { + return false; + } + } + return parent::validate(); } diff --git a/src/classes/entities/class-tainacan-metadata-section.php b/src/classes/entities/class-tainacan-metadata-section.php index ced054e9f..76639540b 100644 --- a/src/classes/entities/class-tainacan-metadata-section.php +++ b/src/classes/entities/class-tainacan-metadata-section.php @@ -24,7 +24,9 @@ class Metadata_Section extends Entity { * @var string */ protected $repository = 'Metadata_Sections'; - + + public $enabled_for_collection = true; + public function __toString() { return apply_filters("tainacan-metadata-section-to-string", $this->get_name(), $this); } @@ -112,6 +114,20 @@ class Metadata_Section extends Entity { $this->set_mapped_property('metadata_list', array_unique($value)); } + /** + * Transient property used to store the status of the metadatum section for a particular collection + * + * Used by the API to tell front end when a metadatum section is disabled + * + */ + public function get_enabled_for_collection() { + return $this->enabled_for_collection; + } + public function set_enabled_for_collection($value) { + $this->enabled_for_collection = $value; + } + + /** * {@inheritdoc } * diff --git a/src/classes/repositories/class-tainacan-collections.php b/src/classes/repositories/class-tainacan-collections.php index fad050a4a..edb3c559d 100644 --- a/src/classes/repositories/class-tainacan-collections.php +++ b/src/classes/repositories/class-tainacan-collections.php @@ -131,6 +131,13 @@ class Collections extends Repository { 'items' => [ 'type' => 'string' ], //'validation' => v::stringType(), ], + 'metadata_section_order' => [ + 'map' => 'meta', + 'title' => __( 'Metadata order', 'tainacan' ), + 'type' => ['array', 'object', 'string'], + 'items' => [ 'type' => ['array', 'string', 'integer', 'object'] ], + 'description' => __( 'The order of the metadata section in the collection', 'tainacan' ), + ], 'metadata_order' => [ 'map' => 'meta', 'title' => __( 'Metadata order', 'tainacan' ), @@ -429,6 +436,7 @@ class Collections extends Repository { function handle_parent_order_clone( &$collection ) { if ($collection instanceof Entities\Collection && $collection->get_parent() != 0) { $parent_collection = $this->fetch( $collection->get_parent() ); + $collection->set_metadata_section_order($parent_collection->get_metadata_section_order()); $collection->set_metadata_order($parent_collection->get_metadata_order()); $collection->set_filters_order($parent_collection->get_filters_order()); diff --git a/src/classes/repositories/class-tainacan-metadata-sections.php b/src/classes/repositories/class-tainacan-metadata-sections.php index 73d8ae29c..79c33d60b 100644 --- a/src/classes/repositories/class-tainacan-metadata-sections.php +++ b/src/classes/repositories/class-tainacan-metadata-sections.php @@ -263,12 +263,11 @@ class Metadata_Sections extends Repository { $results = $this->fetch( $args, 'OBJECT' ); } - return $results; - // return $this->order_result( - // $results, - // $collection, - // isset( $args['include_disabled'] ) ? $args['include_disabled'] : false - // ); + return $this->order_result( + $results, + $collection, + isset( $args['include_disabled'] ) ? $args['include_disabled'] : false + ); } /** @@ -294,7 +293,7 @@ class Metadata_Sections extends Repository { return $this->insert( $object ); } - public function add_metadatum($metadata_section_id, $metadata_list) { + public function add_metadata($metadata_section_id, $metadata_list) { $metadata_section = $this->fetch($metadata_section_id); if ($metadata_section) { $list = $metadata_section->get_metadata_list(); @@ -308,7 +307,7 @@ class Metadata_Sections extends Repository { return false; } - public function delete_metadatum($metadata_section_id, $metadata_list) { + public function delete_metadata($metadata_section_id, $metadata_list) { $metadata_section = $this->fetch($metadata_section_id); if ($metadata_section) { $list = $metadata_section->get_metadata_list(); @@ -338,4 +337,45 @@ class Metadata_Sections extends Repository { //test if not exist a metadata using this section return parent::delete($entity, $permanent); } + + public function order_result( $result, Entities\Collection $collection, $include_disabled = false ) { + $order = $collection->get_metadata_section_order(); + + if ( $order ) { + $order = ( is_array( $order ) ) ? $order : unserialize( $order ); + + if ( is_array( $result ) ) { + $result_ordinate = []; + $not_ordinate = []; + + foreach ( $result as $item ) { + $id = $item->WP_Post->ID; + $index = array_search( $id, array_column( $order, 'id' ) ); + + if ( $index !== false ) { + + // skipping metadata disabled if the arg is set + if ( ! $include_disabled && isset( $order[ $index ]['enabled'] ) && ! $order[ $index ]['enabled'] ) { + continue; + } + + $enable = ( isset( $order[ $index ]['enabled'] ) ) ? $order[ $index ]['enabled'] : true; + $item->set_enabled_for_collection( $enable ); + + $result_ordinate[ $index ] = $item; + } else { + $not_ordinate[] = $item; + } + } + + ksort( $result_ordinate ); + $result_ordinate = array_merge( $result_ordinate, $not_ordinate ); + + return $result_ordinate; + } + + } + + return $result; + } } diff --git a/src/classes/repositories/class-tainacan-metadata.php b/src/classes/repositories/class-tainacan-metadata.php index 9b3a8f580..63b5eb145 100644 --- a/src/classes/repositories/class-tainacan-metadata.php +++ b/src/classes/repositories/class-tainacan-metadata.php @@ -1727,9 +1727,9 @@ class Metadata extends Repository { public function update_metadata_section( Entities\Metadatum $metadatum, $remove = false ) { $metadata_section_repository = Metadata_Sections::get_instance(); if (!$remove) { - $metadata_section_repository->add_metadatum($metadatum->get_metadata_section_id(), [$metadatum->get_id()]); + $metadata_section_repository->add_metadata($metadatum->get_metadata_section_id(), [$metadatum->get_id()]); } else { - $metadata_section_repository->delete_metadatum($metadatum->get_metadata_section_id(), [$metadatum->get_id()]); + $metadata_section_repository->delete_metadata($metadatum->get_metadata_section_id(), [$metadatum->get_id()]); } } diff --git a/tests/test-collections.php b/tests/test-collections.php index 75b1c495d..d4817f672 100644 --- a/tests/test-collections.php +++ b/tests/test-collections.php @@ -95,168 +95,168 @@ class Collections extends TAINACAN_UnitTestCase { true ); - $Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance(); + $Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance(); - $this->assertEquals('Tainacan\Entities\Collection', get_class($x)); + $this->assertEquals('Tainacan\Entities\Collection', get_class($x)); - $test = $Tainacan_Collections->fetch($x->get_id()); + $test = $Tainacan_Collections->fetch($x->get_id()); - $this->assertEquals('teste', $test->get_name()); - $this->assertEquals('adasdasdsa', $test->get_description()); - $this->assertEquals('DESC', $test->get_default_order()); - $this->assertEquals('draft', $test->get_status()); - } + $this->assertEquals('teste', $test->get_name()); + $this->assertEquals('adasdasdsa', $test->get_description()); + $this->assertEquals('DESC', $test->get_default_order()); + $this->assertEquals('draft', $test->get_status()); + } - function test_unique_slugs() { + function test_unique_slugs() { $x = $this->tainacan_entity_factory->create_entity( 'collection', array( 'name' => 'teste', 'description' => 'adasdasdsa', 'default_order' => 'DESC', - 'slug' => 'duplicated_slug', - 'status' => 'publish' + 'slug' => 'duplicated_slug', + 'status' => 'publish' ), true ); - $y = $this->tainacan_entity_factory->create_entity( + $y = $this->tainacan_entity_factory->create_entity( 'collection', array( 'name' => 'teste', 'description' => 'adasdasdsa', 'default_order' => 'DESC', - 'slug' => 'duplicated_slug', - 'status' => 'publish' + 'slug' => 'duplicated_slug', + 'status' => 'publish' ), true ); - $this->assertNotEquals($x->get_slug(), $y->get_slug()); + $this->assertNotEquals($x->get_slug(), $y->get_slug()); - // Create as draft and publish later - $x = $this->tainacan_entity_factory->create_entity( + // Create as draft and publish later + $x = $this->tainacan_entity_factory->create_entity( 'collection', array( 'name' => 'teste', 'description' => 'adasdasdsa', 'default_order' => 'DESC', - 'slug' => 'duplicated_slug', + 'slug' => 'duplicated_slug', ), true ); - $y = $this->tainacan_entity_factory->create_entity( + $y = $this->tainacan_entity_factory->create_entity( 'collection', array( 'name' => 'teste', 'description' => 'adasdasdsa', 'default_order' => 'DESC', - 'slug' => 'duplicated_slug', + 'slug' => 'duplicated_slug', ), true ); - $this->assertEquals($x->get_slug(), $y->get_slug()); + $this->assertEquals($x->get_slug(), $y->get_slug()); - $Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance(); - $x->set_status('publish'); - $x->validate(); - $x = $Tainacan_Collections->insert($x); - $y->set_status('private'); // or publish shoud behave the same - $y->validate(); - $y = $Tainacan_Collections->insert($y); + $Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance(); + $x->set_status('publish'); + $x->validate(); + $x = $Tainacan_Collections->insert($x); + $y->set_status('private'); // or publish shoud behave the same + $y->validate(); + $y = $Tainacan_Collections->insert($y); - $this->assertNotEquals($x->get_slug(), $y->get_slug()); + $this->assertNotEquals($x->get_slug(), $y->get_slug()); - } + } - function test_item() { - $x = $this->tainacan_entity_factory->create_entity( - 'collection', - array( - 'name' => 'teste', - 'description' => 'adasdasdsa', - 'default_order' => 'DESC' - ), - true - ); + function test_item() { + $x = $this->tainacan_entity_factory->create_entity( + 'collection', + array( + 'name' => 'teste', + 'description' => 'adasdasdsa', + 'default_order' => 'DESC' + ), + true + ); - $Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance(); - $collection = $Tainacan_Collections->fetch($x->get_id()); + $Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance(); + $collection = $Tainacan_Collections->fetch($x->get_id()); - $i = $this->tainacan_entity_factory->create_entity( - 'item', - array( - 'title' => 'item test', - 'description' => 'adasdasdsa', - 'order' => 'DESC', - 'collection' => $collection - ), - true - ); + $i = $this->tainacan_entity_factory->create_entity( + 'item', + array( + 'title' => 'item test', + 'description' => 'adasdasdsa', + 'order' => 'DESC', + 'collection' => $collection + ), + true + ); - $Tainacan_Items = \Tainacan\Repositories\Items::get_instance(); - $item = $Tainacan_Items->fetch( $i->get_id() ); + $Tainacan_Items = \Tainacan\Repositories\Items::get_instance(); + $item = $Tainacan_Items->fetch( $i->get_id() ); - $this->assertEquals($item->get_title(), 'item test'); - $this->assertEquals($item->get_description(), 'adasdasdsa'); - $this->assertEquals($item->get_collection_id(), $collection->get_id()); + $this->assertEquals($item->get_title(), 'item test'); + $this->assertEquals($item->get_description(), 'adasdasdsa'); + $this->assertEquals($item->get_collection_id(), $collection->get_id()); - } + } - function test_validation() { - $x = $this->tainacan_entity_factory->create_entity( - 'collection', - array( - 'name' => 'teste', - 'description' => 'adasdasdsa', - 'default_order' => 13, - 'status' => 'publish' - ) - ); + function test_validation() { + $x = $this->tainacan_entity_factory->create_entity( + 'collection', + array( + 'name' => 'teste', + 'description' => 'adasdasdsa', + 'default_order' => 13, + 'status' => 'publish' + ) + ); - $this->assertFalse($x->validate()); - $this->assertTrue(sizeof($x->get_errors()) > 0); + $this->assertFalse($x->validate()); + $this->assertTrue(sizeof($x->get_errors()) > 0); - $x->set_default_order('ASDASD'); + $x->set_default_order('ASDASD'); - $this->assertFalse($x->validate()); - $this->assertTrue(sizeof($x->get_errors()) > 0); + $this->assertFalse($x->validate()); + $this->assertTrue(sizeof($x->get_errors()) > 0); - $x->set_default_order('DESC'); - $this->assertTrue($x->validate()); - $this->assertTrue(empty($x->get_errors())); - } + $x->set_default_order('DESC'); + $this->assertTrue($x->validate()); + $this->assertTrue(empty($x->get_errors())); + } - function test_hooks() { - $Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance(); - $this->assertTrue(has_action('init', array($Tainacan_Collections, 'register_post_type')) !== false, 'Collections Init is not registred!'); - } + function test_hooks() { + $Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance(); + $this->assertTrue(has_action('init', array($Tainacan_Collections, 'register_post_type')) !== false, 'Collections Init is not registred!'); + } function test_create_child_collection() { $x = $this->tainacan_entity_factory->create_entity( - 'collection', - array( - 'name' => 'test', - 'description' => 'adasdasdsa', - 'default_order' => 'DESC', - ), - true - ); + 'collection', + array( + 'name' => 'test', + 'description' => 'adasdasdsa', + 'default_order' => 'DESC', + ), + true + ); $col = $this->tainacan_entity_factory->create_entity( - 'collection', - array( - 'name' => 'test', - 'description' => 'adasdasdsa', - 'default_order' => 'DESC', + 'collection', + array( + 'name' => 'test', + 'description' => 'adasdasdsa', + 'default_order' => 'DESC', 'status' => 'auto-draft' - ), - true - ); + ), + true + ); $Collections = \Tainacan\Repositories\Collections::get_instance();