Merge branch 'master' of github.com:tainacan/tainacan

This commit is contained in:
Leo Germani 2017-11-30 14:42:22 -02:00
commit 23631665b5
9 changed files with 259 additions and 65 deletions

View File

@ -8,7 +8,7 @@ This is the development repository for the Tainacan WordPress plugin.
Overview of folders:
* `docs` - This tecnhinal documentation
* `docs` - This technical documentation
* `tests` - phpunit tests
* `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.
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
@ -80,10 +80,11 @@ The parameters are:
* `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`.
If necessary, you can edit the `tests_url` with your configuration.
### 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/' );
@ -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`).
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.
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:

View File

@ -3,11 +3,20 @@
use Tainacan\Repositories;
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 {
private $collections_repository;
private $collection;
public function __construct(){
/**
* TAINACAN_REST_Collections_Controller constructor.
* Define the namespace, rest base and instantiate your attributes.
*/
public function __construct(){
$this->namespace = 'tainacan/v2';
$this->rest_base = 'collections';
$this->collections_repository = new Repositories\Collections();
@ -16,26 +25,28 @@ class TAINACAN_REST_Collections_Controller extends WP_REST_Controller {
add_action('rest_api_init', array($this, 'register_routes'));
}
public function register_routes(){
/**
* Register the collections route and their endpoints
*/
public function register_routes(){
register_rest_route($this->namespace, '/' . $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_collection_params(),
),
array(
'methods' => WP_REST_Server::CREATABLE,
'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),
),
'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(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_item'),
'args' => $this->get_collection_params(),
'permission_callback' => array($this, 'get_item_permissions_check'),
),
array(
@ -51,7 +62,14 @@ class TAINACAN_REST_Collections_Controller extends WP_REST_Controller {
));
}
public function get_items($request){
/**
* Return a array of Collections objects in JSON
*
* @param WP_REST_Request $request
*
* @return WP_Error|WP_REST_Response
*/
public function get_items($request){
$collections = $this->collections_repository->fetch();
$response = $this->prepare_item_for_response($collections, $request);
@ -59,8 +77,15 @@ class TAINACAN_REST_Collections_Controller extends WP_REST_Controller {
return new WP_REST_Response($response, 200);
}
public function get_item($request){
$collection_id = $request['id'];
/**
* Return a Collection object in JSON
*
* @param WP_REST_Request $request
*
* @return WP_Error|WP_REST_Response
*/
public function get_item($request){
$collection_id = $request['collection_id'];
$collection = $this->collections_repository->fetch($collection_id);
$response = $this->prepare_item_for_response($collection, $request);
@ -68,13 +93,28 @@ class TAINACAN_REST_Collections_Controller extends WP_REST_Controller {
return new WP_REST_Response($response, 200);
}
public function prepare_item_for_response($item, $request){
if(is_array($item)){
/**
*
* 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){
if($item instanceof WP_Query){
$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);
}
@ -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){
return true;
}
public function get_items_permissions_check($request){
/**
*
* @param WP_REST_Request $request
*
* @return bool|WP_Error
*/
public function get_item_permissions_check($request){
return true;
}
public function get_item_permissions_check($request){
return true;
}
public function create_item( $request ) {
/**
* 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 ) {
$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 ) );
}
@ -107,47 +165,95 @@ class TAINACAN_REST_Collections_Controller extends WP_REST_Controller {
if($prepared_post->validate()) {
$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);
}
public function create_item_permissions_check( $request ) {
//if(current_user_can('edit_posts')){
/**
* 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 ) {
if(current_user_can('edit_posts')){
return true;
//}
}
return false;
}
public function prepare_item_for_database( $request ) {
/**
* Prepare collection for insertion on database
*
* @param WP_REST_Request $request
*
* @return object|Entities\Collection|WP_Error
*/
public function prepare_item_for_database( $request ) {
$this->collection->set_name($request['name']);
$this->collection->set_description($request['description']);
return $this->collection;
}
/**
* Delete a collection
*
* @param WP_REST_Request $request
*
* @return string|WP_Error|WP_REST_Response
*/
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';
}
public function delete_item_permissions_check( $request ) {
/**
* 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 ) {
if(current_user_can('delete_posts')){
return true;
}
return false;
}
public function update_item( $request ) {
return parent::update_item( $request ); // TODO: Change the autogenerated stub
/**
* Update a collection
*
* @param WP_REST_Request $request
*
* @return string|WP_Error|WP_REST_Response
*/
public function update_item( $request ) {
return 'Não implementado';
}
public function update_item_permissions_check( $request ) {
/**
* 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 ) {
if(current_user_can('edit_posts')){
return true;
}
}
public function get_public_item_schema() {
return parent::get_public_item_schema(); // TODO: Change the autogenerated stub
return false;
}
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 ) {
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
use Tainacan\Repositories;
use Tainacan\Entities;
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');
$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
?>

View File

@ -110,7 +110,7 @@ class Entity {
$mapped = $map[$prop];
$is_valid = true;
if (
isset($mapped['validation']) &&
is_object($mapped['validation']) &&
@ -118,7 +118,7 @@ class Entity {
) {
$validation = $mapped['validation'];
$prop_value = $this->get_mapped_property($prop);
if (is_array($prop_value)) {
foreach ($prop_value as $val) {
if (!$validation->validate($val)) {

View File

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

View File

@ -177,7 +177,7 @@ abstract class Repository {
* @param $args
* @return mixed
*/
public abstract function fetch($args);
public abstract function fetch( $args = [], $output = null );
/**
* @param $object

View File

@ -1,7 +1,8 @@
<?php
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([
'name' => 'Teste',
'description' => 'Teste JSON',
'itemsPerPage' => 10,
]);
$collection = wp_remote_post(TAINACAN_TESTS_URL . '/wp-json/tainacan/v2/collections/', array(
'body' => $collection_JSON
));
#$this->assertEquals(200, $collection['response']['code']);
$this->assertEquals(201, $collection['response']['code']);
$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);
#$this->assertEquals(200, $response['response']['code']);
$this->assertEquals(200, $response['response']['code']);
$data = json_decode(json_decode($response['body'], true), true);
#$this->assertEquals('Teste', $data['name']);
$this->assertEquals('Teste', $data['name']);
}
public function test_fetch_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);
#$this->assertContainsOnly('string', $data);
$this->assertContainsOnly('string', $data);
$one_collection = json_decode($data[0], true);
#$this->assertEquals('Teste', $one_collection['name']);
$this->assertEquals('Teste', $one_collection['name']);
}
}