API, Docs and Tests config:

setup-local.md updated;
Collections Controller updated;
Items Controller implementation initiated;
Map in Collections updated;
PHPDoc in Collections Controller; and
other things.
This commit is contained in:
weryques 2017-11-30 14:00:43 -02:00
parent 8bbc602774
commit cd498f48a6
8 changed files with 258 additions and 64 deletions

View File

@ -8,7 +8,7 @@ This is the development repository for the Tainacan WordPress plugin.
Overview of folders: Overview of folders:
* `docs` - This tecnhinal documentation * `docs` - This technical documentation
* `tests` - phpunit tests * `tests` - phpunit tests
* `src` - The actual plugin. Everything outside this folder is not part of the distribution package * `src` - The actual plugin. Everything outside this folder is not part of the distribution package
@ -54,7 +54,7 @@ When we want to build the plugin, we run `build.sh` that basically compiles all
In order to use it, make a copy of `build-config-sample.sh` and name it only `build-config.sh`. Edit it and set the folder in which you want the build to be made. In order to use it, make a copy of `build-config-sample.sh` and name it only `build-config.sh`. Edit it and set the folder in which you want the build to be made.
If you are running a local enviroment, you might want to check `build-watch.sh`. This script will watch your development folder for changes and automatically build the plugin so you dont have to do it manually every time you modify a file. If you are running a local environment, you might want to check `build-watch.sh`. This script will watch your development folder for changes and automatically build the plugin so you don't have to do it manually every time you modify a file.
## Tests ## Tests
@ -80,10 +80,11 @@ The parameters are:
* `wordpress-tests-lib` - As the name says, the WordPress Tests Library * `wordpress-tests-lib` - As the name says, the WordPress Tests Library
Inside `tests` folder, edit the file called `bootstrap-config-sample.php` and inform the folder where you installed your WordPress Test Library. This will be `/path/to/wordpress-test-folder/wodpress-tests-lib`. Save the file as `bootstrap-config.php`. Inside `tests` folder, edit the file called `bootstrap-config-sample.php` and inform the folder where you installed your WordPress Test Library. This will be `/path/to/wordpress-test-folder/wodpress-tests-lib`. Save the file as `bootstrap-config.php`.
If necessary, you can edit the `tests_url` with your configuration.
### Setting up API tests (work in progress) ### Setting up API tests (work in progress)
Go to the `wordpress-test-lib` directory located in your test directory, open the file `wordpress-tests-config.php` and edit the value of `WP_TESTS_DOMAIN` contant to the web address pointing to your `wordpress-test` folder located inside the WordPress Test Directory. For example: Go to the `wordpress-test-lib` directory located in your test directory, open the file `wordpress-tests-config.php` and edit the value of `WP_TESTS_DOMAIN` constant to the web address pointing to your `wordpress-test` folder located inside the WordPress Test Directory. For example:
``` ```
define( 'WP_TESTS_DOMAIN', 'localhost/wordpress-test-folder/wordpress-test/' ); define( 'WP_TESTS_DOMAIN', 'localhost/wordpress-test-folder/wordpress-test/' );
@ -91,11 +92,11 @@ define( 'WP_TESTS_DOMAIN', 'localhost/wordpress-test-folder/wordpress-test/' );
Go to `wordpress-test` directory. Make a copy of the `wp-config-sample.php` to `wp-config.php`, open that new file and add the MySQL settings, which you informed on installation script. (tip: copy and paste it from `wordpress-tests-lib/wp-tests-config.php`). Go to `wordpress-test` directory. Make a copy of the `wp-config-sample.php` to `wp-config.php`, open that new file and add the MySQL settings, which you informed on installation script. (tip: copy and paste it from `wordpress-tests-lib/wp-tests-config.php`).
Now go to the URL of the wordpress installation test (example: localhost/wordpress-test) and make the wordpress common installation. Now go to the URL of the wordpress installation test (example: localhost/wordpress-test-folder/wordpress-test) and make the wordpress common installation (Obs: Don't forget to activate the permalinks).
Execute the build script, go to Wordpress plugins page and active Tainacan plugin. Execute the build script, go to Wordpress plugins page and active Tainacan plugin.
Obs: Don't forget, the URL used in API tests should be the same in constant `WP_TESTS_DOMAIN`, of course, with the prefix `http://` (like http://localhost/wordpress-test/). Important: to use the URL of your wordpress test installation in new API tests, you should be use the `TAINACAN_TESTS_URL` constant.
You are done! Now, to run your tests, simply go to the root directory of the repository and type: You are done! Now, to run your tests, simply go to the root directory of the repository and type:

View File

@ -3,10 +3,19 @@
use Tainacan\Repositories; use Tainacan\Repositories;
use Tainacan\Entities; use Tainacan\Entities;
/**
* Class that represents the Collections REST Controller
*
* @uses Entities\Collection and Repositories\Collections
* */
class TAINACAN_REST_Collections_Controller extends WP_REST_Controller { class TAINACAN_REST_Collections_Controller extends WP_REST_Controller {
private $collections_repository; private $collections_repository;
private $collection; private $collection;
/**
* TAINACAN_REST_Collections_Controller constructor.
* Define the namespace, rest base and instantiate your attributes.
*/
public function __construct(){ public function __construct(){
$this->namespace = 'tainacan/v2'; $this->namespace = 'tainacan/v2';
$this->rest_base = 'collections'; $this->rest_base = 'collections';
@ -16,26 +25,28 @@ class TAINACAN_REST_Collections_Controller extends WP_REST_Controller {
add_action('rest_api_init', array($this, 'register_routes')); add_action('rest_api_init', array($this, 'register_routes'));
} }
/**
* Register the collections route and their endpoints
*/
public function register_routes(){ public function register_routes(){
register_rest_route($this->namespace, '/' . $this->rest_base, array( register_rest_route($this->namespace, '/' . $this->rest_base, array(
array( array(
'methods' => WP_REST_Server::READABLE, 'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_items'), 'callback' => array($this, 'get_items'),
'permission_callback' => array($this, 'get_items_permissions_check'), 'permission_callback' => array($this, 'get_items_permissions_check'),
'args' => $this->get_collection_params(),
), ),
array( array(
'methods' => WP_REST_Server::CREATABLE, 'methods' => WP_REST_Server::CREATABLE,
'callback' => array($this, 'create_item'), 'callback' => array($this, 'create_item'),
'permission_callback' => array($this, 'create_item_permissions_check'), //'permission_callback' => array($this, 'create_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::CREATABLE), 'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::CREATABLE),
), ),
'schema' => array($this, 'get_public_item_schema'),
)); ));
register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array( register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P<collection_id>[\d]+)', array(
array( array(
'methods' => WP_REST_Server::READABLE, 'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_item'), 'callback' => array($this, 'get_item'),
'args' => $this->get_collection_params(),
'permission_callback' => array($this, 'get_item_permissions_check'), 'permission_callback' => array($this, 'get_item_permissions_check'),
), ),
array( array(
@ -51,6 +62,13 @@ class TAINACAN_REST_Collections_Controller extends WP_REST_Controller {
)); ));
} }
/**
* Return a array of Collections objects in JSON
*
* @param WP_REST_Request $request
*
* @return WP_Error|WP_REST_Response
*/
public function get_items($request){ public function get_items($request){
$collections = $this->collections_repository->fetch(); $collections = $this->collections_repository->fetch();
@ -59,8 +77,15 @@ class TAINACAN_REST_Collections_Controller extends WP_REST_Controller {
return new WP_REST_Response($response, 200); return new WP_REST_Response($response, 200);
} }
/**
* Return a Collection object in JSON
*
* @param WP_REST_Request $request
*
* @return WP_Error|WP_REST_Response
*/
public function get_item($request){ public function get_item($request){
$collection_id = $request['id']; $collection_id = $request['collection_id'];
$collection = $this->collections_repository->fetch($collection_id); $collection = $this->collections_repository->fetch($collection_id);
$response = $this->prepare_item_for_response($collection, $request); $response = $this->prepare_item_for_response($collection, $request);
@ -68,12 +93,27 @@ class TAINACAN_REST_Collections_Controller extends WP_REST_Controller {
return new WP_REST_Response($response, 200); return new WP_REST_Response($response, 200);
} }
/**
*
* Receive a WP_Query or a Collection object and return both in JSON
*
* @param mixed $item
* @param WP_REST_Request $request
*
* @return mixed|string|void|WP_Error|WP_REST_Response
*/
public function prepare_item_for_response($item, $request){ public function prepare_item_for_response($item, $request){
if(is_array($item)){ if($item instanceof WP_Query){
$collections_as_json = []; $collections_as_json = [];
foreach ($item as $wp_post){
array_push($collections_as_json, $wp_post->__toJSON()); if ($item->have_posts()) {
while ( $item->have_posts() ) {
$item->the_post();
$collection = new Entities\Collection($item->post);
array_push($collections_as_json, $collection->__toJSON());
}
wp_reset_postdata();
} }
return json_encode($collections_as_json); return json_encode($collections_as_json);
@ -83,22 +123,40 @@ class TAINACAN_REST_Collections_Controller extends WP_REST_Controller {
} }
} }
public function get_item_schema(){ /**
*
} * @param WP_REST_Request $request
*
* @return bool|WP_Error
*/
public function get_items_permissions_check($request){ public function get_items_permissions_check($request){
return true; return true;
} }
/**
*
* @param WP_REST_Request $request
*
* @return bool|WP_Error
*/
public function get_item_permissions_check($request){ public function get_item_permissions_check($request){
return true; return true;
} }
/**
* Receive a JSON with the structure of a Collection and return, in case of success insert
* a Collection object in JSON
*
* @param WP_REST_Request $request
*
* @return array|WP_Error|WP_REST_Response
*/
public function create_item( $request ) { public function create_item( $request ) {
$request = json_decode($request->get_body(), true); $request = json_decode($request->get_body(), true);
if (!empty($request['id'])){ if(empty($request)) {
return new WP_Error('rest_empty', __('Empty request.'), array('status' => 204));
} elseif (!empty($request['collection_id'])){
return new WP_Error( 'rest_post_exists', __( 'Cannot create existing post.' ), array( 'status' => 400 ) ); return new WP_Error( 'rest_post_exists', __( 'Cannot create existing post.' ), array( 'status' => 400 ) );
} }
@ -107,18 +165,34 @@ class TAINACAN_REST_Collections_Controller extends WP_REST_Controller {
if($prepared_post->validate()) { if($prepared_post->validate()) {
$collection = $this->collections_repository->insert( $prepared_post ); $collection = $this->collections_repository->insert( $prepared_post );
return new WP_REST_Response($collection->__toJSON(), 200); return new WP_REST_Response($collection->__toJSON(), 201);
} }
return $prepared_post->get_errors(); return new WP_REST_Response($prepared_post->get_errors(), 400);
} }
/**
* Verify if current has permission to create a item
*
* @param WP_REST_Request $request
*
* @return bool|WP_Error
*/
public function create_item_permissions_check( $request ) { public function create_item_permissions_check( $request ) {
//if(current_user_can('edit_posts')){ if(current_user_can('edit_posts')){
return true; return true;
//}
} }
return false;
}
/**
* Prepare collection for insertion on database
*
* @param WP_REST_Request $request
*
* @return object|Entities\Collection|WP_Error
*/
public function prepare_item_for_database( $request ) { public function prepare_item_for_database( $request ) {
$this->collection->set_name($request['name']); $this->collection->set_name($request['name']);
$this->collection->set_description($request['description']); $this->collection->set_description($request['description']);
@ -126,28 +200,60 @@ class TAINACAN_REST_Collections_Controller extends WP_REST_Controller {
return $this->collection; return $this->collection;
} }
/**
* Delete a collection
*
* @param WP_REST_Request $request
*
* @return string|WP_Error|WP_REST_Response
*/
public function delete_item( $request ) { public function delete_item( $request ) {
return parent::delete_item( $request ); // TODO: Change the autogenerated stub $collection_id = $request['collection_id'];
$this->collections_repository->delete($collection_id);
return 'Não implementado';
} }
/**
* Verify if current user has permission to delete a collection
*
* @param WP_REST_Request $request
*
* @return bool|WP_Error
*/
public function delete_item_permissions_check( $request ) { public function delete_item_permissions_check( $request ) {
if(current_user_can('delete_posts')){ if(current_user_can('delete_posts')){
return true; return true;
} }
return false;
} }
/**
* Update a collection
*
* @param WP_REST_Request $request
*
* @return string|WP_Error|WP_REST_Response
*/
public function update_item( $request ) { public function update_item( $request ) {
return parent::update_item( $request ); // TODO: Change the autogenerated stub return 'Não implementado';
} }
/**
* Verify if current user has permission to update a item
*
* @param WP_REST_Request $request
*
* @return bool|WP_Error
*/
public function update_item_permissions_check( $request ) { public function update_item_permissions_check( $request ) {
if(current_user_can('edit_posts')){ if(current_user_can('edit_posts')){
return true; return true;
} }
}
public function get_public_item_schema() { return false;
return parent::get_public_item_schema(); // TODO: Change the autogenerated stub
} }
public function get_collection_params() { public function get_collection_params() {
@ -157,7 +263,14 @@ class TAINACAN_REST_Collections_Controller extends WP_REST_Controller {
} }
public function get_endpoint_args_for_item_schema( $method = WP_REST_Server::CREATABLE ) { public function get_endpoint_args_for_item_schema( $method = WP_REST_Server::CREATABLE ) {
return parent::get_endpoint_args_for_item_schema( $method ); // TODO: Change the autogenerated stub $args = [
'Object' => [
'type' => 'JSON',
'description' => 'A Collection object'
]
];
return apply_filters("rest_{$this->collection->get_post_type()}_collection_params", $args, $this->collection->get_post_type());
} }
} }

View File

@ -1,11 +1,77 @@
<?php <?php
use Tainacan\Repositories; use Tainacan\Repositories;
use Tainacan\Entities;
class TAINACAN_REST_Items_Controller extends WP_REST_Controller { class TAINACAN_REST_Items_Controller extends WP_REST_Controller {
private $items_repository;
private $item;
public function __construct() {
$this->namespace = 'tainacan/v2';
$this->rest_base = 'items';
$this->items_repository = new Repositories\Items();
$this->item = new Entities\Item();
add_action('rest_api_init', array($this, 'register_routes'));
}
public function register_routes() {
register_rest_route(
$this->namespace,
'/' . $this->rest_base . '/collection/(?P<collection_id>[\d]+)',
array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_items'),
//'permission_callback' => array($this, 'get_items_permissions_check'),
'args' => $this->get_collection_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' => array($this, 'get_public_item_schema'),
));
register_rest_route(
$this->namespace,
'/' . $this->rest_base . '/collection/(?P<collection_id>[\d]+)/(?P<item_id>[\d]+)',
array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_item'),
'permission_callback' => array($this, 'get_item_permissions_check'),
),
array(
'methods' => WP_REST_Server::EDITABLE,
'callback' => array($this, 'update_item'),
'permission_callback' => array($this, 'update_item_permissions_check'),
),
array(
'methods' => WP_REST_Server::DELETABLE,
'callback' => array($this, 'delete_item'),
'permission_callback' => array($this, 'delete_item_permissions_check'),
),
));
}
public function get_items( $request ) {
return parent::get_items( $request ); // TODO: Change the autogenerated stub
}
public function get_item_permissions_check( $request ) {
return parent::get_item_permissions_check( $request ); // TODO: Change the autogenerated stub
}
public function create_item( $request ) {
return parent::create_item( $request ); // TODO: Change the autogenerated stub
}
public function create_item_permissions_check( $request ) {
return parent::create_item_permissions_check( $request ); // TODO: Change the autogenerated stub
}
} }
?> ?>

View File

@ -5,6 +5,10 @@ const ENDPOINTS_DIR = __DIR__ . '/endpoints/';
require_once(ENDPOINTS_DIR . 'class-tainacan-rest-collections-controller.php'); require_once(ENDPOINTS_DIR . 'class-tainacan-rest-collections-controller.php');
$rest_collections_controller = new TAINACAN_REST_Collections_Controller(); $rest_collections_controller = new TAINACAN_REST_Collections_Controller();
require_once(ENDPOINTS_DIR . 'class-tainacan-rest-items-controller.php');
$rest_items_controller = new TAINACAN_REST_Items_Controller();
// Add here other endpoints imports // Add here other endpoints imports
?> ?>

View File

@ -14,64 +14,74 @@ class Collections extends Repository {
return [ return [
'id' => [ 'id' => [
'map' => 'ID', 'map' => 'ID',
'name' => __('ID', 'tainacan'), 'title' => __('ID', 'tainacan'),
'type' => 'integer',
'description'=> __('Unique identifier', 'tainacan'), 'description'=> __('Unique identifier', 'tainacan'),
//'validation' => v::numeric(), //'validation' => v::numeric(),
], ],
'name' => [ 'name' => [
'map' => 'post_title', 'map' => 'post_title',
'name' => __('Name', 'tainacan'), 'title' => __('Name', 'tainacan'),
'type' => 'string',
'description'=> __('Name of the collection', 'tainacan'), 'description'=> __('Name of the collection', 'tainacan'),
'validation' => v::stringType(), 'validation' => v::stringType(),
], ],
'order' => [ 'order' => [
'map' => 'menu_order', 'map' => 'menu_order',
'name' => __('Order', 'tainacan'), 'title' => __('Order', 'tainacan'),
'type' => 'string',
'description'=> __('Collection order. Field used if collections are manually ordered', 'tainacan'), 'description'=> __('Collection order. Field used if collections are manually ordered', 'tainacan'),
//'validation' => v::stringType(), //'validation' => v::stringType(),
], ],
'parent' => [ 'parent' => [
'map' => 'post_parent', 'map' => 'post_parent',
'name' => __('Parent Collection', 'tainacan'), 'title' => __('Parent Collection', 'tainacan'),
'type' => 'integer',
'description'=> __('Parent collection ID', 'tainacan'), 'description'=> __('Parent collection ID', 'tainacan'),
//'validation' => v::stringType(), //'validation' => v::stringType(),
], ],
'description' => [ 'description' => [
'map' => 'post_content', 'map' => 'post_content',
'name' => __('Description', 'tainacan'), 'title' => __('Description', 'tainacan'),
'type' => 'string',
'description'=> __('Collection description', 'tainacan'), 'description'=> __('Collection description', 'tainacan'),
//'validation' => v::stringType(), //'validation' => v::stringType(),
], ],
'slug' => [ 'slug' => [
'map' => 'post_name', 'map' => 'post_name',
'name' => __('Slug', 'tainacan'), 'title' => __('Slug', 'tainacan'),
'type' => 'string',
'description'=> __('A unique and santized string representation of the collection, used to build the collection URL', 'tainacan'), 'description'=> __('A unique and santized string representation of the collection, used to build the collection URL', 'tainacan'),
//'validation' => v::stringType(), //'validation' => v::stringType(),
], ],
'default_orderby' => [ 'default_orderby' => [
'map' => 'meta', 'map' => 'meta',
'name' => __('Default Order field', 'tainacan'), 'title' => __('Default Order field', 'tainacan'),
'type' => 'string',
'description'=> __('Default property items in this collections will be ordered by', 'tainacan'), 'description'=> __('Default property items in this collections will be ordered by', 'tainacan'),
'default' => 'name', 'default' => 'name',
//'validation' => v::stringType(), //'validation' => v::stringType(),
], ],
'default_order' => [ 'default_order' => [
'map' => 'meta', 'map' => 'meta',
'name' => __('Default order', 'tainacan'), 'title' => __('Default order', 'tainacan'),
'description'=> __('Default order for items in this collection. ASC or DESC', 'tainacan'), 'description'=> __('Default order for items in this collection. ASC or DESC', 'tainacan'),
'type' => 'string',
'default' => 'ASC', 'default' => 'ASC',
'validation' => v::stringType()->in(['ASC', 'DESC']), 'validation' => v::stringType()->in(['ASC', 'DESC']),
], ],
'columns' => [ 'columns' => [
'map' => 'meta', 'map' => 'meta',
'name' => __('Columns', 'tainacan'), 'title' => __('Columns', 'tainacan'),
'type' => 'string',
'description'=> __('List of collections property that will be displayed in the table view', 'tainacan'), 'description'=> __('List of collections property that will be displayed in the table view', 'tainacan'),
//'validation' => v::stringType(), //'validation' => v::stringType(),
], ],
'default_view_mode' => [ 'default_view_mode' => [
'map' => 'meta', 'map' => 'meta',
'name' => __('Default view mode', 'tainacan'), 'title' => __('Default view mode', 'tainacan'),
'type' => 'string',
'description'=> __('Collection default visualization mode', 'tainacan'), 'description'=> __('Collection default visualization mode', 'tainacan'),
//'validation' => v::stringType(), //'validation' => v::stringType(),
], ],

View File

@ -1,7 +1,8 @@
<?php <?php
return [ return [
'tests_dir' => '/tmp/wordpress-tests-lib' 'tests_dir' => '/tmp/wordpress-tests-lib',
'tests_url' => 'http://localhost/wordpress-test-folder/wordpress-test/'
]; ];
?> ?>

View File

@ -9,14 +9,13 @@ class TAINACAN_REST_Collections_Controller extends \WP_UnitTestCase {
$collection_JSON = json_encode([ $collection_JSON = json_encode([
'name' => 'Teste', 'name' => 'Teste',
'description' => 'Teste JSON', 'description' => 'Teste JSON',
'itemsPerPage' => 10,
]); ]);
$collection = wp_remote_post(TAINACAN_TESTS_URL . '/wp-json/tainacan/v2/collections/', array( $collection = wp_remote_post(TAINACAN_TESTS_URL . '/wp-json/tainacan/v2/collections/', array(
'body' => $collection_JSON 'body' => $collection_JSON
)); ));
#$this->assertEquals(200, $collection['response']['code']); $this->assertEquals(201, $collection['response']['code']);
$collection = json_decode(json_decode($collection['body'], true), true); $collection = json_decode(json_decode($collection['body'], true), true);
@ -24,25 +23,25 @@ class TAINACAN_REST_Collections_Controller extends \WP_UnitTestCase {
$response = wp_remote_get(TAINACAN_TESTS_URL . '/wp-json/tainacan/v2/collections/'. $id); $response = wp_remote_get(TAINACAN_TESTS_URL . '/wp-json/tainacan/v2/collections/'. $id);
#$this->assertEquals(200, $response['response']['code']); $this->assertEquals(200, $response['response']['code']);
$data = json_decode(json_decode($response['body'], true), true); $data = json_decode(json_decode($response['body'], true), true);
#$this->assertEquals('Teste', $data['name']); $this->assertEquals('Teste', $data['name']);
} }
public function test_fetch_collections(){ public function test_fetch_collections(){
$response = wp_remote_get(TAINACAN_TESTS_URL . '/wp-json/tainacan/v2/collections/'); $response = wp_remote_get(TAINACAN_TESTS_URL . '/wp-json/tainacan/v2/collections/');
#$this->assertEquals(200, $response['response']['code']); $this->assertEquals(200, $response['response']['code']);
$data = json_decode(json_decode($response['body'], true), true); $data = json_decode(json_decode($response['body'], true), true);
#$this->assertContainsOnly('string', $data); $this->assertContainsOnly('string', $data);
$one_collection = json_decode($data[0], true); $one_collection = json_decode($data[0], true);
#$this->assertEquals('Teste', $one_collection['name']); $this->assertEquals('Teste', $one_collection['name']);
} }
} }