From 379f8c5f040f5d4c06f6158e3c1e4bb435c29ac2 Mon Sep 17 00:00:00 2001 From: Leo Germani Date: Thu, 5 Jul 2018 12:57:31 -0300 Subject: [PATCH] Buk edit API endpoints #69 --- ...lass-tainacan-rest-bulkedit-controller.php | 292 ++++++++++++++++++ src/api/tainacan-rest-creator.php | 1 + src/classes/class-tainacan-bulk-edit.php | 44 ++- tests/test-bulkedit.php | 124 +++++++- 4 files changed, 433 insertions(+), 28 deletions(-) create mode 100644 src/api/endpoints/class-tainacan-rest-bulkedit-controller.php diff --git a/src/api/endpoints/class-tainacan-rest-bulkedit-controller.php b/src/api/endpoints/class-tainacan-rest-bulkedit-controller.php new file mode 100644 index 000000000..c4521f887 --- /dev/null +++ b/src/api/endpoints/class-tainacan-rest-bulkedit-controller.php @@ -0,0 +1,292 @@ +rest_base = 'bulk-edit'; + parent::__construct(); + add_action('init', array(&$this, 'init_objects'), 11); + } + + public function init_objects() { + $this->metadatum_repository = Repositories\Metadata::get_instance(); + $this->collections_repository = Repositories\Collections::get_instance(); + } + + + /** + * + * + * @throws \Exception + */ + public function register_routes() { + register_rest_route($this->namespace, '/collection/(?P[\d]+)/' . $this->rest_base, + array( + array( + 'methods' => \WP_REST_Server::CREATABLE, + 'callback' => array($this, 'create_item'), + 'permission_callback' => array($this, 'bulk_edit_permissions_check'), + 'args' => $this->get_create_params() + ), + ) + ); + register_rest_route($this->namespace, '/collection/(?P[\d]+)/' . $this->rest_base . '/(?P[0-9a-f]+)/add', + array( + array( + 'methods' => \WP_REST_Server::CREATABLE, + 'callback' => array($this, 'add_value'), + 'permission_callback' => array($this, 'bulk_edit_permissions_check'), + 'args' => [ + 'metadatum_id' => [ + 'type' => 'integer', + 'description' => __( 'The metadatum ID', 'tainacan' ), + ], + 'value' => [ + 'type' => 'string', + 'description' => __( 'The value to be added', 'tainacan' ), + ], + ], + ), + ) + ); + register_rest_route($this->namespace, '/collection/(?P[\d]+)/' . $this->rest_base . '/(?P[0-9a-f]+)/set', + array( + array( + 'methods' => \WP_REST_Server::CREATABLE, + 'callback' => array($this, 'set_value'), + 'permission_callback' => array($this, 'bulk_edit_permissions_check'), + 'args' => [ + 'metadatum_id' => [ + 'type' => 'integer', + 'description' => __( 'The metadatum ID', 'tainacan' ), + ], + 'value' => [ + 'type' => 'string', + 'description' => __( 'The value to be added', 'tainacan' ), + ], + ], + ), + ) + ); + register_rest_route($this->namespace, '/collection/(?P[\d]+)/' . $this->rest_base . '/(?P[0-9a-f]+)/remove', + array( + array( + 'methods' => \WP_REST_Server::CREATABLE, + 'callback' => array($this, 'remove_value'), + 'permission_callback' => array($this, 'bulk_edit_permissions_check'), + 'args' => [ + 'metadatum_id' => [ + 'type' => 'integer', + 'description' => __( 'The metadatum ID', 'tainacan' ), + ], + 'value' => [ + 'type' => 'string', + 'description' => __( 'The value to be added', 'tainacan' ), + ], + ], + ), + ) + ); + register_rest_route($this->namespace, '/collection/(?P[\d]+)/' . $this->rest_base . '/(?P[0-9a-f]+)/replace', + array( + array( + 'methods' => \WP_REST_Server::CREATABLE, + 'callback' => array($this, 'add_value'), + 'permission_callback' => array($this, 'bulk_edit_permissions_check'), + 'args' => [ + 'metadatum_id' => [ + 'type' => 'integer', + 'description' => __( 'The metadatum ID', 'tainacan' ), + ], + 'old_value' => [ + 'type' => 'string', + 'description' => __( 'The value to search for', 'tainacan' ), + ], + 'new_value' => [ + 'type' => 'string', + 'description' => __( 'The value to be set', 'tainacan' ), + ], + ], + ), + ) + ); + + } + + + public function bulk_edit_permissions_check($request) { + $collection = $this->collections_repository->fetch($request['collection_id']); + + if ($collection instanceof Entities\Collection) { + return current_user_can($collection->get_items_capabilities()->edit_others_posts); + } + + return false; + } + + + public function create_item($request) { + $body = json_decode($request->get_body(), true); + + $args = []; + + if (isset($body['items_ids']) && is_array($body['items_ids']) && !empty($body['items_ids'])) { + $args['items_ids'] = $body['items_ids']; + } elseif ( isset($body['use_query']) && $body['use_query'] ) { + + unset($request['paged']); + unset($request['offset']); + unset($request['perpage']); + $request['nopaging'] = 1; + + $query_args = $this->prepare_filters($request); + + $collection_id = $request['collection_id']; + + $args = [ + 'query' => $query_args, + 'collection_id' => $collection_id + ]; + + } else { + return new \WP_REST_Response([ + 'error_message' => __('You mus specify items_ids OR use_query', 'tainacan'), + ], 400); + } + + $bulk = new \Tainacan\Bulk_Edit($args); + + $response = [ + 'id' => $bulk->get_id() + ]; + + $rest_response = new \WP_REST_Response($response, 200); + + $rest_response->header('X-WP-Total', $bulk->count_posts()); + + return $rest_response; + + } + + public function add_value($request) { + + return $this->generic_action('add_value', $request); + + } + public function set_value($request) { + + return $this->generic_action('set_value', $request); + + } + public function remove_value($request) { + + return $this->generic_action('remove_value', $request); + + } + public function replace_value($request) { + + return $this->generic_action('replace_value', $request, ['old_value', 'new_value']); + + } + + + private function generic_action($method, $request, $keys = ['value']) { + $body = json_decode($request->get_body(), true); + + if(empty($body)){ + return new \WP_REST_Response([ + 'error_message' => __('Body can not be empty.', 'tainacan'), + ], 400); + } + + if(!isset($body['metadatum_id'])){ + return new \WP_REST_Response([ + 'error_message' => __('You must specify a Metadatum ID.', 'tainacan'), + ], 400); + } + + foreach ($keys as $key) { + if(!isset($body[$key])){ + return new \WP_REST_Response([ + 'error_message' => sprintf(__('%s must be provided', 'tainacan'), $key), + ], 400); + } + } + + $group_id = $request['group_id']; + var_dump($group_id); + + $args = ['id' => $group_id]; + + $bulk = new \Tainacan\Bulk_Edit($args); + + $metadatum = $this->metadatum_repository->fetch($body['metadatum_id']); + + if ( $metadatum instanceof Entities\Metadatum ) { + + $value = isset($body['new_value']) ? $body['new_value'] : $body['value']; + $old_value = isset($body['old_value']) ? $body['old_value'] : null; + + $action = $bulk->$method($metadatum, $value, $old_value); + + if ( is_wp_error($action) ) { + return new \WP_REST_Response([ + 'error_message' => $action->get_error_message(), + ], 400); + } else { + return new \WP_REST_Response($action, 200); + } + + + } else { + return new \WP_REST_Response([ + 'error_message' => __('Metadatum not found.', 'tainacan'), + ], 400); + } + } + + + + /** + * @param null $object_name + * + * @return array|void + */ + public function get_create_params($object_name = null) { + $query_params['context']['default'] = 'view'; + + array_merge($query_params, parent::get_collection_params('item')); + + $query_params['title'] = array( + 'description' => __('Limits the result set to items with a specific title'), + 'type' => 'string', + ); + + $query_params['items_ids'] = [ + 'type' => 'array', + 'items' => [ + 'type' => 'integer' + ], + 'description' => __( 'Array of items IDs', 'tainacan' ), + ]; + + $query_params['use_query'] = [ + 'type' => 'bool', + 'description' => __( 'Whether to use the current query to select posts', 'tainacan' ), + ]; + + $query_params = array_merge($query_params, parent::get_meta_queries_params()); + + return $query_params; + } + +} + +?> \ No newline at end of file diff --git a/src/api/tainacan-rest-creator.php b/src/api/tainacan-rest-creator.php index eb125f732..bff9a8c7c 100644 --- a/src/api/tainacan-rest-creator.php +++ b/src/api/tainacan-rest-creator.php @@ -15,6 +15,7 @@ $rest_metadata_types_controller = new \Tainacan\API\EndPoints\REST_Metadata_Type $rest_filter_types_controller = new \Tainacan\API\EndPoints\REST_Filter_Types_Controller(); $rest_importers_controller = new \Tainacan\API\EndPoints\REST_Importers_Controller(); $rest_background_processes_controller = new \Tainacan\API\EndPoints\REST_Background_Processes_Controller(); +$rest_bulkedit_controller = new \Tainacan\API\EndPoints\REST_Bulkedit_Controller(); new \Tainacan\API\EndPoints\REST_Export_Controller(); new \Tainacan\API\EndPoints\REST_Metadatum_Mappers_Controller(); // Add here other endpoints imports diff --git a/src/classes/class-tainacan-bulk-edit.php b/src/classes/class-tainacan-bulk-edit.php index 2ac089c53..fb1d485f8 100644 --- a/src/classes/class-tainacan-bulk-edit.php +++ b/src/classes/class-tainacan-bulk-edit.php @@ -60,7 +60,7 @@ class Bulk_Edit { if (isset($params['query']) && is_array($params['query'])) { - if (!isset($params['collection_id']) || !is_integer($params['collection_id'])) { + if (!isset($params['collection_id']) || !is_numeric($params['collection_id'])) { throw new \Exception('Collection ID must be informed when creating a group via query'); } @@ -150,15 +150,15 @@ class Bulk_Edit { public function add_value(Entities\Metadatum $metadatum, $value) { if (!$this->get_id()) { - return false; + return new \WP_Error( 'no_id', __( 'Bulk Edit group not initialized', 'tainacan' ) ); } // Specific validation if (!$metadatum->is_multiple()) { - return ['error' => __('Unable to add a value to a metadata if it does not accept multiple values', 'tainacan')]; + return new \WP_Error( 'invalid_action', __( 'Unable to add a value to a metadata if it does not accept multiple values', 'tainacan' ) ); } if ($metadatum->is_collection_key()) { - return ['error' => __('Unable to add a value to a metadata set to be a collection key', 'tainacan')]; + return new \WP_Error( 'invalid_action', __( 'Unable to add a value to a metadata set to be a collection key', 'tainacan' ) ); } $dummyItem = new Entities\Item(); @@ -168,7 +168,7 @@ class Bulk_Edit { if ($checkItemMetadata->validate()) { return $this->_add_value($metadatum, $value); } else { - return ['error' => __('Invalid value', 'tainacan')]; + return new \WP_Error( 'invalid_value', __( 'Invalid Value', 'tainacan' ) ); } @@ -183,13 +183,13 @@ class Bulk_Edit { public function set_value(Entities\Metadatum $metadatum, $value) { if (!$this->get_id()) { - return false; + return new \WP_Error( 'no_id', __( 'Bulk Edit group not initialized', 'tainacan' ) ); } // Specific validation if ($metadatum->is_collection_key()) { - return ['error' => __('Unable to set a value to a metadata set to be a collection key', 'tainacan')]; + return new \WP_Error( 'invalid_action', __( 'Unable to set a value to a metadata set to be a collection key', 'tainacan' ) ); } $dummyItem = new Entities\Item(); @@ -200,7 +200,7 @@ class Bulk_Edit { $this->_remove_values($metadatum); return $this->_add_value($metadatum, $value); } else { - return ['error' => __('Invalid value', 'tainacan')]; + return new \WP_Error( 'invalid_value', __( 'Invalid Value', 'tainacan' ) ); } @@ -215,16 +215,16 @@ class Bulk_Edit { public function remove_value(Entities\Metadatum $metadatum, $value) { if (!$this->get_id()) { - return false; + return new \WP_Error( 'no_id', __( 'Bulk Edit group not initialized', 'tainacan' ) ); } // Specific validation if ($metadatum->is_required()) { - return ['error' => __('Unable to remove a value from a required metadatum', 'tainacan')]; + return new \WP_Error( 'invalid_action', __( 'Unable to remove a value from a required metadatum', 'tainacan' ) ); } if (!$metadatum->is_multiple()) { - return ['error' => __('Unable to remove a value from a metadata if it does not accept multiple values', 'tainacan')]; + return new \WP_Error( 'invalid_action', __( 'Unable to remove a value from a metadata if it does not accept multiple values', 'tainacan' ) ); } return $this->_remove_value($metadatum, $value); @@ -235,16 +235,16 @@ class Bulk_Edit { /** * Relplaces a value from one metadata with another value in all items in current group */ - public function replace_value(Entities\Metadatum $metadatum, $old_value, $new_value) { + public function replace_value(Entities\Metadatum $metadatum, $new_value, $old_value) { if (!$this->get_id()) { - return false; + return new \WP_Error( 'no_id', __( 'Bulk Edit group not initialized', 'tainacan' ) ); } // Specific validation if ($metadatum->is_collection_key()) { - return ['error' => __('Unable to set a value to a metadata set to be a collection key', 'tainacan')]; + return new \WP_Error( 'invalid_action', __( 'Unable to set a value to a metadata set to be a collection key', 'tainacan' ) ); } $dummyItem = new Entities\Item(); @@ -255,7 +255,7 @@ class Bulk_Edit { $this->_remove_value($metadatum, $old_value); return $this->_add_value($metadatum, $new_value); } else { - return ['error' => __('Invalid value', 'tainacan')]; + return new \WP_Error( 'invalid_value', __( 'Invalid Value', 'tainacan' ) ); } @@ -285,8 +285,8 @@ class Bulk_Edit { $term = wp_insert_term($value, $tax->get_db_identifier()); } - if (is_wp_error($term) || !isset($term['term_taxonomy_id'])) { - return false; + if (is_\WP_Error($term) || !isset($term['term_taxonomy_id'])) { + return new \WP_Error( 'error', __( 'Error adding term', 'tainacan' ) ); } $insert_q = $this->_build_select( $wpdb->prepare("post_id, %d", $term['term_taxonomy_id']) ); @@ -327,8 +327,6 @@ class Bulk_Edit { } - return false; - } /** @@ -354,8 +352,8 @@ class Bulk_Edit { return 0; } - if (is_wp_error($term) || !isset($term['term_taxonomy_id'])) { - return false; + if (is_\WP_Error($term) || !isset($term['term_taxonomy_id'])) { + return new \WP_Error( 'error', __( 'Term not found', 'tainacan' ) ); } $delete_q = $this->_build_select( "post_id" ); @@ -380,8 +378,6 @@ class Bulk_Edit { } - return false; - } /** @@ -425,8 +421,6 @@ class Bulk_Edit { } - return false; - } diff --git a/tests/test-bulkedit.php b/tests/test-bulkedit.php index dc4dd7e6e..3ff8b9a8d 100644 --- a/tests/test-bulkedit.php +++ b/tests/test-bulkedit.php @@ -13,7 +13,7 @@ use Tainacan\Entities; /** * Sample test case. */ -class BulkEdit extends TAINACAN_UnitTestCase { +class BulkEdit extends TAINACAN_UnitApiTestCase { public $items_ids = []; @@ -105,6 +105,8 @@ class BulkEdit extends TAINACAN_UnitTestCase { $this->tainacan_item_metadata_factory->create_item_metadata($item, $category, ['good', 'bad']); } + + $this->api_baseroute = $this->namespace . '/collection/' . $collection->get_id() . '/bulk-edit'; } @@ -382,7 +384,7 @@ class BulkEdit extends TAINACAN_UnitTestCase { ]); - $bulk->replace_value($this->category, 'good', 'awesome'); + $bulk->replace_value($this->category, 'awesome', 'good'); $items = $Tainacan_Items->fetch([ @@ -445,7 +447,7 @@ class BulkEdit extends TAINACAN_UnitTestCase { ]); - $bulk->replace_value($this->metadatum, 'even', 'super'); + $bulk->replace_value($this->metadatum, 'super', 'even'); $items = $Tainacan_Items->fetch([ @@ -724,6 +726,122 @@ class BulkEdit extends TAINACAN_UnitTestCase { } + /** + * @group api + */ + function test_api_create_by_items_ids() { + + $ids = array_slice($this->items_ids, 2, 17); + + $request = new \WP_REST_Request( + 'POST', $this->api_baseroute + ); + + $request->set_body( json_encode(['items_ids' => $ids]) ); + + $response = $this->server->dispatch($request); + + $this->assertEquals(200, $response->get_status()); + + $data = $response->get_data(); + + $this->assertTrue(is_string($data['id'])); + + $this->assertEquals(17, $response->headers['X-WP-Total']); + + + } + + /** + * @group api + */ + function test_api_create_by_query() { + + $query = [ + + 'metaquery' => [ + [ + 'key' => $this->metadatum->get_id(), + 'value' => 'odd' + ] + ], + 'taxquery' => [ + [ + 'taxonomy' => $this->taxonomy->get_db_identifier(), + 'field' => 'name', + 'terms' => 'good' + ] + ], + 'perpage' => 4, + 'paged' => 2 + + ]; + + + + $request = new \WP_REST_Request( + 'POST', $this->api_baseroute + ); + + $request->set_query_params($query); + + $request->set_body( json_encode(['use_query' => 1]) ); + + $response = $this->server->dispatch($request); + + $this->assertEquals(200, $response->get_status()); + + $data = $response->get_data(); + + $this->assertTrue(is_string($data['id'])); + + $this->assertEquals(20, $response->headers['X-WP-Total']); + + + } + + /** + * @group api + */ + public function test_api_add_action() { + + $Tainacan_Items = \Tainacan\Repositories\Items::get_instance(); + + $ids = array_slice($this->items_ids, 2, 14); + + $bulk = new \Tainacan\Bulk_Edit([ + 'items_ids' => $ids, + ]); + + $body = json_encode([ + 'metadatum_id' => $this->multiple_meta->get_id(), + 'value' => 'superduper' + ]); + + + $request = new \WP_REST_Request( + 'POST', $this->api_baseroute . '/' . $bulk->get_id() . '/add' + ); + + $request->set_body( $body ); + + $response = $this->server->dispatch($request); + + $items = $Tainacan_Items->fetch([ + 'meta_query' => [ + [ + 'key' => $this->multiple_meta->get_id(), + 'value' => 'superduper' + ] + ], + 'posts_per_page' => -1 + ]); + + $this->assertEquals(14, $items->found_posts); + + + } + } \ No newline at end of file