├── .gitignore ├── starship └── RestfullYii │ ├── vendors │ └── activerecord-relation-behavior │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── composer.json │ │ └── LICENSE │ ├── views │ ├── api │ │ ├── output.php │ │ ├── options.php │ │ └── JSONResult.php │ └── layouts │ │ └── json.php │ ├── tests │ ├── MockObjs │ │ ├── controllers │ │ │ ├── PostController.php │ │ │ ├── UserController.php │ │ │ ├── BinaryController.php │ │ │ ├── CategoryController.php │ │ │ ├── ProfileController.php │ │ │ └── ERestBaseTestController.php │ │ └── models │ │ │ ├── Binary.php │ │ │ ├── Category.php │ │ │ ├── Profile.php │ │ │ ├── User.php │ │ │ └── Post.php │ ├── phpunit.xml │ ├── bootstrap.php │ ├── WebTestCase.php │ ├── unit │ │ ├── ERestActionProviderUnitTest.php │ │ ├── BinaryOutputUnitTest.php │ │ ├── ERestRequestReaderUnitTest.php │ │ ├── EActionRestOPTIONSUnitTest.php │ │ ├── DELETEResourceUnitTest.php │ │ ├── GETSubresourceUnitTest.php │ │ ├── DELETESubresourceUnitTest.php │ │ ├── POSTResourceUnitTest.php │ │ ├── EHttpStatusUnitTest.php │ │ ├── PUTResourceUnitTest.php │ │ ├── PUTSubresourceUnitTest.php │ │ ├── DELETEResourceVisibleHiddenPropertiesUnitTest.php │ │ ├── DELETESubresourceVisibleHiddenPropertiesUnitTest.php │ │ ├── PUTResourceVisibleHiddenPropertiesUnitTest.php │ │ ├── POSTResourceVisibleHiddenPropertiesUnitTest.php │ │ ├── PUTSubresourceVisibleHiddenPropertiesUnitTest.php │ │ ├── GETSubresourcesUnitTest.php │ │ ├── GETCustomRouteUnitTest.php │ │ ├── GETResourcesUnitTest.php │ │ ├── EActionRestPOSTUnitTest.php │ │ ├── GETResourceUnitTest.php │ │ ├── DELETECustomRouteUnitTest.php │ │ ├── PUTCustomRouteUnitTest.php │ │ ├── POSTCustomRouteUnitTest.php │ │ ├── EActionRestPUTUnitTest.php │ │ ├── GETResourceVisibleHiddenPropertiesUnitTest.php │ │ ├── EActionRestGETUnitTest.php │ │ ├── EActionRestDELETEUnitTest.php │ │ ├── ERestBaseActionUnitTest.php │ │ ├── ERestActiveRecordRelationBehaviorUnitTest.php │ │ ├── RequestCycleAuthUnitTest.php │ │ ├── GETResourcesSortUnitTest.php │ │ ├── EventorUnitTest.php │ │ └── GETResourcesLimitOffsetUnitTest.php │ ├── testConfig.php │ ├── migrations │ │ └── ERestTestMigration.php │ ├── ERestTestRequestHelper.php │ └── ERestTestCase.php │ ├── components │ ├── iERestResourceHelper.php │ ├── ERestRequestReader.php │ ├── EHttpStatus.php │ └── ERestResourceHelper.php │ ├── actions │ ├── ERestActionProvider.php │ ├── EActionRestOPTIONS.php │ ├── EActionRestGET.php │ ├── EActionRestPOST.php │ ├── EActionRestDELETE.php │ ├── EActionRestPUT.php │ └── ERestBaseAction.php │ ├── events │ └── Eventor │ │ ├── iEventor.php │ │ └── Eventor.php │ ├── config │ └── routes.php │ ├── filters │ └── ERestFilter.php │ └── ARBehaviors │ └── ERestActiveRecordRelationBehavior.php └── composer.json /.gitignore: -------------------------------------------------------------------------------- 1 | /README.html 2 | *.swp 3 | -------------------------------------------------------------------------------- /starship/RestfullYii/vendors/activerecord-relation-behavior/.gitignore: -------------------------------------------------------------------------------- 1 | tmp/* 2 | yii 3 | -------------------------------------------------------------------------------- /starship/RestfullYii/views/api/output.php: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /starship/RestfullYii/views/layouts/json.php: -------------------------------------------------------------------------------- 1 | getHttpStatus()); 5 | if($this->emitRest( 6 | ERestEvent::REQ_AUTH_CORS, 7 | [$this->emitRest(ERestEvent::REQ_CORS_ACCESS_CONTROL_ALLOW_ORIGIN)] 8 | )) { 9 | @header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']); 10 | } 11 | echo $content; 12 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | setControllerPath(dirname(__FILE__).'/MockObjs/controllers'); 13 | -------------------------------------------------------------------------------- /starship/RestfullYii/vendors/activerecord-relation-behavior/.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | # - 5.2 4 | - 5.3 5 | - 5.4 6 | - 5.5 7 | 8 | env: 9 | - DB=mysql 10 | - DB=pgsql 11 | - DB=sqlite 12 | 13 | # execute any number of scripts before the test run, custom env's are available as variables 14 | before_script: 15 | - git clone --depth=1 https://github.com/yiisoft/yii.git yii 16 | - if [[ "$DB" == "pgsql" ]]; then psql -c "CREATE DATABASE test;" -U postgres; fi 17 | - if [[ "$DB" == "mysql" ]]; then mysql -e "CREATE DATABASE IF NOT EXISTS test;" -uroot; fi 18 | 19 | script: phpunit --colors EActiveRecordRelationBehaviorTest.php 20 | 21 | notifications: 22 | email: "mail@cebe.cc" 23 | -------------------------------------------------------------------------------- /starship/RestfullYii/views/api/options.php: -------------------------------------------------------------------------------- 1 | $origin, 11 | "Access-Control-Max-Age" => $max_age, 12 | "Access-Control-Allow-Methods" => implode(', ', $allowed_methods), 13 | "Access-Control-Allow-Headers: " => implode(', ', $allowed_headers), 14 | ]); 15 | } 16 | -------------------------------------------------------------------------------- /starship/RestfullYii/views/api/JSONResult.php: -------------------------------------------------------------------------------- 1 | widget('RestfullYii.widgets.ERestJSONOutputWidget', array( 3 | 'type' =>(isset($type)? $type: 'raw'), 4 | 'success' =>(isset($success)? $success: true), 5 | 'message' =>(isset($message)? $message: ""), 6 | 'totalCount' =>(isset($totalCount)? $totalCount: ""), 7 | 'modelName' =>(isset($modelName)? $modelName: null), 8 | 'visibleProperties' =>(isset($visibleProperties)? $visibleProperties: null), 9 | 'hiddenProperties' =>(isset($hiddenProperties)? $hiddenProperties: null), 10 | 'data' =>(isset($data)? $data: null), 11 | 'relations' =>(isset($relations)? $relations: []), 12 | 'errorCode' =>(isset($errorCode)? $errorCode: null), 13 | )); 14 | 15 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/WebTestCase.php: -------------------------------------------------------------------------------- 1 | setBrowserUrl(TEST_BASE_URL); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /starship/RestfullYii/vendors/activerecord-relation-behavior/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yiiext/activerecord-relation-behavior", 3 | "description": "Inspired by and put together the awesomeness of many yii extensions that aim to improve saving of related records. Comes with 100% test coverage and well structured and clean code so it can safely be used in enterprise production environment.", 4 | "keywords": ["yii", "extension", "active-record"], 5 | "homepage": "https://github.com/yiiext/activerecord-relation-behavior", 6 | "type": "yii-extension", 7 | "license": "BSD-3-Clause", 8 | "authors": [ 9 | { 10 | "name": "Carsten Brandt", 11 | "email": "mail@cebe.cc" 12 | } 13 | ], 14 | "require": { 15 | "php": ">=5.1.0", 16 | "yiisoft/yii": ">=1.1.6" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /starship/RestfullYii/actions/ERestActionProvider.php: -------------------------------------------------------------------------------- 1 | 'RestfullYii.actions.EActionRestGET', 27 | 'PUT'=>'RestfullYii.actions.EActionRestPUT', 28 | 'POST'=>'RestfullYii.actions.EActionRestPOST', 29 | 'DELETE'=>'RestfullYii.actions.EActionRestDELETE', 30 | 'OPTIONS'=>'RestfullYii.actions.EActionRestOPTIONS', 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "starship/restfullyii", 3 | "type": "library", 4 | "description": "RESTFull API for your Yii application", 5 | "keywords": ["REST", "RESTFull", "Yii", "API"], 6 | "homepage": "https://github.com/evan108108/RESTFullYii", 7 | "license": "WTFPL", 8 | "authors": [ 9 | { 10 | "name": "Evan Frohlich", 11 | "email": "evan108108@gmail.com" 12 | }, 13 | { 14 | "name": "goliatone" 15 | }, 16 | { 17 | "name": "ubin" 18 | }, 19 | { 20 | "name": "jlsalvador" 21 | }, 22 | { 23 | "name": "ericmcgill" 24 | }, 25 | { 26 | "name": "stianlik" 27 | }, 28 | { 29 | "name": "kachar" 30 | }, 31 | { 32 | "name": "drLev" 33 | }, 34 | { 35 | "name": "sheershoff" 36 | }, 37 | { 38 | "name": "Arne-S" 39 | }, 40 | { 41 | "name": "amesmoey" 42 | }, 43 | { 44 | "name": "eligundry" 45 | }, 46 | { 47 | "name": "rominawnc" 48 | } 49 | ], 50 | "require": { 51 | "php": ">=5.4.0" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /starship/RestfullYii/events/Eventor/iEventor.php: -------------------------------------------------------------------------------- 1 | 'RestfullYii.actions.EActionRestGET', 20 | 'PUT'=>'RestfullYii.actions.EActionRestPUT', 21 | 'POST'=>'RestfullYii.actions.EActionRestPOST', 22 | 'DELETE'=>'RestfullYii.actions.EActionRestDELETE', 23 | 'OPTIONS'=>'RestfullYii.actions.EActionRestOPTIONS', 24 | ]; 25 | 26 | /** 27 | * actions 28 | * 29 | * tests ERestActionProvider::actions() 30 | */ 31 | public function testActions() 32 | { 33 | $this->assertArraysEqual($this->actions, ERestActionProvider::actions()); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /starship/RestfullYii/components/ERestRequestReader.php: -------------------------------------------------------------------------------- 1 | filename = $filename; 26 | } 27 | 28 | /** 29 | * getContents 30 | * 31 | * Read the request data 32 | * 33 | * @return (mixed) request data 34 | */ 35 | public function getContents() { 36 | if(is_resource($this->filename)) { 37 | rewind($this->filename); 38 | return stream_get_contents($this->filename); 39 | } 40 | return file_get_contents($this->filename); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/MockObjs/models/Binary.php: -------------------------------------------------------------------------------- 1 | 'http://api/binary/1', 26 | 'type' => 'GET', 27 | 'data' => null, 28 | 'headers' => [ 29 | 'X_REST_USERNAME' => 'admin@restuser', 30 | 'X_REST_PASSWORD' => 'admin@Access', 31 | ], 32 | ]; 33 | 34 | $request_response = $request->send(); 35 | $expected_response = '{"success":true,"message":"Record Found","data":{"totalCount":1,"binary":{"id":"1","name":"de46c83e5a50ced70e6a525a7be6d709"}}}'; 36 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 37 | } 38 | } 39 | 40 | 41 | -------------------------------------------------------------------------------- /starship/RestfullYii/actions/EActionRestOPTIONS.php: -------------------------------------------------------------------------------- 1 | controller->emitRest(ERestEvent::CONFIG_APPLICATION_ID); 30 | $allowed_methods = $this->controller->emitRest(ERestEvent::REQ_CORS_ACCESS_CONTROL_ALLOW_METHODS); 31 | $allowed_headers = $this->controller->emitRest(ERestEvent::REQ_CORS_ACCESS_CONTROL_ALLOW_HEADERS, [$application_id]); 32 | $max_age = $this->controller->emitRest(ERestEvent::REQ_CORS_ACCESS_CONTROL_MAX_AGE); 33 | 34 | $this->controller->emitRest(ERestEvent::REQ_OPTIONS_RENDER, [ 35 | $allowed_headers, 36 | $allowed_methods, 37 | $max_age, 38 | ]); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/MockObjs/models/Category.php: -------------------------------------------------------------------------------- 1 | broken) { 51 | switch(static::$configurationType) 52 | { 53 | default: 54 | return array( 55 | 'posts' => array(self::MANY_MANY, 'Post', 'tbl_post_category(category_id, post_id)'), 56 | ); 57 | } 58 | } 59 | return array( 60 | 'posts' => array(self::MANY_MANY, 'Post', 'tbl_post_category'), 61 | ); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/MockObjs/models/Profile.php: -------------------------------------------------------------------------------- 1 | disableOwnerRule) { 41 | $rules[] = array('user_id', 'required'); 42 | } 43 | $rules[] = array('photo, website', 'safe'); 44 | return $rules; 45 | } 46 | 47 | /** 48 | * @return array relational rules. 49 | */ 50 | public function relations() 51 | { 52 | switch(static::$configurationType) 53 | { 54 | default: 55 | return array( 56 | 'owner' => array(self::BELONGS_TO, 'User', 'user_id'), 57 | ); 58 | case 'fkarray': 59 | return array( 60 | 'owner' => array(self::BELONGS_TO, 'User', array('user_id'=>'id')), 61 | ); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/MockObjs/controllers/ERestBaseTestController.php: -------------------------------------------------------------------------------- 1 | 'RestfullYii.actions.ERestActionProvider', 26 | ); 27 | } 28 | 29 | /** 30 | * Specifies the access control rules. 31 | * This method is used by the 'accessControl' filter. 32 | * @return array access control rules 33 | */ 34 | public function accessRules() 35 | { 36 | return array( 37 | array('allow', 38 | 'actions'=>array('REST.GET', 'REST.PUT', 'REST.POST', 'REST.DELETE', 'REST.OPTIONS'), 39 | 'users'=>array('*'), 40 | ), 41 | array('deny', // deny all users 42 | 'users'=>array('*'), 43 | ), 44 | ); 45 | } 46 | 47 | public function injectEvents($name, Callable $event) 48 | { 49 | $this->_rest_events[$name] = $event; 50 | } 51 | 52 | public function getInjectEvents() 53 | { 54 | return $this->_rest_events; 55 | } 56 | 57 | public function restEvents() 58 | { 59 | foreach($this->getInjectEvents() as $name=>$listener) { 60 | $this->onRest($name, $listener); 61 | } 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/MockObjs/models/User.php: -------------------------------------------------------------------------------- 1 | array(self::HAS_MANY, 'Post', 'author_id'), 57 | 'profile' => array(self::HAS_ONE, 'Profile', 'user_id'), 58 | ); 59 | case 'fkarray': 60 | return array( 61 | 'posts' => array(self::HAS_MANY, 'Post', array('id'=>'author_id')), 62 | 'profile' => array(self::HAS_ONE, 'Profile', array('id'=>'user_id')), 63 | ); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /starship/RestfullYii/vendors/activerecord-relation-behavior/LICENSE: -------------------------------------------------------------------------------- 1 | EActiveRecordRelationBehavior is free software. 2 | It is released under the terms of the following BSD License. 3 | 4 | Copyright © 2012 by Carsten Brandt (mail@cebe.cc, http://www.cebe.cc) 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions 9 | are met: 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | * Neither the name of Carsten Brandt nor the names of its 17 | contributors may be used to endorse or promote products derived 18 | from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/ERestRequestReaderUnitTest.php: -------------------------------------------------------------------------------- 1 | assertEquals($this->getPrivateProperty($errr, 'filename'), 'php://input'); 27 | 28 | $errr = new ERestRequestReader('/tmp/myfile.txt'); 29 | $this->assertEquals($this->getPrivateProperty($errr, 'filename'), '/tmp/myfile.txt'); 30 | } 31 | 32 | /** 33 | * getContents 34 | * 35 | * tests ERestRequestReader->getContents 36 | */ 37 | public function testGetContents() 38 | { 39 | $tmp_file = sys_get_temp_dir() . '/my_req_file.txt'; 40 | file_put_contents($tmp_file, 'TESTING DATA!'); 41 | $errr = new ERestRequestReader($tmp_file); 42 | $this->assertEquals($errr->getContents(), 'TESTING DATA!'); 43 | } 44 | 45 | /** 46 | * getContents 47 | * 48 | * tests ERestRequestReader->getContents with a resource stream 49 | */ 50 | public function testGetContentsWithStream() 51 | { 52 | $data = [ 53 | "test11" => "someval", 54 | "test12" => "secondval" 55 | ]; 56 | $stream = fopen("php://temp", 'wb'); 57 | fputs($stream, CJSON::encode($data)); 58 | $errr = new ERestRequestReader($stream); 59 | $this->assertEquals(CJSON::encode($data), $errr->getContents()); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/MockObjs/models/Post.php: -------------------------------------------------------------------------------- 1 | 255), 43 | array('title, content, create_time, author_id, id', 'safe'), 44 | ); 45 | } 46 | 47 | /** 48 | * @return array relational rules. 49 | */ 50 | public function relations() 51 | { 52 | switch(static::$configurationType) 53 | { 54 | default: 55 | return array( 56 | 'categories' => array(self::MANY_MANY, 'Category', 'tbl_post_category(post_id, category_id)'), 57 | 'author' => array(self::BELONGS_TO, 'User', 'author_id'), 58 | ); 59 | case 'fkarray': 60 | return array( 61 | 'categories' => array(self::MANY_MANY, 'Category', 'tbl_post_category(post_id, category_id)'), 62 | 'author' => array(self::BELONGS_TO, 'User', array('author_id'=>'id')), 63 | ); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /starship/RestfullYii/config/routes.php: -------------------------------------------------------------------------------- 1 | '=>['/REST.GET', 'verb'=>'GET'], 4 | 'api//'=>['/REST.GET', 'verb'=>'GET'], 5 | 'api///'=>['/REST.GET', 'verb'=>'GET'], 6 | 'api////'=>['/REST.GET', 'verb'=>'GET'], 7 | 8 | ['/REST.PUT', 'pattern'=>'api//', 'verb'=>'PUT'], 9 | ['/REST.PUT', 'pattern'=>'api///', 'verb'=>'PUT'], 10 | ['/REST.PUT', 'pattern'=>'api////', 'verb'=>'PUT'], 11 | 12 | ['/REST.DELETE', 'pattern'=>'api//', 'verb'=>'DELETE'], 13 | ['/REST.DELETE', 'pattern'=>'api///', 'verb'=>'DELETE'], 14 | ['/REST.DELETE', 'pattern'=>'api////', 'verb'=>'DELETE'], 15 | 16 | ['/REST.POST', 'pattern'=>'api/', 'verb'=>'POST'], 17 | ['/REST.POST', 'pattern'=>'api//', 'verb'=>'POST'], 18 | ['/REST.POST', 'pattern'=>'api///', 'verb'=>'POST'], 19 | ['/REST.POST', 'pattern'=>'api////', 'verb'=>'POST'], 20 | 21 | ['/REST.OPTIONS', 'pattern'=>'api/', 'verb'=>'OPTIONS'], 22 | ['/REST.OPTIONS', 'pattern'=>'api//', 'verb'=>'OPTIONS'], 23 | ['/REST.OPTIONS', 'pattern'=>'api///', 'verb'=>'OPTIONS'], 24 | ['/REST.OPTIONS', 'pattern'=>'api////', 'verb'=>'OPTIONS'], 25 | 26 | '/'=>'/view', 27 | '//'=>'/', 28 | '/'=>'/', 29 | ]; 30 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/EActionRestOPTIONSUnitTest.php: -------------------------------------------------------------------------------- 1 | getController()->Category; 28 | $controller->attachBehaviors(array( 29 | 'class'=>'RestfullYii.behaviors.ERestBehavior' 30 | )); 31 | $controller->injectEvents('req.cors.access.control.allow.origin', function() { 32 | return ['http://cors-site.test']; 33 | }); 34 | 35 | $_SERVER['HTTP_X_REST_CORS'] = 'ALLOW'; 36 | $_SERVER['HTTP_ORIGIN'] = 'http://cors-site.test'; 37 | 38 | $controller->ERestInit(); 39 | $this->optionsAction = new EActionRestOPTIONS($controller, 'REST.OPTIONS'); 40 | } 41 | 42 | /** 43 | * run 44 | * 45 | * tests EActionRestOPTIONS->run() 46 | */ 47 | public function testRunRESOURCES() 48 | { 49 | $expected_result = '{"Access-Control-Allow-Origin:":"http:\/\/cors-site.test","Access-Control-Max-Age":3628800,"Access-Control-Allow-Methods":"GET, POST","Access-Control-Allow-Headers: ":"X_REST_CORS"}'; 50 | 51 | $result = $this->captureOB($this, function() { 52 | $this->optionsAction->run(); 53 | }); 54 | 55 | $this->assertJsonStringEqualsJsonString($expected_result, $result); 56 | } 57 | 58 | /** 59 | * tearDown 60 | * 61 | * clear server vars 62 | */ 63 | public function tearDown() 64 | { 65 | unset($_SERVER['HTTP_X_REST_CORS'], $_SERVER['HTTP_ORIGIN']); 66 | parent::tearDown(); 67 | } 68 | 69 | } 70 | 71 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/DELETEResourceUnitTest.php: -------------------------------------------------------------------------------- 1 | 'http://api/category/4', 30 | 'type' => 'DELETE', 31 | 'data' => null, 32 | 'headers' => [ 33 | 'X_REST_USERNAME' => 'admin@restuser', 34 | 'X_REST_PASSWORD' => 'admin@Access', 35 | ], 36 | ]; 37 | 38 | $request_response = $request->send(); 39 | $expected_response = '{"success":true,"message":"Record Deleted","data":{"totalCount":1,"category":{"id":"4","name":"cat4"}}}'; 40 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 41 | } 42 | 43 | /** 44 | * testDELETEResourcePostRequest 45 | * 46 | * tests that a DELETE request 47 | * correctly deletes a resource 48 | */ 49 | public function testDELETEResourcePostRequest() 50 | { 51 | $request = new ERestTestRequestHelper(); 52 | 53 | $request['config'] = [ 54 | 'url' => 'http://api/post/2', 55 | 'type' => 'DELETE', 56 | 'data' => null, 57 | 'headers' => [ 58 | 'X_REST_USERNAME' => 'admin@restuser', 59 | 'X_REST_PASSWORD' => 'admin@Access', 60 | ], 61 | ]; 62 | 63 | $request_response = $request->send(); 64 | $expected_response = '{"success":true,"message":"Record Deleted","data":{"totalCount":1,"post":{"id":"2","title":"title2","content":"content2","create_time":"2013-08-07 10:09:42","author_id":"2"}}}'; 65 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/GETSubresourceUnitTest.php: -------------------------------------------------------------------------------- 1 | 'http://api/post/1/categories/1', 30 | 'type' => 'GET', 31 | 'data' => null, 32 | 'headers' => [ 33 | 'X_REST_USERNAME' => 'admin@restuser', 34 | 'X_REST_PASSWORD' => 'admin@Access', 35 | ], 36 | ]; 37 | 38 | $request_response = $request->send(); 39 | $expected_response = '{"success":true,"message":"Record(s) Found","data":{"totalCount":1,"category":{"id":"1","name":"cat1"}}}'; 40 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 41 | } 42 | 43 | /** 44 | * testGETSubresourceRequest 45 | * 46 | * tests that a get request for a single sub-resource 47 | * returns the correct response 48 | */ 49 | public function testGETSubresourceCategoryPostRequest() 50 | { 51 | $request = new ERestTestRequestHelper(); 52 | 53 | $request['config'] = [ 54 | 'url' => 'http://api/category/1/posts/1', 55 | 'type' => 'GET', 56 | 'data' => null, 57 | 'headers' => [ 58 | 'X_REST_USERNAME' => 'admin@restuser', 59 | 'X_REST_PASSWORD' => 'admin@Access', 60 | ], 61 | ]; 62 | 63 | $request_response = $request->send(); 64 | $expected_response = '{"success":true,"message":"Record(s) Found","data":{"totalCount":1,"post":{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1"}}}'; 65 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/DELETESubresourceUnitTest.php: -------------------------------------------------------------------------------- 1 | 'http://api/category/1/posts/1', 30 | 'type' => 'DELETE', 31 | 'data' => null, 32 | 'headers' => [ 33 | 'X_REST_USERNAME' => 'admin@restuser', 34 | 'X_REST_PASSWORD' => 'admin@Access', 35 | ], 36 | ]; 37 | 38 | $request_response = $request->send(); 39 | $expected_response = '{"success":true,"message":"Sub-Resource Deleted","data":{"totalCount":1,"category":{"id":"1","name":"cat1","posts":[]}}}'; 40 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 41 | } 42 | 43 | /** 44 | * testDELETESubresourcePostsCategoriesRequest 45 | * 46 | * tests that a DELETE request 47 | * correctly deletes a Sub-Resource 48 | */ 49 | public function testDELETESubresourcePostsCategoriesRequest() 50 | { 51 | $request = new ERestTestRequestHelper(); 52 | 53 | $request['config'] = [ 54 | 'url' => 'http://api/post/1/categories/1', 55 | 'type' => 'DELETE', 56 | 'data' => null, 57 | 'headers' => [ 58 | 'X_REST_USERNAME' => 'admin@restuser', 59 | 'X_REST_PASSWORD' => 'admin@Access', 60 | ], 61 | ]; 62 | 63 | $request_response = $request->send(); 64 | $expected_response = '{"success":true,"message":"Sub-Resource Deleted","data":{"totalCount":1,"post":{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1","categories":[{"id":"2","name":"cat2"}]}}}'; 65 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 66 | } 67 | 68 | } 69 | 70 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/POSTResourceUnitTest.php: -------------------------------------------------------------------------------- 1 | 'http://api/category', 32 | 'type' => 'POST', 33 | 'data' => $data, 34 | 'headers' => [ 35 | 'X_REST_USERNAME' => 'admin@restuser', 36 | 'X_REST_PASSWORD' => 'admin@Access', 37 | ], 38 | ]; 39 | 40 | $request_response = $request->send(); 41 | $expected_response = '{"success":true,"message":"Record Created","data":{"totalCount":1,"category":{"id":"7","name":"new_cat_name","posts":[]}}}'; 42 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 43 | } 44 | 45 | /** 46 | * testPOSTResourceProfileRequest 47 | * 48 | * tests that a POST request 49 | * correctly creates a resource 50 | */ 51 | public function testPOSTResourceProfileRequest() 52 | { 53 | $request = new ERestTestRequestHelper(); 54 | 55 | $data = '{"user_id":"4","photo":"0","website":"mysite4.com"}'; 56 | 57 | $request['config'] = [ 58 | 'url' => 'http://api/profile', 59 | 'type' => 'POST', 60 | 'data' => $data, 61 | 'headers' => [ 62 | 'X_REST_USERNAME' => 'admin@restuser', 63 | 'X_REST_PASSWORD' => 'admin@Access', 64 | ], 65 | ]; 66 | 67 | $request->addEvent(ERestEvent::MODEL_WITH_RELATIONS, function() { 68 | return []; 69 | }); 70 | 71 | $request_response = $request->send(); 72 | $expected_response = '{"success":true,"message":"Record Created","data":{"totalCount":1,"profile":{"id":"7","user_id":"4","photo":"0","website":"mysite4.com"}}}'; 73 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/EHttpStatusUnitTest.php: -------------------------------------------------------------------------------- 1 | getConsts() as $code) 27 | { 28 | $this->assertTrue(isset($msg[$code])); 29 | } 30 | } 31 | 32 | /** 33 | * __construct 34 | * 35 | * tests EHttpStatus constructor 36 | */ 37 | public function testConstruct() 38 | { 39 | $ehs = new EHttpStatus(); 40 | $this->assertEquals(200, $ehs->code); 41 | $this->assertEquals('OK', $ehs->message); 42 | 43 | foreach($this->getConsts() as $code) 44 | { 45 | $ehs = new EHttpStatus($code); 46 | $this->assertEquals($code, $ehs->code); 47 | $this->assertEquals(EHttpStatus::$messages[$code], $ehs->message); 48 | } 49 | 50 | $ehs = new EHttpStatus(406, 'You are not acceptable!'); 51 | $this->assertEquals(406, $ehs->code); 52 | $this->assertEquals('You are not acceptable!', $ehs->message); 53 | } 54 | 55 | /** 56 | * set 57 | * 58 | * tests EHttpStatus->set() 59 | */ 60 | public function testSet() 61 | { 62 | $ehs = new EHttpStatus(); 63 | $ehs->set(505, 'Not Supported'); 64 | $this->assertEquals(505, $ehs->code); 65 | $this->assertEquals('Not Supported', $ehs->message); 66 | } 67 | 68 | /** 69 | * __toString 70 | * 71 | * tests EHttpStatus __toString magic method 72 | */ 73 | public function testToString() 74 | { 75 | foreach($this->getConsts() as $code) 76 | { 77 | $ehs = new EHttpStatus($code); 78 | $this->assertEquals('HTTP/1.1 '.$code.' '.$ehs->message, (string) $ehs); 79 | } 80 | } 81 | 82 | /** 83 | * getConsts 84 | * 85 | * returns the list of constants in the EHttpStatus class 86 | * 87 | * @return (Array) list of EHttpStatus constants 88 | */ 89 | public function getConsts() 90 | { 91 | $refl = new ReflectionClass('EHttpStatus'); 92 | return $refl->getConstants(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/PUTResourceUnitTest.php: -------------------------------------------------------------------------------- 1 | 'http://api/category/1', 32 | 'type' => 'PUT', 33 | 'data' => $data, 34 | 'headers' => [ 35 | 'X_REST_USERNAME' => 'admin@restuser', 36 | 'X_REST_PASSWORD' => 'admin@Access', 37 | ], 38 | ]; 39 | 40 | $request->addEvent(ERestEvent::MODEL_WITH_RELATIONS, function() { 41 | return []; 42 | }); 43 | 44 | $request_response = $request->send(); 45 | $expected_response = '{"success":true,"message":"Record Updated","data":{"totalCount":1,"category":' . $data . '}}'; 46 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 47 | } 48 | 49 | /** 50 | * testPUTResourceUserRequest 51 | * 52 | * tests that a PUT request 53 | * correctly updates a resource 54 | */ 55 | public function testPUTResourceUserRequest() 56 | { 57 | $request = new ERestTestRequestHelper(); 58 | 59 | $data = '{"id":"2","username":"UPDATEDUSERNAME","password":"UPDATEDPASSWORD","email":"UPDATED@email2.com"}'; 60 | 61 | $request['config'] = [ 62 | 'url' => 'http://api/user/2', 63 | 'type' => 'PUT', 64 | 'data' => $data, 65 | 'headers' => [ 66 | 'X_REST_USERNAME' => 'admin@restuser', 67 | 'X_REST_PASSWORD' => 'admin@Access', 68 | ], 69 | ]; 70 | 71 | $request->addEvent(ERestEvent::MODEL_WITH_RELATIONS, function() { 72 | return []; 73 | }); 74 | 75 | $request_response = $request->send(); 76 | $expected_response = '{"success":true,"message":"Record Updated","data":{"totalCount":1,"user":' . $data . '}}'; 77 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /starship/RestfullYii/actions/EActionRestGET.php: -------------------------------------------------------------------------------- 1 | finalRender( 30 | function($visibleProperties, $hiddenProperties) use($id, $param1, $param2) { 31 | switch ($this->getRequestActionType($id, $param1, $param2, 'get')) { 32 | case 'RESOURCES': 33 | return $this->controller->emitRest(ERestEvent::REQ_GET_RESOURCES_RENDER, [ 34 | $this->getModel($id), $this->getModelName(), $this->getRelations(), $this->getModelCount($id), $visibleProperties, $hiddenProperties 35 | ]); 36 | break; 37 | case 'CUSTOM': 38 | return $this->controller->emitRest("req.get.$id.render", [$param1, $param2]); 39 | break; 40 | case 'SUBRESOURCES': 41 | return $this->controller->emitRest(ERestEvent::REQ_GET_SUBRESOURCES_RENDER, [ 42 | $this->getSubresources($id, $param1), $this->getSubresourceClassName($param1), $this->getSubresourceCount($id, $param1, $param2), $visibleProperties, $hiddenProperties 43 | ]); 44 | break; 45 | case 'SUBRESOURCE': 46 | return $this->controller->emitRest(ERestEvent::REQ_GET_SUBRESOURCE_RENDER, [ 47 | $this->getSubresource($id, $param1, $param2), $this->getSubresourceClassName($param1), $this->getSubresourceCount($id, $param1, $param2), $visibleProperties, $hiddenProperties 48 | ]); 49 | break; 50 | case 'RESOURCE': 51 | return $this->controller->emitRest(ERestEvent::REQ_GET_RESOURCE_RENDER, [ 52 | $this->getModel($id), $this->getModelName(), $this->getRelations(), 1, $visibleProperties, $hiddenProperties 53 | ]); 54 | break; 55 | default: 56 | throw new CHttpException(404, "Resource Not Found"); 57 | } 58 | } 59 | ); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/testConfig.php: -------------------------------------------------------------------------------- 1 | dirname(__FILE__).'/../../../..', 10 | 'name'=>'RestfullYii Testing App', 11 | 12 | // preloading 'log' component 13 | 'preload'=>array('log'), 14 | 15 | 'aliases' => array( 16 | 'app' => 'application', 17 | 'RestfullYii' =>realpath(__DIR__ . '/../') 18 | ), 19 | // autoloading model and component classes 20 | 'import'=>array( 21 | 'application.models.*', 22 | 'application.components.*', 23 | //'vendor.starship.scalar.src.Starship.Scalar.*' 24 | ), 25 | 26 | 'modules'=>array( 27 | // uncomment the following to enable the Gii tool 28 | 29 | 'gii'=>array( 30 | 'class'=>'system.gii.GiiModule', 31 | 'password'=>'Password1', 32 | // If removed, Gii defaults to localhost only. Edit carefully to taste. 33 | 'ipFilters'=>array('127.0.0.1','::1'), 34 | ), 35 | ), 36 | 37 | // application components 38 | 'components'=>array( 39 | 'user'=>array( 40 | // enable cookie-based authentication 41 | 'allowAutoLogin'=>true, 42 | ), 43 | 'fixture'=>array( 44 | 'class'=>'system.test.CDbFixtureManager', 45 | ), 46 | // uncomment the following to enable URLs in path-format 47 | 48 | 'urlManager'=>array( 49 | 'urlFormat'=>'path', 50 | 'rules'=>require(dirname(__FILE__).'/../config/routes.php'), 51 | ), 52 | 'db'=>array( 53 | 'connectionString' => 'mysql:host=localhost;dbname=restfullyii_test', 54 | 'emulatePrepare' => true, 55 | 'username' => 'restfulyiiuser', 56 | 'password' => '', 57 | 'charset' => 'utf8', 58 | ), 59 | 'errorHandler'=>array( 60 | // use 'site/error' action to display errors 61 | 'errorAction'=>'site/error', 62 | ), 63 | 'log'=>array( 64 | 'class'=>'CLogRouter', 65 | 'routes'=>array( 66 | array( 67 | 'class'=>'CFileLogRoute', 68 | 'levels'=>'error, warning, trace', 69 | ), 70 | // uncomment the following to show log messages on web pages 71 | array( 72 | 'class'=>'CWebLogRoute', 73 | ), 74 | ), 75 | ), 76 | ), 77 | 78 | // application-level parameters that can be accessed 79 | // using Yii::app()->params['paramName'] 80 | 'params'=>array( 81 | // this is used in contact page 82 | 'adminEmail'=>'webmaster@example.com', 83 | ), 84 | ); 85 | 86 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/PUTSubresourceUnitTest.php: -------------------------------------------------------------------------------- 1 | 'http://api/category/4/posts/1', 30 | 'type' => 'PUT', 31 | 'data' => null, 32 | 'headers' => [ 33 | 'X_REST_USERNAME' => 'admin@restuser', 34 | 'X_REST_PASSWORD' => 'admin@Access', 35 | ], 36 | ]; 37 | 38 | $request_response = $request->send(); 39 | $expected_response = '{"success":true,"message":"Subresource Added","data":{"totalCount":1,"category":{"id":"4","name":"cat4","posts":[{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1"},{"id":"4","title":"title4","content":"content4","create_time":"2013-08-07 10:09:44","author_id":"4"}]}}}'; 40 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 41 | } 42 | 43 | /** 44 | * testPUTSubresourcePostsCategoriesRequest 45 | * 46 | * tests that a PUT request with belongsTo 47 | * correctly updates a resource 48 | */ 49 | public function testPUTSubresourcePostsCategoriesRequest() 50 | { 51 | $request = new ERestTestRequestHelper(); 52 | 53 | $request['config'] = [ 54 | 'url' => 'http://api/post/1/categories/4', 55 | 'type' => 'PUT', 56 | 'data' => null, 57 | 'headers' => [ 58 | 'X_REST_USERNAME' => 'admin@restuser', 59 | 'X_REST_PASSWORD' => 'admin@Access', 60 | ], 61 | ]; 62 | 63 | $request_response = $request->send(); 64 | $expected_response = '{"success":true,"message":"Subresource Added","data":{"totalCount":1,"post":{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1","categories":[{"id":"1","name":"cat1"},{"id":"2","name":"cat2"},{"id":"4","name":"cat4"}]}}}'; 65 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /starship/RestfullYii/actions/EActionRestPOST.php: -------------------------------------------------------------------------------- 1 | finalRender( 30 | function($visibleProperties, $hiddenProperties) use($id, $param1, $param2) { 31 | switch ($this->getRequestActionType($id, $param1, $param2, 'post')) { 32 | case 'RESOURCES': 33 | return $this->controller->emitRest(ERestEvent::REQ_POST_RESOURCE_RENDER, [$this->handlePost(), $this->getRelations(), $visibleProperties, $hiddenProperties]); 34 | break; 35 | case 'CUSTOM': 36 | return $this->controller->emitRest("req.post.$id.render", [$this->controller->emitRest(ERestEvent::REQ_DATA_READ), $param1, $param2]); 37 | break; 38 | case 'SUBRESOURCES': 39 | throw new CHttpException('405', 'Method Not Allowed'); 40 | break; 41 | case 'SUBRESOURCE': 42 | throw new CHttpException('405', 'Method Not Allowed'); 43 | break; 44 | case 'RESOURCE': 45 | throw new CHttpException('405', 'Method Not Allowed'); 46 | break; 47 | default: 48 | throw new CHttpException(404, "Resource Not Found"); 49 | } 50 | } 51 | ); 52 | } 53 | 54 | /** 55 | * handlePost 56 | * 57 | * Helper method for post actions 58 | * 59 | * @return (Object) Returns the model of the new resource 60 | */ 61 | public function handlePost() 62 | { 63 | $model = $this->controller->emitRest( 64 | ERestEvent::MODEL_ATTACH_BEHAVIORS, 65 | $this->controller->emitRest(ERestEvent::MODEL_INSTANCE) 66 | ); 67 | $data = $this->controller->emitRest(ERestEvent::REQ_DATA_READ); 68 | $restricted_properties = $this->controller->emitRest(ERestEvent::MODEL_RESTRICTED_PROPERTIES); 69 | $model = $this->controller->emitRest(ERestEvent::MODEL_APPLY_POST_DATA, [$model, $data, $restricted_properties]); 70 | return $this->controller->emitRest(ERestEvent::MODEL_SAVE, [$model]); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/DELETEResourceVisibleHiddenPropertiesUnitTest.php: -------------------------------------------------------------------------------- 1 | addEvent('model.visible.properties', function() { 29 | return ['username', 'email']; 30 | }); 31 | 32 | $request->addEvent('model.with.relations', function() { 33 | return []; 34 | }); 35 | 36 | $request['config'] = [ 37 | 'url' => 'http://api/user/1', 38 | 'type' => 'DELETE', 39 | 'data' => null, 40 | 'headers' => [ 41 | 'X_REST_USERNAME' => 'admin@restuser', 42 | 'X_REST_PASSWORD' => 'admin@Access', 43 | ], 44 | ]; 45 | 46 | $request_response = $request->send(); 47 | $expected_response = '{"success":true,"message":"Record Deleted","data":{"totalCount":1,"user":{"username":"username1","email":"email@email1.com"}}}'; 48 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 49 | } 50 | 51 | 52 | /** 53 | * testDELETEResourceHiddenProperties 54 | * 55 | * tests that a DELETE request for a 'User' resource 56 | * With exluded visible fields only 57 | * returns the correct response 58 | */ 59 | public function testDELETEResourceHiddenProperties() 60 | { 61 | $request = new ERestTestRequestHelper(); 62 | 63 | $request->addEvent('model.hidden.properties', function() { 64 | return ['password', 'id']; 65 | }); 66 | 67 | $request->addEvent('model.with.relations', function() { 68 | return []; 69 | }); 70 | 71 | $request['config'] = [ 72 | 'url' => 'http://api/user/1', 73 | 'type' => 'DELETE', 74 | 'data' => null, 75 | 'headers' => [ 76 | 'X_REST_USERNAME' => 'admin@restuser', 77 | 'X_REST_PASSWORD' => 'admin@Access', 78 | ], 79 | ]; 80 | 81 | $request_response = $request->send(); 82 | $expected_response = '{"success":true,"message":"Record Deleted","data":{"totalCount":1,"user":{"username":"username1","email":"email@email1.com"}}}'; 83 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 84 | } 85 | 86 | } 87 | 88 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/DELETESubresourceVisibleHiddenPropertiesUnitTest.php: -------------------------------------------------------------------------------- 1 | addEvent('model.visible.properties', function() { 29 | return ['id', 'name']; 30 | }); 31 | 32 | $request->addEvent('model.with.relations', function() { 33 | return []; 34 | }); 35 | 36 | $request['config'] = [ 37 | 'url' => 'http://api/category/1/posts/1', 38 | 'type' => 'DELETE', 39 | 'data' => null, 40 | 'headers' => [ 41 | 'X_REST_USERNAME' => 'admin@restuser', 42 | 'X_REST_PASSWORD' => 'admin@Access', 43 | ], 44 | ]; 45 | 46 | $request_response = $request->send(); 47 | $expected_response = '{"success":true,"message":"Sub-Resource Deleted","data":{"totalCount":1,"category":{"id":"1","name":"cat1","posts":[]}}}'; 48 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 49 | } 50 | 51 | 52 | /** 53 | * testDELETESubresourceHiddenProperties 54 | * 55 | * tests that a DELETE request for a 'User' resource 56 | * With exluded visible fields only 57 | * returns the correct response 58 | */ 59 | public function testDELETESubresourceHiddenProperties() 60 | { 61 | $request = new ERestTestRequestHelper(); 62 | 63 | $request->addEvent('model.hidden.properties', function() { 64 | return ['id']; 65 | }); 66 | 67 | $request->addEvent('model.with.relations', function() { 68 | return []; 69 | }); 70 | 71 | $request['config'] = [ 72 | 'url' => 'http://api/category/1/posts/1', 73 | 'type' => 'DELETE', 74 | 'data' => null, 75 | 'headers' => [ 76 | 'X_REST_USERNAME' => 'admin@restuser', 77 | 'X_REST_PASSWORD' => 'admin@Access', 78 | ], 79 | ]; 80 | 81 | $request_response = $request->send(); 82 | $expected_response = '{"success":true,"message":"Sub-Resource Deleted","data":{"totalCount":1,"category":{"name":"cat1","posts":[]}}}'; 83 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 84 | } 85 | 86 | } 87 | 88 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/PUTResourceVisibleHiddenPropertiesUnitTest.php: -------------------------------------------------------------------------------- 1 | addEvent('model.visible.properties', function() { 29 | return ['user_id']; 30 | }); 31 | 32 | $request->addEvent('model.with.relations', function() { 33 | return []; 34 | }); 35 | 36 | $data = '{"user_id":"4","photo":"0","website":"mysite4.com"}'; 37 | 38 | $request['config'] = [ 39 | 'url' => 'http://api/profile/1', 40 | 'type' => 'PUT', 41 | 'data' => $data, 42 | 'headers' => [ 43 | 'X_REST_USERNAME' => 'admin@restuser', 44 | 'X_REST_PASSWORD' => 'admin@Access', 45 | ], 46 | ]; 47 | 48 | $request_response = $request->send(); 49 | $expected_response = '{"success":true,"message":"Record Updated","data":{"totalCount":1,"profile":{"user_id":"4"}}}'; 50 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 51 | } 52 | 53 | 54 | /** 55 | * testPUTResourceHiddenProperties 56 | * 57 | * tests that a PUT request for a 'Profile' resource 58 | * With exluded visible fields only 59 | * returns the correct response 60 | */ 61 | public function testPUTResourceHiddenProperties() 62 | { 63 | $request = new ERestTestRequestHelper(); 64 | 65 | $request->addEvent('model.hidden.properties', function() { 66 | return ['website', 'photo', 'id']; 67 | }); 68 | 69 | $request->addEvent('model.with.relations', function() { 70 | return []; 71 | }); 72 | 73 | $data = '{"user_id":"4","photo":"0","website":"mysite4.com"}'; 74 | 75 | $request['config'] = [ 76 | 'url' => 'http://api/profile/1', 77 | 'type' => 'PUT', 78 | 'data' => $data, 79 | 'headers' => [ 80 | 'X_REST_USERNAME' => 'admin@restuser', 81 | 'X_REST_PASSWORD' => 'admin@Access', 82 | ], 83 | ]; 84 | 85 | $request_response = $request->send(); 86 | $expected_response = '{"success":true,"message":"Record Updated","data":{"totalCount":1,"profile":{"user_id":"4"}}}'; 87 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 88 | 89 | } 90 | 91 | } 92 | 93 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/POSTResourceVisibleHiddenPropertiesUnitTest.php: -------------------------------------------------------------------------------- 1 | addEvent('model.visible.properties', function() { 29 | return ['user_id']; 30 | }); 31 | 32 | $request->addEvent('model.with.relations', function() { 33 | return []; 34 | }); 35 | 36 | $data = '{"user_id":"4","photo":"0","website":"mysite4.com"}'; 37 | 38 | $request['config'] = [ 39 | 'url' => 'http://api/profile', 40 | 'type' => 'POST', 41 | 'data' => $data, 42 | 'headers' => [ 43 | 'X_REST_USERNAME' => 'admin@restuser', 44 | 'X_REST_PASSWORD' => 'admin@Access', 45 | ], 46 | ]; 47 | 48 | $request_response = $request->send(); 49 | $expected_response = '{"success":true,"message":"Record Created","data":{"totalCount":1,"profile":{"user_id":"4"}}}'; 50 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 51 | } 52 | 53 | 54 | /** 55 | * testPOSTResourceHiddenProperties 56 | * 57 | * tests that a POST request for a 'Profile' resource 58 | * With exluded visible fields only 59 | * returns the correct response 60 | */ 61 | public function testPOSTResourceHiddenProperties() 62 | { 63 | $request = new ERestTestRequestHelper(); 64 | 65 | $request->addEvent('model.hidden.properties', function() { 66 | return ['website', 'photo', 'id']; 67 | }); 68 | 69 | $request->addEvent('model.with.relations', function() { 70 | return []; 71 | }); 72 | 73 | $data = '{"user_id":"4","photo":"0","website":"mysite4.com"}'; 74 | 75 | $request['config'] = [ 76 | 'url' => 'http://api/profile', 77 | 'type' => 'POST', 78 | 'data' => $data, 79 | 'headers' => [ 80 | 'X_REST_USERNAME' => 'admin@restuser', 81 | 'X_REST_PASSWORD' => 'admin@Access', 82 | ], 83 | ]; 84 | 85 | $request_response = $request->send(); 86 | $expected_response = '{"success":true,"message":"Record Created","data":{"totalCount":1,"profile":{"user_id":"4"}}}'; 87 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 88 | 89 | } 90 | 91 | } 92 | 93 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/PUTSubresourceVisibleHiddenPropertiesUnitTest.php: -------------------------------------------------------------------------------- 1 | addEvent('model.visible.properties', function() { 29 | return ['id', 'name', 'posts.title']; 30 | }); 31 | 32 | $request->addEvent('model.with.relations', function() { 33 | return []; 34 | }); 35 | 36 | $request['config'] = [ 37 | 'url' => 'http://api/category/1/posts/3', 38 | 'type' => 'PUT', 39 | 'data' => null, 40 | 'headers' => [ 41 | 'X_REST_USERNAME' => 'admin@restuser', 42 | 'X_REST_PASSWORD' => 'admin@Access', 43 | ], 44 | ]; 45 | 46 | $request_response = $request->send(); 47 | $expected_response = '{"success":true,"message":"Subresource Added","data":{"totalCount":1,"category":{"id":"1","name":"cat1","posts":[{"title":"title1"},{"title":"title3"}]}}}'; 48 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 49 | } 50 | 51 | 52 | /** 53 | * testPUTSubresourceHiddenProperties 54 | * 55 | * tests that a PUT request for a 'Post' sub-resource 56 | * With exluded visible fields only 57 | * returns the correct response 58 | */ 59 | public function testPUTSubresourceHiddenProperties() 60 | { 61 | $request = new ERestTestRequestHelper(); 62 | 63 | $request->addEvent('model.hidden.properties', function() { 64 | return ['id', 'posts.title', 'posts.content', 'posts.create_time']; 65 | }); 66 | 67 | $request->addEvent('model.with.relations', function() { 68 | return []; 69 | }); 70 | 71 | $request['config'] = [ 72 | 'url' => 'http://api/category/1/posts/3', 73 | 'type' => 'PUT', 74 | 'data' => null, 75 | 'headers' => [ 76 | 'X_REST_USERNAME' => 'admin@restuser', 77 | 'X_REST_PASSWORD' => 'admin@Access', 78 | ], 79 | ]; 80 | 81 | $request_response = $request->send(); 82 | $expected_response = '{"success":true,"message":"Subresource Added","data":{"totalCount":1,"category":{"name":"cat1","posts":[{"id":"1","author_id":"1"},{"id":"3","author_id":"3"}]}}}'; 83 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 84 | } 85 | 86 | } 87 | 88 | -------------------------------------------------------------------------------- /starship/RestfullYii/actions/EActionRestDELETE.php: -------------------------------------------------------------------------------- 1 | finalRender( 30 | function($visibleProperties, $hiddenProperties) use($id, $param1, $param2) { 31 | switch ($this->getRequestActionType($id, $param1, $param2, 'delete')) { 32 | case 'RESOURCES': 33 | throw new CHttpException('405', 'Method Not Allowed'); 34 | break; 35 | case 'CUSTOM': 36 | return $this->controller->emitRest("req.delete.$id.render", [$param1, $param2]); 37 | break; 38 | case 'SUBRESOURCES': 39 | throw new CHttpException('405', 'Method Not Allowed'); 40 | break; 41 | case 'SUBRESOURCE': 42 | return $this->controller->emitRest(ERestEvent::REQ_DELETE_SUBRESOURCE_RENDER, [ 43 | $this->handleSubresourceDelete($id, $param1, $param2), 44 | $param1, 45 | $param2, 46 | $visibleProperties, 47 | $hiddenProperties, 48 | ]); 49 | break; 50 | case 'RESOURCE': 51 | return $this->controller->emitRest(ERestEvent::REQ_DELETE_RESOURCE_RENDER, [$this->handleDelete($id), $visibleProperties, $hiddenProperties]); 52 | break; 53 | default: 54 | throw new CHttpException(404, "Resource Not Found"); 55 | } 56 | } 57 | ); 58 | } 59 | 60 | /** 61 | * handleDelete 62 | * 63 | * Helper method for delete actions 64 | * 65 | * @param (Mixed/Int) (id) unique identifier of the resource to delete 66 | * 67 | * @return (Object) Returns the model of the deleted resource 68 | */ 69 | public function handleDelete($id) 70 | { 71 | $model = $this->controller->emitRest( 72 | ERestEvent::MODEL_ATTACH_BEHAVIORS, 73 | $this->getModel($id) 74 | ); 75 | return $this->controller->emitRest(ERestEvent::MODEL_DELETE, [$model]); 76 | } 77 | 78 | /** 79 | * handleSubresourceDelete 80 | * 81 | * Helper method for delete subresource actions 82 | * 83 | * @param (Mixed/Int) (id) unique identifier of the resource 84 | * @param (String) (param1) name of the subresource 85 | * @param (Mixed/Int) (id) unique identifier of the subresource to delete 86 | * 87 | * @return (Object) Returns the model containing the deleted subresource 88 | */ 89 | public function handleSubresourceDelete($id, $param1, $param2) 90 | { 91 | $model = $this->controller->emitRest( 92 | ERestEvent::MODEL_ATTACH_BEHAVIORS, 93 | $this->getModel($id) 94 | ); 95 | return $this->controller->emitRest(ERestEvent::MODEL_SUBRESOURCE_DELETE, [$model, $param1, $param2]); 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/GETSubresourcesUnitTest.php: -------------------------------------------------------------------------------- 1 | 'http://api/post/1/categories', 30 | 'type' => 'GET', 31 | 'data' => null, 32 | 'headers' => [ 33 | 'X_REST_USERNAME' => 'admin@restuser', 34 | 'X_REST_PASSWORD' => 'admin@Access', 35 | ], 36 | ]; 37 | 38 | $request_response = $request->send(); 39 | $expected_response = '{"success":true,"message":"Record(s) Found","data":{"totalCount":2,"category":[{"id":"1","name":"cat1"},{"id":"2","name":"cat2"}]}}'; 40 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 41 | } 42 | 43 | /** 44 | * testGETSubresourcesRequest 45 | * 46 | * tests that a get request for sub-resources 47 | * returns the correct response 48 | */ 49 | public function testGETSubresourcesCategoryPostRequest() 50 | { 51 | $request = new ERestTestRequestHelper(); 52 | 53 | $request['config'] = [ 54 | 'url' => 'http://api/category/1/posts', 55 | 'type' => 'GET', 56 | 'data' => null, 57 | 'headers' => [ 58 | 'X_REST_USERNAME' => 'admin@restuser', 59 | 'X_REST_PASSWORD' => 'admin@Access', 60 | ], 61 | ]; 62 | 63 | $request_response = $request->send(); 64 | $expected_response = '{"success":true,"message":"Record(s) Found","data":{"totalCount":1,"post":[{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1"}]}}'; 65 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 66 | } 67 | 68 | 69 | /** 70 | * testGETSubresourcesCategoryUserRequestForHasManyWithEventOverrideRequest 71 | * 72 | * tests that a get request for a non sub-resources (HAS_MANY) with event override 73 | * returns the correct response 74 | */ 75 | public function testGETSubresourcesCategoryUserRequestForHasManyWithEventOverrideRequest() 76 | { 77 | $request = new ERestTestRequestHelper(); 78 | 79 | $request['config'] = [ 80 | 'url' => 'http://api/user/1/posts', 81 | 'type' => 'GET', 82 | 'data' => null, 83 | 'headers' => [ 84 | 'X_REST_USERNAME' => 'admin@restuser', 85 | 'X_REST_PASSWORD' => 'admin@Access', 86 | ], 87 | ]; 88 | 89 | $request->addEvent('req.is.subresource', function($model, $subresource_name, $http_verb) { 90 | return true; 91 | }); 92 | 93 | $request_response = $request->send(); 94 | $expected_response = '{"success":true,"message":"Record(s) Found","data":{"totalCount":1,"post":[{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1"}]}}'; 95 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 96 | } 97 | 98 | } 99 | 100 | -------------------------------------------------------------------------------- /starship/RestfullYii/filters/ERestFilter.php: -------------------------------------------------------------------------------- 1 | run() to allow 26 | */ 27 | protected function preFilter($filterChain) 28 | { 29 | $controller = $filterChain->controller; 30 | 31 | $controller->attachBehaviors([ 32 | 'ERestBehavior'=>'RestfullYii.behaviors.ERestBehavior' 33 | ]); 34 | $controller->ERestInit(); 35 | 36 | /** 37 | * Since we are going to be outputting JSON 38 | * we disable CWebLogRoute unless otherwise indicated 39 | */ 40 | if( $controller->emitRest(ERestEvent::REQ_DISABLE_CWEBLOGROUTE ) ){ 41 | foreach (Yii::app()->log->routes as $route) { 42 | if ( $route instanceof CWebLogRoute ) { 43 | $route->enabled = false; 44 | } 45 | } 46 | } 47 | 48 | 49 | if( $controller->emitRest(ERestEvent::REQ_AUTH_HTTPS_ONLY) ) { 50 | if( !$this->validateHttpsOnly() ) { 51 | throw new CHttpException(401, "You must use a secure connection"); 52 | } 53 | } 54 | 55 | 56 | $application_id = $controller->emitRest(ERestEvent::CONFIG_APPLICATION_ID); 57 | 58 | switch ($controller->emitRest(ERestEvent::REQ_AUTH_TYPE, $application_id)) { 59 | case ERestEventListenerRegistry::REQ_TYPE_CORS: 60 | $authorized = $controller->emitRest( 61 | ERestEvent::REQ_AUTH_CORS, 62 | [$controller->emitRest(ERestEvent::REQ_CORS_ACCESS_CONTROL_ALLOW_ORIGIN)] 63 | ); 64 | break; 65 | case ERestEventListenerRegistry::REQ_TYPE_USERPASS: 66 | $authorized = ($controller->emitRest(ERestEvent::REQ_AUTH_USER, [ 67 | $application_id, 68 | $controller->emitRest(ERestEvent::REQ_AUTH_USERNAME), 69 | $controller->emitRest(ERestEvent::REQ_AUTH_PASSWORD), 70 | ])); 71 | break; 72 | case ERestEventListenerRegistry::REQ_TYPE_AJAX: 73 | $authorized = ($controller->emitRest(ERestEvent::REQ_AUTH_AJAX_USER)); 74 | break; 75 | default: 76 | $authorized = false; 77 | break; 78 | } 79 | 80 | if(!$authorized) { 81 | throw new CHttpException(401, "Unauthorized"); 82 | } 83 | 84 | if(!$controller->emitRest(ERestEvent::REQ_AUTH_URI, $controller->getURIAndHTTPVerb())) { 85 | throw new CHttpException(401, "Unauthorized"); 86 | } 87 | 88 | return $filterChain->run(); 89 | } 90 | 91 | /** 92 | * postFilter 93 | * 94 | * logic being applied after the action is executed 95 | * 96 | * @param (Object) (filterChain) the filterChain object 97 | */ 98 | protected function postFilter($filterChain) 99 | { 100 | $filterChain->controller->emitRest(ERestEvent::REQ_AFTER_ACTION, $filterChain); 101 | } 102 | 103 | /** 104 | * validateHttpsOnly 105 | * 106 | * checks if request is https 107 | * 108 | * @return (bool) returns true if the request protocol is https; false if not 109 | */ 110 | public final function validateHttpsOnly() 111 | { 112 | if (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS']!='on'){ 113 | return false; 114 | } 115 | return true; 116 | } 117 | } 118 | 119 | -------------------------------------------------------------------------------- /starship/RestfullYii/actions/EActionRestPUT.php: -------------------------------------------------------------------------------- 1 | finalRender(function($visibleProperties, $hiddenProperties) use($id, $param1, $param2) { 30 | switch ($this->getRequestActionType($id, $param1, $param2, 'put')) { 31 | case 'RESOURCES': 32 | throw new CHttpException('405', 'Method Not Allowed'); 33 | break; 34 | case 'CUSTOM': 35 | return $this->controller->emitRest("req.put.$id.render", [$this->controller->emitRest(ERestEvent::REQ_DATA_READ), $param1, $param2]); 36 | break; 37 | case 'SUBRESOURCES': 38 | throw new CHttpException('405', 'Method Not Allowed'); 39 | break; 40 | case 'SUBRESOURCE': 41 | return $this->controller->emitRest(ERestEvent::REQ_PUT_SUBRESOURCE_RENDER, [ 42 | $this->handlePutSubresource($id, $param1, $param2), 43 | $param1, 44 | $param2, 45 | $visibleProperties, 46 | $hiddenProperties, 47 | ]); 48 | break; 49 | case 'RESOURCE': 50 | return $this->controller->emitRest(ERestEvent::REQ_PUT_RESOURCE_RENDER, [$this->handlePut($id), $this->getRelations(), $visibleProperties, $hiddenProperties]); 51 | break; 52 | default: 53 | throw new CHttpException(404, "Resource Not Found"); 54 | } 55 | } 56 | ); 57 | } 58 | 59 | /** 60 | * handlePut 61 | * 62 | * Helper method for PUT actions 63 | * 64 | * @param (Mixed/Int) (id) unique identifier of the resource to put 65 | * 66 | * @return (Object) Returns the model of the updated resource 67 | */ 68 | public function handlePut($id) 69 | { 70 | $model = $this->controller->emitRest( 71 | ERestEvent::MODEL_ATTACH_BEHAVIORS, 72 | $this->getModel($id) 73 | ); 74 | $data = $this->controller->emitRest(ERestEvent::REQ_DATA_READ); 75 | $restricted_properties = $this->controller->emitRest(ERestEvent::MODEL_RESTRICTED_PROPERTIES); 76 | $model = $this->controller->emitRest(ERestEvent::MODEL_APPLY_PUT_DATA, [$model, $data, $restricted_properties]); 77 | return $this->controller->emitRest(ERestEvent::MODEL_SAVE, [$model]); 78 | } 79 | 80 | /** 81 | * handlePutSubresource 82 | * 83 | * Helper method for PUT subresource actions 84 | * 85 | * @param (Mixed/Int) (id) unique identifier of the resource 86 | * @param (String) (subresource_name) name of the subresource 87 | * @param (Mixed/Int) (subresource_id) unique identifier of the subresource to put 88 | * 89 | * @return (Object) Returns the model containing the updated subresource 90 | */ 91 | public function handlePutSubresource($id, $subresource_name, $subresource_id) 92 | { 93 | $model = $this->controller->emitRest( 94 | ERestEvent::MODEL_ATTACH_BEHAVIORS, 95 | $this->getModel($id) 96 | ); 97 | $this->controller->emitRest(ERestEvent::MODEL_SUBRESOURCE_SAVE, [$model, $subresource_name, $subresource_id]); 98 | return $model; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /starship/RestfullYii/components/EHttpStatus.php: -------------------------------------------------------------------------------- 1 | 'Continue', 62 | 101 => 'Switching Protocols', 63 | 200 => 'OK', 64 | 201 => 'Created', 65 | 202 => 'Accepted', 66 | 203 => 'Non-Authoritative Information', 67 | 204 => 'No Content', 68 | 205 => 'Reset Content', 69 | 206 => 'Partial Content', 70 | 300 => 'Multiple Choices', 71 | 301 => 'Moved Permanently', 72 | 302 => 'Found', 73 | 303 => 'See Other', 74 | 304 => 'Not Modified', 75 | 305 => 'Use Proxy', 76 | 307 => 'Temporary Redirect', 77 | 400 => 'Bad Request', 78 | 401 => 'Unauthorized', 79 | 402 => 'Payment Required', 80 | 403 => 'Forbidden', 81 | 404 => 'Not Found', 82 | 405 => 'Method Not Allowed', 83 | 406 => 'Not Acceptable', 84 | 407 => 'Proxy Authentication Required', 85 | 408 => 'Request Timeout', 86 | 409 => 'Conflict', 87 | 410 => 'Gone', 88 | 411 => 'Length Required', 89 | 412 => 'Precondition Failed', 90 | 413 => 'Request Entity Too Large', 91 | 414 => 'Request-URI Too Long', 92 | 415 => 'Unsupported Media Type', 93 | 416 => 'Requested Range Not Satisfiable', 94 | 417 => 'Expectation Failed', 95 | 500 => 'Internal Server Error', 96 | 501 => 'Not Implemented', 97 | 502 => 'Bad Gateway', 98 | 503 => 'Service Unavailable', 99 | 504 => 'Gateway Timeout', 100 | 505 => 'HTTP Version Not Supported', 101 | ]; 102 | 103 | /** 104 | * @var int The http status code. 105 | */ 106 | public $code; 107 | 108 | /** 109 | * @var string The http status message. 110 | */ 111 | public $message; 112 | 113 | /** 114 | * @param int $code The Http status code. [optional] 115 | */ 116 | public function __construct($code = self::CODE_OK, $message = null) 117 | { 118 | $this->set($code, $message); 119 | } 120 | 121 | public function set($code = self::CODE_OK, $message = null) 122 | { 123 | if ($message === null && isset(self::$messages[$code])) { 124 | $message = self::$messages[$code]; 125 | } 126 | $this->code = $code; 127 | $this->message = $message; 128 | 129 | return $this; 130 | } 131 | /** 132 | * @return string The Http status. 133 | */ 134 | public function __toString() 135 | { 136 | return 'HTTP/1.1 '.$this->code.' '.$this->message; 137 | } 138 | 139 | } 140 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/GETCustomRouteUnitTest.php: -------------------------------------------------------------------------------- 1 | 'http://api/category/testing', 30 | 'type' => 'GET', 31 | 'data' => null, 32 | 'headers' => [ 33 | 'X_REST_USERNAME' => 'admin@restuser', 34 | 'X_REST_PASSWORD' => 'admin@Access', 35 | ], 36 | ]; 37 | 38 | $request->addEvent('req.get.testing.render', function() { 39 | echo CJSON::encode(['myParam' => 'myValue']); 40 | }); 41 | 42 | $request_response = $request->send(); 43 | $expected_response = '{"myParam":"myValue"}'; 44 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 45 | } 46 | 47 | /** 48 | * testGETCustomRouteOneParamRequest 49 | * 50 | * tests that a GET request with custom route and one param 51 | * returns the correct response 52 | */ 53 | public function testGETCustomRouteOneParamRequest() 54 | { 55 | $request = new ERestTestRequestHelper(); 56 | 57 | $request['config'] = [ 58 | 'url' => 'http://api/post/testing/1', 59 | 'type' => 'GET', 60 | 'data' => null, 61 | 'headers' => [ 62 | 'X_REST_USERNAME' => 'admin@restuser', 63 | 'X_REST_PASSWORD' => 'admin@Access', 64 | ], 65 | ]; 66 | 67 | $request->addEvent('req.get.testing.render', function($param1) { 68 | echo CJSON::encode(['myParam' => "$param1"]); 69 | }); 70 | 71 | $request_response = $request->send(); 72 | $expected_response = '{"myParam":"1"}'; 73 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 74 | } 75 | 76 | /** 77 | * testGETCustomRouteTowParamRequest 78 | * 79 | * tests that a GET request with custom route and two params 80 | * returns the correct response 81 | */ 82 | public function testGETCustomRouteTwoParamRequest() 83 | { 84 | $request = new ERestTestRequestHelper(); 85 | 86 | $request['config'] = [ 87 | 'url' => 'http://api/user/testing/a/b', 88 | 'type' => 'GET', 89 | 'data' => null, 90 | 'headers' => [ 91 | 'X_REST_USERNAME' => 'admin@restuser', 92 | 'X_REST_PASSWORD' => 'admin@Access', 93 | ], 94 | ]; 95 | 96 | $request->addEvent('req.get.testing.render', function($param1, $param2) { 97 | echo CJSON::encode([$param1 => $param2]); 98 | }); 99 | 100 | $request_response = $request->send(); 101 | $expected_response = '{"a":"b"}'; 102 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 103 | } 104 | 105 | /** 106 | * testGETCustomRouteTowParamPreFilterRequest 107 | * 108 | * tests that a GET request with custom route and two params and pre-filter 109 | * returns the correct response 110 | */ 111 | public function testGETCustomRouteTwoParamPreFilterRequest() 112 | { 113 | $request = new ERestTestRequestHelper(); 114 | 115 | $request['config'] = [ 116 | 'url' => 'http://api/user/testing/a/b', 117 | 'type' => 'GET', 118 | 'data' => null, 119 | 'headers' => [ 120 | 'X_REST_USERNAME' => 'admin@restuser', 121 | 'X_REST_PASSWORD' => 'admin@Access', 122 | ], 123 | ]; 124 | 125 | $request->addEvent('req.get.testing.render', function($param1, $param2) { 126 | echo CJSON::encode([$param1 => $param2]); 127 | }); 128 | 129 | $request->addEvent('pre.filter.req.get.testing.render', function($param1, $param2) { 130 | return ["pre_1_$param1", "pre_2_$param2"]; 131 | }); 132 | 133 | $request_response = $request->send(); 134 | $expected_response = '{"pre_1_a":"pre_2_b"}'; 135 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/GETResourcesUnitTest.php: -------------------------------------------------------------------------------- 1 | 'http://api/category', 30 | 'type' => 'GET', 31 | 'data' => null, 32 | 'headers' => [ 33 | 'X_REST_USERNAME' => 'admin@restuser', 34 | 'X_REST_PASSWORD' => 'admin@Access', 35 | ], 36 | ]; 37 | 38 | $request_response = $request->send(); 39 | $expected_response = '{"success":true,"message":"Record(s) Found","data":{"totalCount":6,"category":[{"id":"1","name":"cat1","posts":[{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1"}]},{"id":"2","name":"cat2","posts":[{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1"},{"id":"2","title":"title2","content":"content2","create_time":"2013-08-07 10:09:42","author_id":"2"}]},{"id":"3","name":"cat3","posts":[{"id":"3","title":"title3","content":"content3","create_time":"2013-08-07 10:09:43","author_id":"3"}]},{"id":"4","name":"cat4","posts":[{"id":"4","title":"title4","content":"content4","create_time":"2013-08-07 10:09:44","author_id":"4"}]},{"id":"5","name":"cat5","posts":[{"id":"5","title":"title5","content":"content5","create_time":"2013-08-07 10:09:45","author_id":"5"}]},{"id":"6","name":"cat6","posts":[{"id":"6","title":"title6","content":"content6","create_time":"2013-08-07 10:09:46","author_id":"6"}]}]}}'; 40 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 41 | } 42 | 43 | /** 44 | * testGETResourcesPostsRequest 45 | * 46 | * tests that a GET request for a list of 'Post' resources 47 | * returns the correct response 48 | */ 49 | public function testGETResourcesPostsRequest() 50 | { 51 | $request = new ERestTestRequestHelper(); 52 | 53 | $request['config'] = [ 54 | 'url' => 'http://api/post', 55 | 'type' => 'GET', 56 | 'data' => null, 57 | 'headers' => [ 58 | 'X_REST_USERNAME' => 'admin@restuser', 59 | 'X_REST_PASSWORD' => 'admin@Access', 60 | ], 61 | ]; 62 | 63 | $request_response = $request->send(); 64 | $expected_response = '{"success":true,"message":"Record(s) Found","data":{"totalCount":6,"post":[{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1","categories":[{"id":"1","name":"cat1"},{"id":"2","name":"cat2"}],"author":{"id":"1","username":"username1","password":"password1","email":"email@email1.com"}},{"id":"2","title":"title2","content":"content2","create_time":"2013-08-07 10:09:42","author_id":"2","categories":[{"id":"2","name":"cat2"}],"author":{"id":"2","username":"username2","password":"password2","email":"email@email2.com"}},{"id":"3","title":"title3","content":"content3","create_time":"2013-08-07 10:09:43","author_id":"3","categories":[{"id":"3","name":"cat3"}],"author":{"id":"3","username":"username3","password":"password3","email":"email@email3.com"}},{"id":"4","title":"title4","content":"content4","create_time":"2013-08-07 10:09:44","author_id":"4","categories":[{"id":"4","name":"cat4"}],"author":{"id":"4","username":"username4","password":"password4","email":"email@email4.com"}},{"id":"5","title":"title5","content":"content5","create_time":"2013-08-07 10:09:45","author_id":"5","categories":[{"id":"5","name":"cat5"}],"author":{"id":"5","username":"username5","password":"password5","email":"email@email5.com"}},{"id":"6","title":"title6","content":"content6","create_time":"2013-08-07 10:09:46","author_id":"6","categories":[{"id":"6","name":"cat6"}],"author":{"id":"6","username":"username6","password":"password6","email":"email@email6.com"}}]}}'; 65 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/EActionRestPOSTUnitTest.php: -------------------------------------------------------------------------------- 1 | getController()->Category; 28 | $controller->attachBehaviors(array( 29 | 'class'=>'RestfullYii.behaviors.ERestBehavior' 30 | )); 31 | $controller->injectEvents('req.post.my_custom_route.render', function($data, $param1='', $param2='') { 32 | echo "My Custom Route" . $param1 . $param2 . '_' . implode('_', $data); 33 | }); 34 | $controller->injectEvents('req.data.read', function() { 35 | return [ 36 | 'name' => 'cat-new', 37 | ]; 38 | }); 39 | 40 | $controller->ERestInit(); 41 | $this->postAction = new EActionRestPOST($controller, 'REST.POST'); 42 | } 43 | 44 | /** 45 | * run 46 | * 47 | * tests EActionRestPOST->run() 48 | */ 49 | public function testRunRESOURCES() 50 | { 51 | $result = $this->captureOB($this, function() { 52 | $this->postAction->run(); 53 | }); 54 | $this->assertJSONFormat($result); 55 | $this->assertJsonStringEqualsJsonString( 56 | $result, 57 | '{"success":true,"message":"Record Created","data":{"totalCount":1,"category":{"id":"7","name":"cat-new","posts":[]}}}' 58 | ); 59 | } 60 | 61 | /** 62 | * run 63 | * 64 | * tests EActionRestPOST->run('my_custom_route') 65 | */ 66 | public function testRunCUSTOM() 67 | { 68 | $result = $this->captureOB($this, function() { 69 | $this->postAction->run('my_custom_route'); 70 | }); 71 | $this->assertEquals($result, 'My Custom Route_cat-new'); 72 | 73 | $result = $this->captureOB($this, function() { 74 | $this->postAction->run('my_custom_route', '_p1'); 75 | }); 76 | $this->assertEquals($result, 'My Custom Route_p1_cat-new'); 77 | 78 | $result = $this->captureOB($this, function() { 79 | $this->postAction->run('my_custom_route', '_p1', '_p2'); 80 | }); 81 | $this->assertEquals($result, 'My Custom Route_p1_p2_cat-new'); 82 | } 83 | 84 | /** 85 | * run 86 | * 87 | * tests EActionRestPOST->run(1, 'posts') 88 | */ 89 | public function testSubresources() 90 | { 91 | $result = $this->captureOB($this, function() { 92 | $this->postAction->run(1, 'posts'); 93 | }); 94 | $this->assertInstanceOf('Exception', $result); 95 | $this->assertExceptionHasMessage('Method Not Allowed', $result); 96 | } 97 | 98 | /** 99 | * run 100 | * 101 | * tests EActionRestPOST->run(1, 'posts', 1) 102 | */ 103 | public function testSubresource() 104 | { 105 | $result = $this->captureOB($this, function() { 106 | $this->postAction->run(1, 'posts', 1); 107 | }); 108 | $this->assertInstanceOf('Exception', $result); 109 | $this->assertExceptionHasMessage('Method Not Allowed', $result); 110 | } 111 | 112 | /** 113 | * run 114 | * 115 | * tests EActionRestPOST->run(1) 116 | */ 117 | public function testResource() 118 | { 119 | $result = $this->captureOB($this, function() { 120 | $this->postAction->run(1); 121 | }); 122 | $this->assertInstanceOf('Exception', $result); 123 | $this->assertExceptionHasMessage('Method Not Allowed', $result); 124 | } 125 | 126 | /** 127 | * run 128 | * 129 | * tests EActionRestPOST->run('WHAT-THE-RESOURCE') 130 | */ 131 | public function testRunResourceNotFound() 132 | { 133 | $result = $this->captureOB($this, function() { 134 | $this->postAction->run('WHAT-THE-RESOURCE'); 135 | }); 136 | $this->assertInstanceOf('Exception', $result); 137 | $this->assertExceptionHasMessage('Resource Not Found', $result); 138 | } 139 | 140 | /** 141 | * handlePost 142 | * 143 | * test EActionRestPOST->handlePost() 144 | */ 145 | public function testHandlePost() 146 | { 147 | $new_model = $this->postAction->handlePost(); 148 | $this->assertInstanceOf('Category', $new_model); 149 | $this->assertEquals($new_model->id, 7); 150 | } 151 | 152 | } 153 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/GETResourceUnitTest.php: -------------------------------------------------------------------------------- 1 | 'http://api/post/6', 30 | 'type' => 'GET', 31 | 'data' => null, 32 | 'headers' => [ 33 | 'X_REST_USERNAME' => 'admin@restuser', 34 | 'X_REST_PASSWORD' => 'admin@Access', 35 | ], 36 | ]; 37 | 38 | $request->addEvent(ERestEvent::POST_FILTER_MODEL_WITH_RELATIONS, function() { 39 | return []; 40 | }); 41 | 42 | $request_response = $request->send(); 43 | $expected_response = '{"success":true,"message":"Record Found","data":{"totalCount":1,"post":{"id":"6","title":"title6","content":"content6","create_time":"2013-08-07 10:09:46","author_id":"6"}}}'; 44 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 45 | } 46 | 47 | /** 48 | * testGETResourceRequestWithRelations 49 | * 50 | * tests that a get request for a single resource 51 | * returns the correct response 52 | */ 53 | public function testGETResourceRequestWithRelations() 54 | { 55 | $request = new ERestTestRequestHelper(); 56 | 57 | $request['config'] = [ 58 | 'url' => 'http://api/post/6', 59 | 'type' => 'GET', 60 | 'data' => null, 61 | 'headers' => [ 62 | 'X_REST_USERNAME' => 'admin@restuser', 63 | 'X_REST_PASSWORD' => 'admin@Access', 64 | ], 65 | ]; 66 | 67 | $request->addEvent(ERestEvent::POST_FILTER_MODEL_WITH_RELATIONS, function() { 68 | return ['author', 'categories']; 69 | }); 70 | 71 | $request_response = $request->send(); 72 | $expected_response = '{"success":true,"message":"Record Found","data":{"totalCount":1,"post":{"id":"6","title":"title6","content":"content6","create_time":"2013-08-07 10:09:46","author_id":"6","author":{"id":"6","username":"username6","password":"password6","email":"email@email6.com"},"categories":[{"id":"6","name":"cat6"}]}}}'; 73 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 74 | } 75 | 76 | /** 77 | * testGETCategory 78 | * 79 | * tests that a get request for a single resource (category) 80 | * returns the correct response 81 | */ 82 | public function testGETCategory() 83 | { 84 | $request = new ERestTestRequestHelper(); 85 | 86 | $request['config'] = [ 87 | 'url' => 'http://api/category/1', 88 | 'type' => 'GET', 89 | 'data' => null, 90 | 'headers' => [ 91 | 'X_REST_USERNAME' => 'admin@restuser', 92 | 'X_REST_PASSWORD' => 'admin@Access', 93 | ], 94 | ]; 95 | 96 | $request_response = $request->send(); 97 | $expected_response = '{"success":true,"message":"Record Found","data":{"totalCount":1,"category":{"id":"1","name":"cat1","posts":[{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1"}]}}}'; 98 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 99 | } 100 | 101 | /** 102 | * testGETProfile 103 | * 104 | * tests that a get request for a single resource (category) 105 | * returns the correct response 106 | */ 107 | public function testGETProfile() 108 | { 109 | $request = new ERestTestRequestHelper(); 110 | 111 | $request['config'] = [ 112 | 'url' => 'http://api/profile/2', 113 | 'type' => 'GET', 114 | 'data' => null, 115 | 'headers' => [ 116 | 'X_REST_USERNAME' => 'admin@restuser', 117 | 'X_REST_PASSWORD' => 'admin@Access', 118 | ], 119 | ]; 120 | 121 | $request_response = $request->send(); 122 | $expected_response = '{"success":true,"message":"Record Found","data":{"totalCount":1,"profile":{"id":"2","user_id":"2","photo":"0","website":"mysite2.com","owner":{"id":"2","username":"username2","password":"password2","email":"email@email2.com"}}}}'; 123 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/DELETECustomRouteUnitTest.php: -------------------------------------------------------------------------------- 1 | 'http://api/category/testing', 30 | 'type' => 'DELETE', 31 | 'data' => null, 32 | 'headers' => [ 33 | 'X_REST_USERNAME' => 'admin@restuser', 34 | 'X_REST_PASSWORD' => 'admin@Access', 35 | ], 36 | ]; 37 | 38 | $request->addEvent('req.delete.testing.render', function() { 39 | echo CJSON::encode(['test'=>'data']); 40 | }); 41 | 42 | $request_response = $request->send(); 43 | $expected_response = '{"test":"data"}'; 44 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 45 | } 46 | 47 | 48 | /** 49 | * testDELETECustomRouteOneParamRequest 50 | * 51 | * tests that a DELETE request with custom route and one param 52 | * returns the correct response 53 | */ 54 | public function testDELETECustomRouteOneParamRequest() 55 | { 56 | $request = new ERestTestRequestHelper(); 57 | 58 | $request['config'] = [ 59 | 'url' => 'http://api/post/testing/1', 60 | 'type' => 'DELETE', 61 | 'data' => '{"test":"data"}', 62 | 'headers' => [ 63 | 'X_REST_USERNAME' => 'admin@restuser', 64 | 'X_REST_PASSWORD' => 'admin@Access', 65 | ], 66 | ]; 67 | 68 | $request->addEvent('req.delete.testing.render', function($param1) { 69 | echo '{"test":"' . $param1 . '"}'; 70 | }); 71 | 72 | $request_response = $request->send(); 73 | $expected_response = '{"test":"1"}'; 74 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 75 | } 76 | 77 | /** 78 | * testDELETECustomRouteTowParamRequest 79 | * 80 | * tests that a DELETE request with custom route and two params 81 | * returns the correct response 82 | */ 83 | public function testDELETECustomRouteTwoParamRequest() 84 | { 85 | $request = new ERestTestRequestHelper(); 86 | 87 | $request['config'] = [ 88 | 'url' => 'http://api/user/testing/a/b', 89 | 'type' => 'DELETE', 90 | 'data' => '{"test":"data"}', 91 | 'headers' => [ 92 | 'X_REST_USERNAME' => 'admin@restuser', 93 | 'X_REST_PASSWORD' => 'admin@Access', 94 | ], 95 | ]; 96 | 97 | $request->addEvent('req.delete.testing.render', function($param1, $param2) { 98 | echo '{"test":"data", "param1":"' . $param1 . '", "param2":"' . $param2 . '"}'; 99 | }); 100 | 101 | $request_response = $request->send(); 102 | $expected_response = '{"test":"data", "param1":"a", "param2":"b"}'; 103 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 104 | } 105 | 106 | /** 107 | * testDELETECustomRouteTowParamPreFilterRequest 108 | * 109 | * tests that a DELETE request with custom route and two params and pre-filter 110 | * returns the correct response 111 | */ 112 | public function testDELETECustomRouteTwoParamPreFilterRequest() 113 | { 114 | $request = new ERestTestRequestHelper(); 115 | 116 | $request['config'] = [ 117 | 'url' => 'http://api/user/testing/1/2', 118 | 'type' => 'DELETE', 119 | 'data' => '{"test":"data"}', 120 | 'headers' => [ 121 | 'X_REST_USERNAME' => 'admin@restuser', 122 | 'X_REST_PASSWORD' => 'admin@Access', 123 | ], 124 | ]; 125 | 126 | $request->addEvent('req.delete.testing.render', function($param1, $param2) { 127 | echo '{"test":"data", "param1":"' . $param1 . '", "param2":"' . $param2 . '"}'; 128 | }); 129 | 130 | $request->addEvent('pre.filter.req.delete.testing.render', function($param1, $param2) { 131 | return [$param1+1, $param2+1]; 132 | }); 133 | 134 | $request_response = $request->send(); 135 | $expected_response = '{"test":"data", "param1":"2", "param2":"3"}'; 136 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 137 | } 138 | 139 | } 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/PUTCustomRouteUnitTest.php: -------------------------------------------------------------------------------- 1 | 'http://api/category/testing', 30 | 'type' => 'PUT', 31 | 'data' => '{"test":"data"}', 32 | 'headers' => [ 33 | 'X_REST_USERNAME' => 'admin@restuser', 34 | 'X_REST_PASSWORD' => 'admin@Access', 35 | ], 36 | ]; 37 | 38 | $request->addEvent('req.put.testing.render', function($data) { 39 | echo CJSON::encode($data); 40 | }); 41 | 42 | $request_response = $request->send(); 43 | $expected_response = '{"test":"data"}'; 44 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 45 | } 46 | 47 | 48 | /** 49 | * testPUTCustomRouteOneParamRequest 50 | * 51 | * tests that a PUT request with custom route and one param 52 | * returns the correct response 53 | */ 54 | public function testPUTCustomRouteOneParamRequest() 55 | { 56 | $request = new ERestTestRequestHelper(); 57 | 58 | $request['config'] = [ 59 | 'url' => 'http://api/post/testing/1', 60 | 'type' => 'PUT', 61 | 'data' => '{"test":"data"}', 62 | 'headers' => [ 63 | 'X_REST_USERNAME' => 'admin@restuser', 64 | 'X_REST_PASSWORD' => 'admin@Access', 65 | ], 66 | ]; 67 | 68 | $request->addEvent('req.put.testing.render', function($data, $param1) { 69 | $data['test'] = $param1; 70 | echo CJSON::encode($data); 71 | }); 72 | 73 | $request_response = $request->send(); 74 | $expected_response = '{"test":"1"}'; 75 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 76 | } 77 | 78 | /** 79 | * testPUTCustomRouteTowParamRequest 80 | * 81 | * tests that a PUT request with custom route and two params 82 | * returns the correct response 83 | */ 84 | public function testPUTCustomRouteTwoParamRequest() 85 | { 86 | $request = new ERestTestRequestHelper(); 87 | 88 | $request['config'] = [ 89 | 'url' => 'http://api/user/testing/a/b', 90 | 'type' => 'PUT', 91 | 'data' => '{"test":"data"}', 92 | 'headers' => [ 93 | 'X_REST_USERNAME' => 'admin@restuser', 94 | 'X_REST_PASSWORD' => 'admin@Access', 95 | ], 96 | ]; 97 | 98 | $request->addEvent('req.put.testing.render', function($data, $param1, $param2) { 99 | $data['param1'] = $param1; 100 | $data['param2'] = $param2; 101 | echo CJSON::encode($data); 102 | }); 103 | 104 | $request_response = $request->send(); 105 | $expected_response = '{"test":"data", "param1":"a", "param2":"b"}'; 106 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 107 | } 108 | 109 | /** 110 | * testPUTCustomRouteTowParamPreFilterRequest 111 | * 112 | * tests that a PUT request with custom route and two params and pre-filter 113 | * returns the correct response 114 | */ 115 | public function testPUTCustomRouteTwoParamPreFilterRequest() 116 | { 117 | $request = new ERestTestRequestHelper(); 118 | 119 | $request['config'] = [ 120 | 'url' => 'http://api/user/testing/1/2', 121 | 'type' => 'PUT', 122 | 'data' => '{"test":"data"}', 123 | 'headers' => [ 124 | 'X_REST_USERNAME' => 'admin@restuser', 125 | 'X_REST_PASSWORD' => 'admin@Access', 126 | ], 127 | ]; 128 | 129 | $request->addEvent('req.put.testing.render', function($data, $param1, $param2) { 130 | $data['param1'] = $param1; 131 | $data['param2'] = $param2; 132 | echo CJSON::encode($data); 133 | }); 134 | 135 | $request->addEvent('pre.filter.req.put.testing.render', function($data, $param1, $param2) { 136 | return [$data, $param1+1, $param2+1]; 137 | }); 138 | 139 | $request_response = $request->send(); 140 | $expected_response = '{"test":"data", "param1":"2", "param2":"3"}'; 141 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 142 | } 143 | 144 | } 145 | 146 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/POSTCustomRouteUnitTest.php: -------------------------------------------------------------------------------- 1 | 'http://api/category/testing', 30 | 'type' => 'POST', 31 | 'data' => '{"test":"data"}', 32 | 'headers' => [ 33 | 'X_REST_USERNAME' => 'admin@restuser', 34 | 'X_REST_PASSWORD' => 'admin@Access', 35 | ], 36 | ]; 37 | 38 | $request->addEvent('req.post.testing.render', function($data) { 39 | echo CJSON::encode($data); 40 | }); 41 | 42 | $request_response = $request->send(); 43 | $expected_response = '{"test":"data"}'; 44 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 45 | } 46 | 47 | 48 | /** 49 | * testPOSTCustomRouteOneParamRequest 50 | * 51 | * tests that a POST request with custom route and one param 52 | * returns the correct response 53 | */ 54 | public function testPOSTCustomRouteOneParamRequest() 55 | { 56 | $request = new ERestTestRequestHelper(); 57 | 58 | $request['config'] = [ 59 | 'url' => 'http://api/post/testing/1', 60 | 'type' => 'POST', 61 | 'data' => '{"test":"data"}', 62 | 'headers' => [ 63 | 'X_REST_USERNAME' => 'admin@restuser', 64 | 'X_REST_PASSWORD' => 'admin@Access', 65 | ], 66 | ]; 67 | 68 | $request->addEvent('req.post.testing.render', function($data, $param1) { 69 | $data['test'] = $param1; 70 | echo CJSON::encode($data); 71 | }); 72 | 73 | $request_response = $request->send(); 74 | $expected_response = '{"test":"1"}'; 75 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 76 | } 77 | 78 | /** 79 | * testPOSTCustomRouteTowParamRequest 80 | * 81 | * tests that a POST request with custom route and two params 82 | * returns the correct response 83 | */ 84 | public function testPOSTCustomRouteTwoParamRequest() 85 | { 86 | $request = new ERestTestRequestHelper(); 87 | 88 | $request['config'] = [ 89 | 'url' => 'http://api/user/testing/a/b', 90 | 'type' => 'POST', 91 | 'data' => '{"test":"data"}', 92 | 'headers' => [ 93 | 'X_REST_USERNAME' => 'admin@restuser', 94 | 'X_REST_PASSWORD' => 'admin@Access', 95 | ], 96 | ]; 97 | 98 | $request->addEvent('req.post.testing.render', function($data, $param1, $param2) { 99 | $data['param1'] = $param1; 100 | $data['param2'] = $param2; 101 | echo CJSON::encode($data); 102 | }); 103 | 104 | $request_response = $request->send(); 105 | $expected_response = '{"test":"data", "param1":"a", "param2":"b"}'; 106 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 107 | } 108 | 109 | /** 110 | * testPOSTCustomRouteTowParamPreFilterRequest 111 | * 112 | * tests that a POST request with custom route and two params and pre-filter 113 | * returns the correct response 114 | */ 115 | public function testPOSTCustomRouteTwoParamPreFilterRequest() 116 | { 117 | $request = new ERestTestRequestHelper(); 118 | 119 | $request['config'] = [ 120 | 'url' => 'http://api/user/testing/1/2', 121 | 'type' => 'POST', 122 | 'data' => '{"test":"data"}', 123 | 'headers' => [ 124 | 'X_REST_USERNAME' => 'admin@restuser', 125 | 'X_REST_PASSWORD' => 'admin@Access', 126 | ], 127 | ]; 128 | 129 | $request->addEvent('req.post.testing.render', function($data, $param1, $param2) { 130 | $data['param1'] = $param1; 131 | $data['param2'] = $param2; 132 | echo CJSON::encode($data); 133 | }); 134 | 135 | $request->addEvent('pre.filter.req.post.testing.render', function($data, $param1, $param2) { 136 | return [$data, $param1+1, $param2+1]; 137 | }); 138 | 139 | $request_response = $request->send(); 140 | $expected_response = '{"test":"data", "param1":"2", "param2":"3"}'; 141 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 142 | } 143 | 144 | } 145 | 146 | 147 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/migrations/ERestTestMigration.php: -------------------------------------------------------------------------------- 1 | getDbConnection()->getSchema(); 7 | $schema->checkIntegrity($check); 8 | } 9 | 10 | 11 | public function up() 12 | { 13 | $this->checkIntegrity(false); 14 | ob_start(); 15 | try { 16 | $this->createTable('tbl_user', array( 17 | 'id'=>'pk', 18 | 'username'=>'string', 19 | 'password'=>'string', 20 | 'email'=>'string', 21 | )); 22 | } catch(Exception $e) { 23 | $this->truncateTable("tbl_user"); 24 | } 25 | 26 | try { 27 | $this->createTable('tbl_profile', array( 28 | 'id'=>'pk', 29 | 'user_id'=>'INT(11)', 30 | 'photo'=>'binary', 31 | 'website'=>'string', 32 | 'FOREIGN KEY (user_id) REFERENCES tbl_user(id) ON DELETE CASCADE ON UPDATE CASCADE', 33 | )); 34 | } catch(Exception $e) { 35 | $this->truncateTable("tbl_profile"); 36 | } 37 | 38 | try { 39 | $this->createTable('tbl_category', array( 40 | 'id'=>'pk', 41 | 'name'=>'string', 42 | )); 43 | } catch(Exception $e) { 44 | $this->truncateTable("tbl_category"); 45 | } 46 | 47 | try { 48 | $this->createTable('tbl_post', array( 49 | 'id'=>'pk', 50 | 'title'=>'string', 51 | 'content'=>'text', 52 | 'create_time'=>'timestamp', 53 | 'author_id'=>'integer', 54 | 'FOREIGN KEY (author_id) REFERENCES tbl_user(id) ON DELETE CASCADE ON UPDATE CASCADE', 55 | )); 56 | } catch(Exception $e) { 57 | $this->truncateTable("tbl_post"); 58 | } 59 | 60 | try { 61 | $this->createTable('tbl_post_category', array( 62 | 'post_id'=>'integer', 63 | 'category_id'=>'integer', 64 | 'post_order'=>'integer', // added this row to test additional attributes added to a relation 65 | 'PRIMARY KEY(post_id, category_id)', 66 | 'FOREIGN KEY (post_id) REFERENCES tbl_post(id) ON DELETE CASCADE ON UPDATE CASCADE', 67 | 'FOREIGN KEY (category_id) REFERENCES tbl_category(id) ON DELETE CASCADE ON UPDATE CASCADE', 68 | )); 69 | } catch(Exception $e) { 70 | $this->truncateTable("tbl_post_category"); 71 | } 72 | 73 | try { 74 | $this->createTable('tbl_binary', array( 75 | 'id'=>'pk', 76 | 'name'=>'BINARY(16) NOT NULL', 77 | )); 78 | } catch(Exception $e) { 79 | $this->truncateTable("tbl_binary"); 80 | } 81 | 82 | $this->execute(" 83 | INSERT INTO tbl_user 84 | VALUES 85 | (NULL, 'username1', 'password1', 'email@email1.com'), 86 | (NULL, 'username2', 'password2', 'email@email2.com'), 87 | (NULL, 'username3', 'password3', 'email@email3.com'), 88 | (NULL, 'username4', 'password4', 'email@email4.com'), 89 | (NULL, 'username5', 'password5', 'email@email5.com'), 90 | (NULL, 'username6', 'password6', 'email@email6.com') 91 | "); 92 | $this->execute(" 93 | INSERT INTO tbl_profile 94 | VALUES 95 | (NULL, 1, 1, 'mysite1.com'), 96 | (NULL, 2, 0, 'mysite2.com'), 97 | (NULL, 3, 1, 'mysite3.com'), 98 | (NULL, 4, 0, 'mysite4.com'), 99 | (NULL, 5, 1, 'mysite5.com'), 100 | (NULL, 6, 0, 'mysite6.com') 101 | "); 102 | $this->execute(" 103 | INSERT INTO tbl_category 104 | VALUES 105 | (NULL, 'cat1'), 106 | (NULL, 'cat2'), 107 | (NULL, 'cat3'), 108 | (NULL, 'cat4'), 109 | (NULL, 'cat5'), 110 | (NULL, 'cat6') 111 | "); 112 | $this->execute(" 113 | INSERT INTO tbl_post 114 | VALUES 115 | (NULL, 'title1', 'content1', '2013-08-07 10:09:41', 1), 116 | (NULL, 'title2', 'content2', '2013-08-07 10:09:42', 2), 117 | (NULL, 'title3', 'content3', '2013-08-07 10:09:43', 3), 118 | (NULL, 'title4', 'content4', '2013-08-07 10:09:44', 4), 119 | (NULL, 'title5', 'content5', '2013-08-07 10:09:45', 5), 120 | (NULL, 'title6', 'content6', '2013-08-07 10:09:46', 6) 121 | "); 122 | $this->execute(" 123 | INSERT INTO tbl_post_category 124 | VALUES 125 | (1, 1, 1), 126 | (2, 2, 1), 127 | (3, 3, 1), 128 | (4, 4, 1), 129 | (5, 5, 1), 130 | (6, 6, 1), 131 | (1, 2, 2) 132 | "); 133 | $this->checkIntegrity(true); 134 | $this->execute(" 135 | INSERT INTO tbl_binary 136 | VALUES 137 | (1, UNHEX('DE46C83E5A50CED70E6A525A7BE6D709')) 138 | "); 139 | ob_end_clean(); 140 | } 141 | 142 | public function down() 143 | { 144 | $this->checkIntegrity(false); 145 | ob_start(); 146 | try { 147 | $this->dropTable('tbl_post_category'); 148 | $this->dropTable('tbl_category'); 149 | $this->dropTable('tbl_post'); 150 | $this->dropTable('tbl_profile'); 151 | $this->dropTable('tbl_user'); 152 | $this->dropTable('tbl_binary'); 153 | } catch(Exception $e) { 154 | //Nothing to do... 155 | } 156 | ob_end_clean(); 157 | $this->checkIntegrity(true); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /starship/RestfullYii/components/ERestResourceHelper.php: -------------------------------------------------------------------------------- 1 | setEmitter($emitter); 32 | } 33 | 34 | /** 35 | * setEmitter 36 | * 37 | * sets the emitter property 38 | * 39 | * @param (Callable) (emitter) the emitter callback 40 | */ 41 | public function setEmitter(Callable $emitter) 42 | { 43 | $this->emitter = $emitter; 44 | } 45 | 46 | /** 47 | * getEmitter 48 | * 49 | * gets the emitter callback 50 | * 51 | * @return (Callable) (emitter) the emitter callback 52 | */ 53 | public function getEmitter() 54 | { 55 | return $this->emitter; 56 | } 57 | 58 | /** 59 | * prepareRestModel 60 | * 61 | * gets the model associated with the REST request ready for output 62 | * 63 | * @param (Mixed/Int) (id) the id of the model 64 | * @param (Bool) (count) if true then the count is returned; if false then the model is returned 65 | * 66 | * @return (Mixed) prepared model or count of models 67 | */ 68 | public function prepareRestModel($id=null, $count=false) 69 | { 70 | $emitRest = $this->getEmitter(); 71 | 72 | $model = $emitRest(ERestEvent::MODEL_INSTANCE); 73 | $model = $emitRest(ERestEvent::MODEL_ATTACH_BEHAVIORS, $model); 74 | 75 | $scenario = $emitRest(ERestEvent::MODEL_SCENARIO); 76 | if(!is_null($scenario) && $scenario !== false) { 77 | $model->scenario = $scenario; 78 | } 79 | 80 | if($emitRest(ERestEvent::MODEL_LAZY_LOAD_RELATIONS) === false) { 81 | $model = $this->applyScope(ERestEvent::MODEL_WITH_RELATIONS, $model, 'with', true); 82 | } 83 | 84 | if(!empty($id)) { 85 | $model_found = $emitRest(ERestEvent::MODEL_FIND, [$model, $id]); 86 | if(is_null($model_found)) { 87 | throw new CHttpException(404, "RESOURCE '$id' NOT FOUND"); 88 | } 89 | return ($count)? 1: $model_found; 90 | } 91 | 92 | $model = $this->applyScope(ERestEvent::MODEL_FILTER, $model, 'filter', false); 93 | $model = $this->applyScope(ERestEvent::MODEL_SORT, $model, 'orderBy', false); 94 | 95 | if($count) { 96 | return $emitRest(ERestEvent::MODEL_COUNT, $model); 97 | } 98 | 99 | $model = $this->applyScope(ERestEvent::MODEL_LIMIT, $model, 'limit', false); 100 | $model = $this->applyScope(ERestEvent::MODEL_OFFSET, $model, 'offset', false); 101 | 102 | return $emitRest(ERestEvent::MODEL_FIND_ALL, $model); 103 | } 104 | 105 | /** 106 | * applyScope 107 | * 108 | * helper fo prepareRestModel 109 | * sets model scopes 110 | * 111 | * @param (String) (event) the name of the event 112 | * @param (Object) (model) an AR model object 113 | * @param (String) (scope_name) the name of the scope to apply 114 | * @param (Bool) (pass_model) true to pass model into the event 115 | * 116 | * @return (Object) (model) returns the AR model object with scope applied 117 | */ 118 | private function applyScope($event, $model, $scope_name, $pass_model=false) 119 | { 120 | $emitRest = $this->getEmitter(); 121 | 122 | if(!$pass_model) { 123 | $scope_params = $emitRest($event); 124 | } else { 125 | $scope_params = $emitRest($event, $model); 126 | } 127 | if(!is_null($scope_params) && $scope_params !== false) { 128 | return $model->$scope_name($scope_params); 129 | } 130 | return $model; 131 | } 132 | 133 | 134 | /** 135 | * setModelAttributes 136 | * 137 | * sets an AR models properties to the data in the request 138 | * 139 | * @param (Object) (model) AR model 140 | * @param (Array) (data) data to be applied to the AR model 141 | * @param (Array) (restricted_properties) list of properties not to allow setting of 142 | * 143 | * @return (Object) AR model 144 | */ 145 | public function setModelAttributes($model, $data, $restricted_properties) 146 | { 147 | foreach($data as $var=>$value) { 148 | if(($model->hasAttribute($var) || isset($model->metadata->relations[$var])) && !in_array($var, $restricted_properties)) { 149 | $model->$var = $value; 150 | } 151 | else { 152 | throw new CHttpException(406, 'Parameter \'' . $var . '\' is not allowed for model (' . get_class($model) . ')'); 153 | } 154 | } 155 | return $model; 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/EActionRestPUTUnitTest.php: -------------------------------------------------------------------------------- 1 | getController()->Category; 28 | $controller->attachBehaviors(array( 29 | 'class'=>'RestfullYii.behaviors.ERestBehavior' 30 | )); 31 | $controller->injectEvents('req.put.my_custom_route.render', function($data, $param1='', $param2='') { 32 | echo "My Custom Route" . $param1 . $param2 . '_' . implode('_', $data); 33 | }); 34 | $controller->injectEvents('req.data.read', function() { 35 | return [ 36 | 'id' => '1', 37 | 'name' => 'cat-updated', 38 | ]; 39 | }); 40 | 41 | $controller->ERestInit(); 42 | $this->putAction = new EActionRestPUT($controller, 'REST.PUT'); 43 | } 44 | 45 | /** 46 | * run 47 | * 48 | * tests EActionRestPUT->run() 49 | */ 50 | public function testRunRESOURCES() 51 | { 52 | $result = $this->captureOB($this, function() { 53 | $this->putAction->run(); 54 | }); 55 | $this->assertInstanceOf('Exception', $result); 56 | $this->assertExceptionHasMessage('Method Not Allowed', $result); 57 | } 58 | 59 | /** 60 | * run 61 | * 62 | * tests EActionRestPUT->run('my_custom_route') 63 | */ 64 | public function testRunCUSTOM() 65 | { 66 | $result = $this->captureOB($this, function() { 67 | $this->putAction->run('my_custom_route'); 68 | }); 69 | $this->assertEquals($result, 'My Custom Route_1_cat-updated'); 70 | 71 | $result = $this->captureOB($this, function() { 72 | $this->putAction->run('my_custom_route', '_p1'); 73 | }); 74 | $this->assertEquals($result, 'My Custom Route_p1_1_cat-updated'); 75 | 76 | $result = $this->captureOB($this, function() { 77 | $this->putAction->run('my_custom_route', '_p1', '_p2'); 78 | }); 79 | $this->assertEquals($result, 'My Custom Route_p1_p2_1_cat-updated'); 80 | } 81 | 82 | /** 83 | * run 84 | * 85 | * tests EActionRestPUT->run(1, 'posts') 86 | */ 87 | public function testRunSUBRESOURCES() 88 | { 89 | $result = $this->captureOB($this, function() { 90 | $this->putAction->run(1, 'posts'); 91 | }); 92 | $this->assertInstanceOf('Exception', $result); 93 | $this->assertExceptionHasMessage('Method Not Allowed', $result); 94 | } 95 | 96 | /** 97 | * run 98 | * 99 | * tests EActionRestPUT->run(1, 'posts', 1) 100 | */ 101 | public function testSubresource() 102 | { 103 | $result = $this->captureOB($this, function() { 104 | $this->putAction->run(1, 'posts', 2); 105 | }); 106 | $this->assertJSONFormat($result); 107 | $this->assertJsonStringEqualsJsonString( 108 | $result, 109 | '{"success":true,"message":"Subresource Added","data":{"totalCount":"1","category":{"id":"1","name":"cat1","posts":[{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1"},{"id":"2","title":"title2","content":"content2","create_time":"2013-08-07 10:09:42","author_id":"2"}]}}}' 110 | ); 111 | } 112 | 113 | /** 114 | * run 115 | * 116 | * tests EActionRestPUT->run(1) 117 | */ 118 | public function testRunRESOURCE() 119 | { 120 | $result = $this->captureOB($this, function() { 121 | $this->putAction->run(1); 122 | }); 123 | $this->assertJSONFormat($result); 124 | $this->assertJsonStringEqualsJsonString( 125 | $result, 126 | '{"success":true,"message":"Record Updated","data":{"totalCount":"1","category":{"id":"1","name":"cat-updated","posts":[{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1"}]}}}' 127 | ); 128 | } 129 | 130 | /** 131 | * run 132 | * 133 | * tests EActionRestPUT->run('WHAT-THE-RESOURCE') 134 | */ 135 | public function testRunResourceNotFound() 136 | { 137 | $result = $this->captureOB($this, function() { 138 | $this->putAction->run('WHAT-THE-RESOURCE'); 139 | }); 140 | $this->assertInstanceOf('Exception', $result); 141 | $this->assertExceptionHasMessage('Resource Not Found', $result); 142 | } 143 | 144 | /** 145 | * handlePut 146 | * 147 | * test EActionRestPUT->handlePut() 148 | */ 149 | public function testHandlePut() 150 | { 151 | $new_model = $this->putAction->handlePut(1); 152 | $this->assertInstanceOf('Category', $new_model); 153 | $this->assertEquals($new_model->id, 1); 154 | } 155 | 156 | /** 157 | * handlePutSubresource 158 | * 159 | * test EActionRestPUT->handlePutSubresource(1, 'posts', 2) 160 | */ 161 | public function testHandlePutSubresource() 162 | { 163 | $new_model = $this->putAction->handlePutSubresource(1, 'posts', 2); 164 | $this->assertInstanceOf('Category', $new_model); 165 | $this->assertEquals($new_model->posts[1]->id, 2); 166 | } 167 | 168 | } 169 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/GETResourceVisibleHiddenPropertiesUnitTest.php: -------------------------------------------------------------------------------- 1 | addEvent('model.visible.properties', function() { 28 | return ['username', 'email']; 29 | }); 30 | 31 | $request->addEvent('model.with.relations', function() { 32 | return []; 33 | }); 34 | 35 | $request['config'] = [ 36 | 'url' => 'http://api/user/1', 37 | 'type' => 'GET', 38 | 'data' => null, 39 | 'headers' => [ 40 | 'X_REST_USERNAME' => 'admin@restuser', 41 | 'X_REST_PASSWORD' => 'admin@Access', 42 | ], 43 | ]; 44 | 45 | $request_response = $request->send(); 46 | $expected_response = '{"success":true,"message":"Record Found","data":{"totalCount":1,"user":{"username":"username1","email":"email@email1.com"}}}'; 47 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 48 | } 49 | 50 | /** 51 | * testGETResourcesHiddenProperties 52 | * 53 | * tests that a GET request for a list of 'User' resources 54 | * With exluded visible fields only 55 | * returns the correct response 56 | */ 57 | public function testGETResourceHiddenProperties() 58 | { 59 | $request = new ERestTestRequestHelper(); 60 | 61 | $request->addEvent('model.hidden.properties', function() { 62 | return ['password', 'id']; 63 | }); 64 | 65 | $request->addEvent('model.with.relations', function() { 66 | return []; 67 | }); 68 | 69 | $request['config'] = [ 70 | 'url' => 'http://api/user/1', 71 | 'type' => 'GET', 72 | 'data' => null, 73 | 'headers' => [ 74 | 'X_REST_USERNAME' => 'admin@restuser', 75 | 'X_REST_PASSWORD' => 'admin@Access', 76 | ], 77 | ]; 78 | 79 | $request_response = $request->send(); 80 | $expected_response = '{"success":true,"message":"Record Found","data":{"totalCount":1,"user":{"username":"username1","email":"email@email1.com"}}}'; 81 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 82 | } 83 | 84 | /** 85 | * testGETResourcesVisibleRelatedProperties 86 | * 87 | * tests that a GET request for a list of 'User' resources 88 | * With limited selected visible fields only 89 | * returns the correct response 90 | */ 91 | public function testGETResourceVisibleRelatedProperties() 92 | { 93 | $request = new ERestTestRequestHelper(); 94 | 95 | $request->addEvent('model.visible.properties', function() { 96 | return ['username', 'email', 'posts.id', '*.title', 'profile.website']; 97 | }); 98 | 99 | $request->addEvent('model.with.relations', function() { 100 | return ['posts', 'profile']; 101 | }); 102 | 103 | $request['config'] = [ 104 | 'url' => 'http://api/user/1', 105 | 'type' => 'GET', 106 | 'data' => null, 107 | 'headers' => [ 108 | 'X_REST_USERNAME' => 'admin@restuser', 109 | 'X_REST_PASSWORD' => 'admin@Access', 110 | ], 111 | ]; 112 | 113 | $request_response = $request->send(); 114 | $expected_response = '{"success":true,"message":"Record Found","data":{"totalCount":1,"user":{"username":"username1","email":"email@email1.com","posts":[{"id":"1","title":"title1"}],"profile":{"website":"mysite1.com"}}}}'; 115 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 116 | } 117 | 118 | /** 119 | * testGETResourcesHiddenRelatedProperties 120 | * 121 | * tests that a GET request for a list of 'User' resources 122 | * With exluded visible fields only 123 | * returns the correct response 124 | */ 125 | public function testGETResourceHiddenRelatedProperties() 126 | { 127 | $request = new ERestTestRequestHelper(); 128 | 129 | $request->addEvent('model.hidden.properties', function() { 130 | return ['password', 'id', '*.title', 'posts.id', '*.website']; 131 | }); 132 | 133 | $request->addEvent('model.with.relations', function() { 134 | return ['posts', 'profile']; 135 | }); 136 | 137 | $request['config'] = [ 138 | 'url' => 'http://api/user/1', 139 | 'type' => 'GET', 140 | 'data' => null, 141 | 'headers' => [ 142 | 'X_REST_USERNAME' => 'admin@restuser', 143 | 'X_REST_PASSWORD' => 'admin@Access', 144 | ], 145 | ]; 146 | 147 | $request_response = $request->send(); 148 | $expected_response = '{"success":true,"message":"Record Found","data":{"totalCount":1,"user":{"username":"username1","email":"email@email1.com","posts":[{"content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1"}],"profile":{"id":"1","user_id":"1","photo":"1"}}}}'; 149 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/EActionRestGETUnitTest.php: -------------------------------------------------------------------------------- 1 | getController()->Category; 28 | $controller->attachBehaviors(array( 29 | 'class'=>'RestfullYii.behaviors.ERestBehavior' 30 | )); 31 | $controller->injectEvents('req.get.my_custom_route.render', function($param1='', $param2='') { 32 | echo "My Custom Route" . $param1 . $param2; 33 | }); 34 | $controller->ERestInit(); 35 | $this->getAction = new EActionRestGET($controller, 'REST.GET'); 36 | } 37 | 38 | 39 | /** 40 | * run 41 | * 42 | * tests EActionRestGET->run() 43 | */ 44 | public function testRunRESOURCES() 45 | { 46 | $result = $this->captureOB($this, function() { 47 | $this->getAction->run(); 48 | }); 49 | $this->assertJSONFormat($result); 50 | $this->assertJsonStringEqualsJsonString( 51 | $result, 52 | '{"success":true,"message":"Record(s) Found","data":{"totalCount":"6","category":[{"id":"1","name":"cat1","posts":[{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1"}]},{"id":"2","name":"cat2","posts":[{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1"},{"id":"2","title":"title2","content":"content2","create_time":"2013-08-07 10:09:42","author_id":"2"}]},{"id":"3","name":"cat3","posts":[{"id":"3","title":"title3","content":"content3","create_time":"2013-08-07 10:09:43","author_id":"3"}]},{"id":"4","name":"cat4","posts":[{"id":"4","title":"title4","content":"content4","create_time":"2013-08-07 10:09:44","author_id":"4"}]},{"id":"5","name":"cat5","posts":[{"id":"5","title":"title5","content":"content5","create_time":"2013-08-07 10:09:45","author_id":"5"}]},{"id":"6","name":"cat6","posts":[{"id":"6","title":"title6","content":"content6","create_time":"2013-08-07 10:09:46","author_id":"6"}]}]}}' 53 | ); 54 | } 55 | 56 | /** 57 | * run 58 | * 59 | * tests EActionRestGET->run('my_custom_route') 60 | */ 61 | public function testRunCUSTOM() 62 | { 63 | $result = $this->captureOB($this, function() { 64 | $this->getAction->run('my_custom_route'); 65 | }); 66 | $this->assertEquals($result, 'My Custom Route'); 67 | 68 | $result = $this->captureOB($this, function() { 69 | $this->getAction->run('my_custom_route', '_p1'); 70 | }); 71 | $this->assertEquals($result, 'My Custom Route_p1'); 72 | 73 | $result = $this->captureOB($this, function() { 74 | $this->getAction->run('my_custom_route', '_p1', '_p2'); 75 | }); 76 | $this->assertEquals($result, 'My Custom Route_p1_p2'); 77 | } 78 | 79 | /** 80 | * run 81 | * 82 | * tests EActionRestGET->run(1, 'posts') 83 | */ 84 | public function testRunSUBRESOURCES() 85 | { 86 | $result = $this->captureOB($this, function() { 87 | $this->getAction->run(1, 'posts'); 88 | }); 89 | $this->assertJSONFormat($result); 90 | $this->assertJsonStringEqualsJsonString( 91 | $result, 92 | '{"success":true,"message":"Record(s) Found","data":{"totalCount":1,"post":[{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1"}]}}' 93 | ); 94 | } 95 | 96 | /** 97 | * run 98 | * 99 | * tests EActionRestGET->run(1, 'posts', 1) 100 | */ 101 | public function testRunSUBRESOURCE() 102 | { 103 | $result = $this->captureOB($this, function() { 104 | $this->getAction->run(1, 'posts', 1); 105 | }); 106 | $this->assertJSONFormat($result); 107 | 108 | $this->assertJsonStringEqualsJsonString( 109 | $result, 110 | '{"success":true,"message":"Record(s) Found","data":{"totalCount":1,"post":{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1"}}}' 111 | ); 112 | } 113 | 114 | /** 115 | * run 116 | * 117 | * tests EActionRestGET->run(1) 118 | */ 119 | public function testRunRESOURCE() 120 | { 121 | $result = $this->captureOB($this, function() { 122 | $this->getAction->run(1); 123 | }); 124 | $this->assertJSONFormat($result); 125 | $this->assertJsonStringEqualsJsonString( 126 | $result, 127 | '{"success":true,"message":"Record Found","data":{"totalCount":1,"category":{"id":"1","name":"cat1","posts":[{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1"}]}}}' 128 | ); 129 | } 130 | 131 | /** 132 | * run 133 | * 134 | * tests EActionRestGET->run('WHAT-THE-RESOURCE') 135 | */ 136 | public function testRunResourceNotFound() 137 | { 138 | $result = $this->captureOB($this, function() { 139 | $this->getAction->run('WHAT-THE-RESOURCE'); 140 | }); 141 | $this->assertInstanceOf('Exception', $result); 142 | $this->assertExceptionHasMessage('Resource Not Found', $result); 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /starship/RestfullYii/ARBehaviors/ERestActiveRecordRelationBehavior.php: -------------------------------------------------------------------------------- 1 | 'beforeSave', 28 | 'onAfterSave'=>'afterSave', 29 | ]; 30 | } 31 | 32 | /** 33 | * beforeSave 34 | * 35 | * Sets up the transaction and triggers relation parsing 36 | * 37 | * @param (Object) (event) the active record event 38 | * 39 | * @return (Bool) the result of calling the parent beforeSave($event) 40 | */ 41 | public function beforeSave($event) 42 | { 43 | // ensure transactions 44 | if ($this->useTransaction && $this->owner->dbConnection->currentTransaction===null) { 45 | $this->setTransaction($this->owner->dbConnection->beginTransaction()); 46 | } 47 | 48 | $this->preSaveHelper($this->owner); 49 | 50 | return parent::beforeSave($event); 51 | } 52 | 53 | /** 54 | * preSaveHelper 55 | * 56 | * Cleans Model attributes 57 | * Gets relations ready for save 58 | * 59 | * @param (Object) (model) takes an active record model 60 | * 61 | * @return (Object) returns the cleaned model 62 | */ 63 | public function preSaveHelper($model) 64 | { 65 | $attribute_cleaner = function($attributes) { 66 | array_walk($attributes, function(&$val, $attr) { 67 | if(is_bool($val) === true) { 68 | $val = (int) $val; 69 | } else if( $attr == 'id' && $val === 0) { 70 | $val = NULL; 71 | } 72 | }); 73 | return $attributes; 74 | }; 75 | 76 | $relation_helper = function($relation_name, $attributes) use ($attribute_cleaner, $model) { 77 | $relation_class_name = $model->metaData->relations[$relation_name]->className; 78 | 79 | $relation_model = new $relation_class_name(); 80 | $relation_model->attributes = $attribute_cleaner($attributes); 81 | $table = $relation_model->getMetaData()->tableSchema; 82 | if(is_string($table->primaryKey)) { 83 | if(isset($attribute_cleaner($attributes)[($table->primaryKey)])) { 84 | $relation_model->setPrimaryKey($attribute_cleaner($attributes)[($table->primaryKey)]); 85 | } 86 | } 87 | 88 | $relation_pk = $relation_model->getPrimaryKey(); 89 | 90 | if( !empty($relation_pk) ) { 91 | //$relation_model = $relation_model::model()->findByPk($relation_pk); 92 | $relation_model->setIsNewRecord(false); 93 | } 94 | 95 | if($this->getRelationType($model, $relation_name) == 'CHasManyRelation' || $this->getRelationType($model, $relation_name) == 'CHasOneRelation') { 96 | $relation_model->{$model->metaData->relations[$relation_name]->foreignKey} = $model->getPrimaryKey(); 97 | } 98 | 99 | if(!$relation_model->save()) { 100 | throw new CHttpException(500, 'Could not save Model: ' . get_class($relation_model) . ' : ' . CJSON::encode($relation_model->errors)); 101 | $relation_model->refresh(); 102 | } 103 | 104 | if($this->getRelationType($model, $relation_name) == 'CBelongsToRelation') { 105 | $belongs_to_fk = $model->metaData->relations[$relation_name]->foreignKey; 106 | if(empty($model->$belongs_to_fk)) { 107 | $model->$belongs_to_fk = $relation_model->getPrimaryKey(); 108 | } 109 | } 110 | 111 | return $relation_model; 112 | }; 113 | 114 | $model->attributes = $attribute_cleaner($model->attributes); 115 | 116 | foreach($model->metadata->relations as $key=>$value) 117 | { 118 | if ($model->hasRelated($key) && is_array($model->{$key})) { 119 | if( array_key_exists(0, $model->{$key}) ) { 120 | $relation_data = []; 121 | foreach($model->{$key} as $index=>$attributes) { 122 | if (!is_object($attributes)) { 123 | $relation_data[$index] = $relation_helper( 124 | $key, $attributes 125 | ); 126 | } else { 127 | $relation_data[$index] = $attributes; 128 | } 129 | } 130 | $model->{$key} = $relation_data; 131 | } else if(is_array($model->{$key})){ 132 | $model->$key = $relation_helper($key, $model->$key); 133 | } 134 | } 135 | } 136 | return $model; 137 | } 138 | 139 | /** 140 | * getRelationType 141 | * 142 | * Gets the type of a relation or returns false 143 | * 144 | * @param (Object) (model) active record model 145 | * @param (String) (key) the relation name 146 | * 147 | * @return (Mixed) returns the relation type (String) or false (Bool) 148 | */ 149 | private function getRelationType($model, $key) 150 | { 151 | $relations = $model->relations(); 152 | if(isset($relations[$key])) { 153 | return $relations[$key][0]; 154 | } 155 | return false; 156 | } 157 | 158 | } 159 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/ERestTestRequestHelper.php: -------------------------------------------------------------------------------- 1 | stream = fopen("php://temp", 'wb'); 26 | $stream = $this->stream; 27 | $this->container['events'] = [ 28 | [ 29 | ERestEvent::REQ_DATA_READ => function($notused=null) use ($stream) { 30 | $reader = new ERestRequestReader($stream); 31 | return CJSON::decode($reader->getContents()); 32 | } 33 | ] 34 | ]; 35 | $this->container['config'] = [ 36 | 'url' => null, 37 | 'type' => null, 38 | 'data' => null, 39 | 'headers' => [], 40 | ]; 41 | } 42 | public function offsetSet($offset, $value) 43 | { 44 | if (is_null($offset)) { 45 | $this->container[] = $value; 46 | } else { 47 | $this->container[$offset] = $value; 48 | } 49 | } 50 | 51 | public function offsetExists($offset) 52 | { 53 | return isset($this->container[$offset]); 54 | } 55 | 56 | public function offsetUnset($offset) 57 | { 58 | unset($this->container[$offset]); 59 | } 60 | 61 | public function offsetGet($offset) 62 | { 63 | return isset($this->container[$offset]) ? $this->container[$offset] : null; 64 | } 65 | 66 | public function addEvent($event, Callable $callback) 67 | { 68 | $this->container['events'][] = [$event => $callback]; 69 | } 70 | 71 | public function send() 72 | { 73 | //parse url 74 | if(!is_string($this->url)) { 75 | throw new CHttpException(500, 'You must set the url (string)'); 76 | } 77 | $url_info = parse_url($this->url); 78 | 79 | 80 | //Set the http type 81 | if(strtolower($url_info['scheme']) == 'https') { 82 | $_SERVER['HTTPS'] = 'on'; 83 | } 84 | 85 | //parse query string and set get variables 86 | if(isset($url_info['query'])) { 87 | parse_str($url_info['query'], $get_vars); 88 | foreach($get_vars as $get_var=>$value) 89 | { 90 | $_GET[$get_var] = $value; 91 | } 92 | } 93 | 94 | //instance the controller indicated by the url and apply events 95 | $path_parts = explode('/', ltrim($url_info['path'], '/')); 96 | $controller_name = ucfirst($path_parts[0]) . 'Controller'; 97 | $controller = new $controller_name(ucfirst($path_parts[0])); 98 | $this->applyEvents($controller); 99 | 100 | 101 | //set the params to be passed to the controllers action 102 | $id = isset($path_parts[1])? $path_parts[1]: null; 103 | $param1 = isset($path_parts[2])? $path_parts[2]: null; 104 | $param2 = isset($path_parts[3])? $path_parts[3]: null; 105 | 106 | //set the action to run based on the config request type 107 | switch (strtolower($this->type)) { 108 | case 'get': 109 | $action = 'REST.GET'; 110 | break; 111 | case 'post': 112 | $action = 'REST.POST'; 113 | break; 114 | case 'put': 115 | $action = 'REST.PUT'; 116 | break; 117 | case 'delete': 118 | $action = 'REST.DELETE'; 119 | break; 120 | case 'options': 121 | $action = 'REST.OPTIONS'; 122 | break; 123 | default: 124 | $action = 'REST.GET'; 125 | break; 126 | } 127 | 128 | $action = $controller->createAction($action); 129 | 130 | //write data set in the request config 131 | $this->writeRequestData($this->data); 132 | 133 | //set header vars set in the request config 134 | foreach($this->headers as $header=>$value) { 135 | $_SERVER['HTTP_' . $header] = $value; 136 | //echo $header . ":" . $value . "\n"; 137 | } 138 | 139 | //Run the controller action and return the response 140 | return $this->sendRequest($controller, $action, $id, $param1, $param2); 141 | } 142 | 143 | public function sendRequest($controller, $action, $id, $param1, $param2) 144 | { 145 | $_GET['id'] = $id; 146 | $_GET['param1'] = $param1; 147 | $_GET['param2'] = $param2; 148 | 149 | ob_start(); 150 | try { 151 | $controller->runActionWithFilters($action, $controller->filters()); 152 | $output = ob_get_contents(); 153 | } catch (Exception $e) { 154 | $output = $e; 155 | } 156 | if (ob_get_length() > 0 ) { @ob_end_clean(); } 157 | 158 | return $output; 159 | } 160 | 161 | public function writeRequestData($data) 162 | { 163 | if(!is_null($data)) { 164 | fputs($this->stream, $data); 165 | } 166 | } 167 | 168 | public function applyEvents(&$controller) 169 | { 170 | foreach($this->container['events'] as $event) { 171 | list($event_name, $callback) = each($event); 172 | call_user_func_array([$controller, 'injectEvents'], [$event_name, $callback]); 173 | } 174 | } 175 | 176 | public function __get($name) 177 | { 178 | if(array_key_exists($name, $this->container)) { 179 | return $this->container[$name]; 180 | } 181 | if(array_key_exists($name, $this->container['config'])) { 182 | return $this->container['config'][$name]; 183 | } 184 | if(array_key_exists($name, $this->container['events'])) { 185 | return $this->container['events'][$name]; 186 | } 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/EActionRestDELETEUnitTest.php: -------------------------------------------------------------------------------- 1 | getController()->Category; 28 | $controller->attachBehaviors(array( 29 | 'class'=>'RestfullYii.behaviors.ERestBehavior' 30 | )); 31 | $controller->injectEvents('req.delete.my_custom_route.render', function($param1='', $param2='') { 32 | echo "My Custom Route" . $param1 . $param2; 33 | }); 34 | $controller->ERestInit(); 35 | $this->deleteAction = new EActionRestDELETE($controller, 'REST.DELETE'); 36 | } 37 | 38 | /** 39 | * run 40 | * 41 | * tests EActionRestDELETE->run() 42 | */ 43 | public function testRunRESOURCES() 44 | { 45 | $result = $this->captureOB($this, function() { 46 | $this->deleteAction->run(); 47 | }); 48 | $this->assertInstanceOf('Exception', $result); 49 | $this->assertExceptionHasMessage('Method Not Allowed', $result); 50 | } 51 | 52 | 53 | /** 54 | * run 55 | * 56 | * tests EActionRestDELETE->run(1, 'posts') 57 | */ 58 | public function testRunSUBRESOURCES() 59 | { 60 | $result = $this->captureOB($this, function() { 61 | $this->deleteAction->run(1, 'posts'); 62 | }); 63 | $this->assertInstanceOf('Exception', $result); 64 | $this->assertExceptionHasMessage('Method Not Allowed', $result); 65 | } 66 | 67 | 68 | /** 69 | * run 70 | * 71 | * tests EActionRestDELETE->run(1, 'posts', 1) 72 | */ 73 | public function testRunSUBRESOURCE() 74 | { 75 | $result = $this->captureOB($this, function() { 76 | $this->deleteAction->run(1, 'posts', 1); 77 | }); 78 | 79 | $this->assertJSONFormat($result); 80 | $result = CJSON::decode($result); 81 | $this->assertEquals($result['success'], true); 82 | $this->assertEquals($result['message'], 'Sub-Resource Deleted'); 83 | $this->assertEquals($result['data']['totalCount'], '1'); 84 | $this->assertArrayHasKey('category', $result['data']); 85 | $this->assertArrayHasKey('id', $result['data']['category']); 86 | $this->assertEquals($result['data']['category']['id'], 1); 87 | $this->assertArrayHasKey('posts', $result['data']['category']); 88 | $this->assertEquals( $result['data']['category']['posts'], []); 89 | } 90 | 91 | 92 | /** 93 | * run 94 | * 95 | * tests EActionRestDELETE->run('my_custom_route') 96 | */ 97 | public function testRunCUSTOM() 98 | { 99 | $result = $this->captureOB($this, function() { 100 | $this->deleteAction->run('my_custom_route'); 101 | }); 102 | $this->assertEquals($result, 'My Custom Route'); 103 | 104 | $result = $this->captureOB($this, function() { 105 | $this->deleteAction->run('my_custom_route', '_p1'); 106 | }); 107 | $this->assertEquals($result, 'My Custom Route_p1'); 108 | 109 | $result = $this->captureOB($this, function() { 110 | $this->deleteAction->run('my_custom_route', '_p1', '_p2'); 111 | }); 112 | $this->assertEquals($result, 'My Custom Route_p1_p2'); 113 | } 114 | 115 | /** 116 | * run 117 | * 118 | * tests EActionRestDELETE->run(1) 119 | */ 120 | public function testRunRESOURCE() 121 | { 122 | $result = $this->captureOB($this, function() { 123 | $this->deleteAction->run(1); 124 | }); 125 | $this->assertJSONFormat($result); 126 | $result = CJSON::decode($result); 127 | $this->assertEquals($result['success'], true); 128 | $this->assertEquals($result['message'], 'Record Deleted'); 129 | $this->assertEquals($result['data']['totalCount'], '1'); 130 | $this->assertArrayHasKey('category', $result['data']); 131 | $this->assertArrayHasKey('id', $result['data']['category']); 132 | $this->assertEquals($result['data']['category']['id'], 1); 133 | } 134 | 135 | /** 136 | * run 137 | * 138 | * tests EActionRestDELETE->run('WHAT-THE-RESOURCE') 139 | */ 140 | public function testRunResourceNotFound() 141 | { 142 | $result = $this->captureOB($this, function() { 143 | $this->deleteAction->run('WHAT-THE-RESOURCE'); 144 | }); 145 | $this->assertInstanceOf('Exception', $result); 146 | $this->assertExceptionHasMessage('Resource Not Found', $result); 147 | } 148 | 149 | /** 150 | * handleDelete 151 | * 152 | * Tests EActionRestDELETE->handleDelete(1) 153 | */ 154 | public function testHandleDelete() 155 | { 156 | $model = $this->deleteAction->handleDelete(1); 157 | $this->assertInstanceOf('Category', $model); 158 | $deleted_model = Category::model()->findByPk(1); 159 | $this->assertEquals($deleted_model, null); 160 | } 161 | 162 | /** 163 | * handleSubresourceDelete 164 | * 165 | * Tests EActionRestDELETE->handleSubresourceDelete(1, 'posts', 1) 166 | */ 167 | public function testHandleSubresourceDelete() 168 | { 169 | $model = $this->deleteAction->handleSubresourceDelete(1, 'posts', 1); 170 | $this->assertInstanceOf('Category', $model); 171 | $deleted_model = Category::model()->findByPk(1); 172 | $this->assertEquals($deleted_model->posts, []); 173 | } 174 | 175 | 176 | 177 | } 178 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/ERestBaseActionUnitTest.php: -------------------------------------------------------------------------------- 1 | getController()->Category; 26 | $controller->attachBehaviors(array( 27 | 'class'=>'RestfullYii.behaviors.ERestBehavior' 28 | )); 29 | $controller->injectEvents('req.get.my_custom_route.render', function($param1=null, $param2=null) { 30 | echo "My Custom Route"; 31 | }); 32 | $controller->ERestInit(); 33 | $this->baseAction = new ERestBaseAction($controller, 'REST.GET'); 34 | } 35 | 36 | /** 37 | * testRequestType 38 | * 39 | * Test for ERestBaseAction->requestType() 40 | */ 41 | public function testRequestType() 42 | { 43 | $this->assertEquals($this->baseAction->getRequestActionType(null, null, null, 'get'), 'RESOURCES'); 44 | $this->assertEquals($this->baseAction->getRequestActionType('my_custom_route', null, null, 'get'), 'CUSTOM'); 45 | $this->assertEquals($this->baseAction->getRequestActionType('my_custom_route', 1, null, 'get'), 'CUSTOM'); 46 | $this->assertEquals($this->baseAction->getRequestActionType('my_custom_route', 1, 2, 'get'), 'CUSTOM'); 47 | $this->assertEquals($this->baseAction->getRequestActionType(1, 'posts', null, 'get'), 'SUBRESOURCES'); 48 | $this->assertEquals($this->baseAction->getRequestActionType(1, 'posts', 1, 'get'), 'SUBRESOURCE'); 49 | $this->assertEquals($this->baseAction->getRequestActionType(1, null, null, 'get'), 'RESOURCE'); 50 | } 51 | 52 | /** 53 | * testFinalRender 54 | * 55 | * Test for ERestBaseAction->finalRender() 56 | */ 57 | public function testFinalRender() 58 | { 59 | $data_json = CJSON::encode(['one'=>1, 'two'=>2]); 60 | 61 | $result = $this->captureOB($this->baseAction, function() use ($data_json) { 62 | $this->finalRender(function($v, $h) use($data_json) { 63 | return $data_json; 64 | }); 65 | }); 66 | 67 | $this->assertJsonStringEqualsJsonString($data_json, $result); 68 | } 69 | 70 | /** 71 | * testGetModel 72 | * 73 | * Test for ERestBaseAction->getModel() 74 | */ 75 | public function testGetModel() 76 | { 77 | $this->assertInstanceOf('Category', $this->baseAction->getModel(null, true)); 78 | $this->assertInstanceOf('Category', $this->baseAction->getModel(1, false)); 79 | $this->assertEquals(1, $this->baseAction->getModel(1, false)->id); 80 | $this->assertNotEquals(1, $this->baseAction->getModel(1, true)->id); 81 | } 82 | 83 | /** 84 | * testGetModelCount 85 | * 86 | * Test for ERestBaseAction->getModelCount() 87 | */ 88 | public function testGetModelCount() 89 | { 90 | $category = new Category(); 91 | $count = $category->count(); 92 | $this->assertEquals($count, $this->baseAction->getModelCount(null)); 93 | $this->assertEquals(1, $this->baseAction->getModelCount(1)); 94 | } 95 | 96 | /** 97 | * testGetRelations 98 | * 99 | * Test for ERestBaseAction->getRelations() 100 | */ 101 | public function testGetRelations() 102 | { 103 | $relations = $this->baseAction->getRelations(); 104 | 105 | $model = new Category(); 106 | $nestedRelations = []; 107 | foreach($model->metadata->relations as $rel=>$val) 108 | { 109 | $className = $val->className; 110 | $rel_model = call_user_func([$className, 'model']); 111 | if(!is_array($rel_model->tableSchema->primaryKey) && substr($rel, 0, 1) != '_') { 112 | $this->assertContains($rel, $relations); 113 | $nestedRelations[] = $rel; 114 | } 115 | } 116 | $this->assertArraysEqual($nestedRelations, $relations); 117 | } 118 | 119 | /** 120 | * testGetSubresourceCount 121 | * 122 | * Test for ERestBaseAction->getSubresourceCount() 123 | */ 124 | public function testGetSubresourceCount() 125 | { 126 | foreach(Category::model()->findAll() as $cat) 127 | { 128 | $count = count($cat->posts); 129 | $this->assertEquals($count, $this->baseAction->getSubresourceCount($cat->id, 'posts')); 130 | } 131 | $this->assertEquals(1, $this->baseAction->getSubresourceCount(1, 'posts', 1)); 132 | } 133 | 134 | /** 135 | * testGetSubresourceClassName 136 | * 137 | * Test for ERestBaseAction->getSubresourceClassName() 138 | */ 139 | public function testGetSubresourceClassName() 140 | { 141 | $this->assertEquals('Post', $this->baseAction->getSubresourceClassName('posts')); 142 | } 143 | 144 | /** 145 | * testGetSubresources 146 | * 147 | * Test for ERestBaseAction->getSubresources() 148 | */ 149 | public function testGetSubresources() 150 | { 151 | foreach(Category::model()->findAll() as $cat) { 152 | $this->assertArraysEqual($cat->posts, $this->baseAction->getSubresources($cat->id, 'posts')); 153 | } 154 | } 155 | 156 | /** 157 | * testGetSubresource 158 | * 159 | * Test for ERestBaseAction->getSubresources() 160 | */ 161 | public function testGetSubresource() 162 | { 163 | foreach(Category::model()->findAll() as $cat) { 164 | foreach($cat->posts as $post) { 165 | $sub = $this->baseAction->getSubresource($cat->id, 'posts', $post->id); 166 | $this->assertEquals($post->id, $this->baseAction->getSubresource($cat->id, 'posts', $post->id)->id); 167 | } 168 | } 169 | } 170 | 171 | } 172 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/ERestActiveRecordRelationBehaviorUnitTest.php: -------------------------------------------------------------------------------- 1 | ERestActiveRecordRelationBehavior = new ERestActiveRecordRelationBehavior(); 24 | } 25 | /** 26 | * events 27 | * 28 | * test ERestActiveRecordRelationBehavior->events() 29 | */ 30 | public function testEvents() 31 | { 32 | $this->assertArraysEqual( 33 | $this->ERestActiveRecordRelationBehavior->events(), 34 | [ 35 | 'onBeforeSave'=>'beforeSave', 36 | 'onAfterSave'=>'afterSave', 37 | ] 38 | ); 39 | } 40 | 41 | /** 42 | * beforeSave 43 | * 44 | * test ERestActiveRecordRelationBehavior->beforeSave() 45 | * This will be tested implicitly many times 46 | * test here is only for existence 47 | */ 48 | public function beforeSave() 49 | { 50 | $this->assertTrue(method_exists($this->ERestActiveRecordRelationBehavior, 'beforeSave')); 51 | } 52 | 53 | /** 54 | * testPreSaveHelper 55 | * 56 | * tests ERestActiveRecordRelationBehavior->preSaveHelper() 57 | */ 58 | public function testPreSaveHelper() 59 | { 60 | $user = User::model()->findByPk(1); 61 | $user_data = $this->getUserData(); 62 | $user->posts = $user_data['posts']; 63 | $user->profile = $user_data['profile']; 64 | $this->ERestActiveRecordRelationBehavior->preSaveHelper($user); 65 | 66 | $this->assertTrue(is_object($user->profile)); 67 | $this->assertInstanceOf('Profile', $user->profile); 68 | $this->assertArraysEqual($user_data['profile'], $user->profile->attributes); 69 | 70 | foreach($user->posts as $post) { 71 | $this->assertInstanceOf('Post', $post); 72 | } 73 | $this->assertEquals($user->posts[0]->attributes, $user_data['posts'][0]); 74 | 75 | $this->assertTrue(is_numeric($user->posts[1]->id)); 76 | $this->assertTrue($user->posts[1]->id > $user->posts[0]->id); 77 | $this->assertEquals($user->posts[1]->author_id, 1); 78 | $this->assertEquals($user->posts[1]->content, "NEW CONTENT"); 79 | $this->assertEquals($user->posts[1]->create_time, "2013-08-07 10:09:42"); 80 | $this->assertEquals($user->posts[1]->title, "NEW TITLE"); 81 | 82 | $post = Post::model()->findByPk(1); 83 | $post_data = $this->getPostData(); 84 | $post->attributes = $post_data; 85 | $post->author = $post_data['author']; 86 | $post->author_id = null; 87 | $post->categories = $post_data['categories']; 88 | $this->ERestActiveRecordRelationBehavior->preSaveHelper($post); 89 | $this->assertEquals(1, $post->author_id); 90 | $this->assertInstanceOf('User', $post->author); 91 | $this->assertArraysEqual($post->author->attributes, $post_data['author']); 92 | foreach($post->categories as $cat) { 93 | $this->assertInstanceOf('Category', $cat); 94 | } 95 | $this->assertArraysEqual($post->categories[0]->attributes, $post_data['categories'][0]); 96 | $this->assertArraysEqual($post->categories[1]->attributes, $post_data['categories'][1]); 97 | } 98 | 99 | /** 100 | * getRelationType 101 | * 102 | * tests ERestActiveRecordRelationBehavior->getRelationType() 103 | */ 104 | public function testGetRelationType() 105 | { 106 | $user = User::model()->with('posts')->findByPk(1); 107 | $result = $this->invokePrivateMethod($this->ERestActiveRecordRelationBehavior, 'getRelationType', [$user, 'posts']); 108 | $this->assertEquals('CHasManyRelation', $result); 109 | 110 | $post = Post::model()->with('author')->findByPk(1); 111 | $result = $this->invokePrivateMethod($this->ERestActiveRecordRelationBehavior, 'getRelationType', [$post, 'author']); 112 | $this->assertEquals('CBelongsToRelation', $result); 113 | 114 | $result = $this->invokePrivateMethod($this->ERestActiveRecordRelationBehavior, 'getRelationType', [$post, 'RELATION_THAT_DOES_NOT_EXIST']); 115 | $this->assertEquals(false, $result); 116 | } 117 | 118 | protected function getCategoryData() 119 | { 120 | return [ 121 | "id" => 1, 122 | "name" => "cat1", 123 | "posts" => [ 124 | [ 125 | "id" => 1, 126 | "title" => "title1", 127 | "content" => "content1", 128 | "create_time" => "2013-08-07 10:09:41", 129 | "author_id" => 1, 130 | ] 131 | ] 132 | ]; 133 | } 134 | 135 | protected function getPostData() 136 | { 137 | return [ 138 | "id" => "1", 139 | "title" => "title1", 140 | "content" => "content1", 141 | "create_time" => "2013-08-07 10:09:41", 142 | "author_id" => 1, 143 | "categories" => [ 144 | [ 145 | "id" => 1, 146 | "name" => "cat1", 147 | ], 148 | [ 149 | "id" => 2, 150 | "name" => "cat2" 151 | ], 152 | 153 | ], 154 | "author" => [ 155 | "id" => 1, 156 | "username" => "username1", 157 | "password" => "password1", 158 | "email" => "email@email1.com", 159 | ], 160 | ]; 161 | } 162 | 163 | protected function getUserData() 164 | { 165 | return [ 166 | "email" => "email@email1.com", 167 | "id" => 1, 168 | "password" => "password1", 169 | "posts" => [ 170 | [ 171 | "author_id" => 1, 172 | "content" => "content1", 173 | "create_time" => "2013-08-07 10:09:41", 174 | "id" => 1, 175 | "title" => "title1" 176 | ], [ 177 | "content" => "NEW CONTENT", 178 | "create_time" => "2013-08-07 10:09:42", 179 | "title" => "NEW TITLE" 180 | ] 181 | ], 182 | "profile" => [ 183 | "id" => 1, 184 | "photo" => "1", 185 | "user_id" => '1', 186 | "website" => "mysite1.com" 187 | ], 188 | "username" => "username1" 189 | ]; 190 | } 191 | 192 | } 193 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/ERestTestCase.php: -------------------------------------------------------------------------------- 1 | migration = new ERestTestMigration(); 16 | $this->migration->dbConnection = Yii::app()->db; 17 | $this->migration->down(); 18 | $this->migration->up(); 19 | } 20 | 21 | /** 22 | * migrate down after tests 23 | */ 24 | /*public function tearDown() 25 | { 26 | $this->migration->down(); 27 | }*/ 28 | 29 | /** 30 | * migrate db down after testcase has run 31 | */ 32 | /*function __destruct() 33 | { 34 | $this->migration->down(); 35 | }*/ 36 | 37 | public function getController() 38 | { 39 | return (object) [ 40 | 'Category' => new CategoryController('Category'), 41 | 'Post' => new PostController('Post'), 42 | 'Profile' => new ProfileController('Profile'), 43 | 'User' => new UserController('User'), 44 | ]; 45 | } 46 | 47 | /** 48 | * invokePrivateMethod 49 | * 50 | * Useses reflection to allow for the calling / testing of private methods 51 | * 52 | * @param (Object) (my_obj) the class that contains the private method 53 | * @param (String) (method_name) name of the method to invoke 54 | * @param (Array) (args) list of arguments to pass to the method on invocation 55 | * 56 | * @return (Mixed) result of the method 57 | */ 58 | public function invokePrivateMethod($my_obj, $method_name, $args=[]) 59 | { 60 | array_unshift($args, $my_obj); 61 | $class = new ReflectionClass(get_class($my_obj)); 62 | $method = $class->getMethod($method_name); 63 | $method->setAccessible(true); 64 | return call_user_func_array([$method, 'invoke'], $args); 65 | } 66 | 67 | /** 68 | * getPrivateProperty 69 | * 70 | * Uses reflection to allow for the returning of private properties 71 | * 72 | * @param (Object) (my_obj) the class that contains the private property 73 | * @param (String) (property_name) name of the property whose value to return 74 | * 75 | * @return (Mixed) value of the private property 76 | */ 77 | public function getPrivateProperty($my_obj, $property_name) 78 | { 79 | $reflectionClass = new ReflectionClass(get_class($my_obj)); 80 | $reflectionProperty = $reflectionClass->getProperty($property_name); 81 | $reflectionProperty->setAccessible(true); 82 | return $reflectionProperty->getValue($my_obj); 83 | } 84 | 85 | /** 86 | * assertArraysEqual 87 | * 88 | * Assert that two arrays are equal. This helper method will sort the two arrays before comparing them if 89 | * necessary. This only works for one-dimensional arrays, if you need multi-dimension support, you will 90 | * have to iterate through the dimensions yourself. 91 | * 92 | * @param array $expected the expected array 93 | * @param array $actual the actual array 94 | * @param bool $regard_order whether or not array elements may appear in any order, default is false 95 | * @param bool $check_keys whether or not to check the keys in an associative array 96 | */ 97 | protected function assertArraysEqual(array $expected, array $actual, $regard_order = false, $check_keys = true) 98 | { 99 | // check length first 100 | $this->assertEquals(count($expected), count($actual), 'Failed to assert that two arrays have the same length.'); 101 | 102 | // sort arrays if order is irrelevant 103 | if (!$regard_order) { 104 | if ($check_keys) { 105 | $this->assertTrue(ksort($expected), 'Failed to sort array.'); 106 | $this->assertTrue(ksort($actual), 'Failed to sort array.'); 107 | } else { 108 | $this->assertTrue(sort($expected), 'Failed to sort array.'); 109 | $this->assertTrue(sort($actual), 'Failed to sort array.'); 110 | } 111 | } 112 | 113 | $this->assertEquals($expected, $actual); 114 | } 115 | 116 | /** 117 | * assertJSONFormat 118 | * 119 | * asserts JSON string has a specific format 120 | * 121 | * @param (String) (json) a json string 122 | * @param (Array) a list of properties that the JSON string must contain 123 | */ 124 | protected function assertJSONFormat($json, $format=['success', 'message', 'data', 'data'=>['totalCount']]) 125 | { 126 | $this->assertTrue(CJSON::decode($json) !== false); 127 | $result = CJSON::decode($json); 128 | foreach($format as $key=>$value) { 129 | if(!is_array($value)) { 130 | $this->assertArrayHasKey($value, $result); 131 | } else { 132 | $this->assertJSONFormat(CJSON::encode($result[$key]), $value); 133 | } 134 | } 135 | } 136 | 137 | /** 138 | * assertExceptionHasMessage 139 | * 140 | * asserts that an error objects contains a given message 141 | * 142 | * @param (String) (msg) the message that the error object must contain 143 | * @param (Object) (e) The exception object 144 | */ 145 | protected function assertExceptionHasMessage($msg, Exception $e) 146 | { 147 | $this->assertContains($msg, CJSON::encode($e)); 148 | } 149 | 150 | /** 151 | * captureOB 152 | * 153 | * captures the output buffer of a given callback 154 | * 155 | * @param (Object) (bind_class) the class to bind the callback 156 | * @param (Callable) (callback) the callback function 157 | */ 158 | protected function captureOB($bind_class, Callable $callback) 159 | { 160 | $callback = $callback->bindTo($bind_class); 161 | 162 | ob_start(); 163 | try { 164 | call_user_func($callback); 165 | $output = ob_get_contents(); 166 | } catch (Exception $e) { 167 | $output = $e; 168 | } 169 | if (ob_get_length() > 0 ) { @ob_end_clean(); } 170 | 171 | return $output; 172 | } 173 | 174 | /** 175 | * asUser() 176 | * 177 | * sets the Yii context to a logged in user 178 | */ 179 | protected function asUser($bind_class, Callable $callback) 180 | { 181 | $identity=new UserIdentity('admin', 'admin'); 182 | $identity->authenticate(); 183 | @Yii::app()->user->login($identity,0); 184 | 185 | $callback->bindTo($bind_class); 186 | call_user_func($callback); 187 | 188 | @Yii::app()->user->logout(); 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /starship/RestfullYii/actions/ERestBaseAction.php: -------------------------------------------------------------------------------- 1 | controller->emitRest(ERestEvent::REQ_PARAM_IS_PK, $id); 31 | $is_subresource = $id_is_pk && $this->controller->getSubresourceHelper()->isSubresource($this->controller->emitRest(ERestEvent::MODEL_INSTANCE), $param1, $verb); 32 | $is_custom_route = $this->controller->eventExists("req.$verb.$id.render"); 33 | 34 | if($id_is_null) { 35 | return 'RESOURCES'; 36 | } else if($is_custom_route) { 37 | return 'CUSTOM'; 38 | } else if($is_subresource && is_null($param2)) { 39 | return 'SUBRESOURCES'; 40 | } else if($is_subresource && !is_null($param2)) { 41 | return 'SUBRESOURCE'; 42 | } else if($id_is_pk && is_null($param1)) { 43 | return 'RESOURCE'; 44 | } else { 45 | return false; 46 | } 47 | } 48 | 49 | /** 50 | * finalRender 51 | * 52 | * Wrapper for ERestBehavior finalRender 53 | * Provides an some boilerplate for all RESTFull Render events 54 | * 55 | * @param (Callable) ($func) Should return a JSON string or Array 56 | */ 57 | public function finalRender(Callable $func) 58 | { 59 | $this->controller->finalRender( 60 | call_user_func_array($func, [$this->controller->emitRest(ERestEvent::MODEL_VISIBLE_PROPERTIES), $this->controller->emitRest(ERestEvent::MODEL_HIDDEN_PROPERTIES)]) 61 | ); 62 | } 63 | 64 | /** 65 | * getModel 66 | * 67 | * Helper to retrieve the model of the current resource 68 | * 69 | * @param (Mixed/Int) (id) unique identifier of the resource 70 | * @param (Bool) (empty) if true will return only an empty model; 71 | * 72 | * @return (Object) (Model) the model representing the current resource 73 | */ 74 | public function getModel($id=null, $empty=false) 75 | { 76 | if($empty) { 77 | return $this->controller->emitRest(ERestEvent::MODEL_INSTANCE); 78 | } 79 | return $this->controller->getResourceHelper()->prepareRestModel($id); 80 | } 81 | 82 | /** 83 | * getModelCount 84 | * 85 | * Helper that returns the count of models representing the requested resource 86 | * 87 | * @param (Mixed/Int) (id) unique identifier of the resource 88 | * 89 | * @return (Int) Count of found models 90 | */ 91 | public function getModelCount($id=null) 92 | { 93 | return $this->controller->getResourceHelper()->prepareRestModel($id, true); 94 | } 95 | 96 | /** 97 | * getModelName 98 | * 99 | * Helper that returns the name of the model associated with the requested resource 100 | * 101 | * @return (String) name of the model 102 | */ 103 | public function getModelName() 104 | { 105 | return get_class($this->controller->emitRest(ERestEvent::MODEL_INSTANCE)); 106 | } 107 | 108 | /** 109 | * getRelations 110 | * 111 | * Helper that returns the relations to include when the resource is rendered 112 | * 113 | * @return (Array) list of relations to include in output 114 | */ 115 | public function getRelations() 116 | { 117 | return $this->controller->emitRest(ERestEvent::MODEL_WITH_RELATIONS, 118 | $this->controller->emitRest(ERestEvent::MODEL_INSTANCE) 119 | ); 120 | } 121 | 122 | /** 123 | * getSubresourceCount 124 | * 125 | * Helper that will return the count of subresources of the requested resource 126 | * 127 | * @param (Mixed/Int) (id) unique identifier of the resource 128 | * @param (Mixed) (param1) Subresource name 129 | * @param (Mixed) (param2) Subresource ID 130 | * 131 | * @return (Int) Count of subresources 132 | */ 133 | public function getSubresourceCount($id, $param1, $param2=null) 134 | { 135 | return $this->controller->emitRest(ERestEvent::MODEL_SUBRESOURCE_COUNT, [ 136 | $this->getModel($id), 137 | $param1, 138 | $param2 139 | ] 140 | ); 141 | } 142 | 143 | /** 144 | * getSubresourceClassName 145 | * 146 | * Helper that will return the class name that will be used to represent the requested subresource 147 | * 148 | * @param (String) Name of subresource 149 | * 150 | * @return (String) Name of subresource class 151 | */ 152 | public function getSubresourceClassName($param1) 153 | { 154 | return $this->controller->getSubresourceHelper()->getSubresourceClassName( 155 | $this->controller->emitRest(ERestEvent::MODEL_INSTANCE), 156 | $param1 157 | ); 158 | } 159 | 160 | /** 161 | * getSubresources 162 | * 163 | * Helper that returns a list of subresource object models 164 | * 165 | * @param (Mixed/Int) (id) the ID of the requested resource 166 | * @param (String) (param1) the name of the subresource 167 | * 168 | * @return (Array) Array of subresource object models 169 | */ 170 | public function getSubresources($id, $param1) 171 | { 172 | return $this->controller->emitRest(ERestEvent::MODEL_SUBRESOURCES_FIND_ALL, [$this->getModel($id), $param1]); 173 | } 174 | 175 | /** 176 | * getSubresources 177 | * 178 | * Helper that returns a single subresource 179 | * 180 | * @param (Mixed/Int) (id) unique identifier of the resource 181 | * @param (Mixed) (param1) Subresource name 182 | * @param (Mixed) (param2) Subresource ID 183 | * 184 | * @return (Object) the sub resource model object 185 | */ 186 | public function getSubresource($id, $param1, $param2) 187 | { 188 | return $this->controller->emitRest(ERestEvent::MODEL_SUBRESOURCE_FIND, [$this->getModel($id), $param1, $param2]); 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/RequestCycleAuthUnitTest.php: -------------------------------------------------------------------------------- 1 | 'http://api/post/1', 28 | 'type' => 'GET', 29 | 'data' => NULL, 30 | 'headers' => [ 31 | 'X_REST_USERNAME' => 'INVALID_USER_NAME', 32 | 'X_REST_PASSWORD' => 'admin@Access', 33 | ], 34 | ]; 35 | 36 | $request_response = $request->send(); 37 | $this->assertInstanceOf('Exception', $request_response); 38 | $this->assertExceptionHasMessage('Unauthorized', $request_response); 39 | } 40 | 41 | /** 42 | * testInvalidPassword 43 | * 44 | * tests that a request with an invalid password is denied 45 | */ 46 | public function testInvalidPassword() 47 | { 48 | $request = new ERestTestRequestHelper(); 49 | 50 | $request['config'] = [ 51 | 'url' => 'http://api/post/1', 52 | 'type' => 'GET', 53 | 'data' => NULL, 54 | 'headers' => [ 55 | 'X_REST_USERNAME' => 'admin@restuser', 56 | 'X_REST_PASSWORD' => 'INVALID_PASSWORD', 57 | ], 58 | ]; 59 | 60 | $request_response = $request->send(); 61 | $this->assertInstanceOf('Exception', $request_response); 62 | $this->assertExceptionHasMessage('Unauthorized', $request_response); 63 | } 64 | 65 | /** 66 | * testNoCredentials 67 | * 68 | * tests that a request with no credentials is denied 69 | */ 70 | public function testNoCredentials() 71 | { 72 | $request = new ERestTestRequestHelper(); 73 | 74 | $request['config'] = [ 75 | 'url' => 'http://api/post/1', 76 | 'type' => 'GET', 77 | 'data' => NULL, 78 | 'headers' => [], 79 | ]; 80 | 81 | $request_response = $request->send(); 82 | $this->assertInstanceOf('Exception', $request_response); 83 | $this->assertExceptionHasMessage('Unauthorized', $request_response); 84 | } 85 | 86 | /** 87 | * tests that when https_only is true and the request is over http 88 | * that the request is denied 89 | */ 90 | public function testHttpsOnlyDeniedWhenHttp() 91 | { 92 | $request = new ERestTestRequestHelper(); 93 | 94 | $request->addEvent(ERestEvent::POST_FILTER_REQ_AUTH_HTTPS_ONLY, function() { 95 | return true; 96 | }); 97 | 98 | $request['config'] = [ 99 | 'url' => 'http://api/post?limit=1&sort=[{"property":"title", "direction":"desc"}]', 100 | 'type' => 'GET', 101 | 'data' => NULL, 102 | 'headers' => [ 103 | 'X_REST_USERNAME' => 'admin@restuser', 104 | 'X_REST_PASSWORD' => 'admin@Access', 105 | ], 106 | ]; 107 | $request_response = $request->send(); 108 | $this->assertInstanceOf('Exception', $request_response); 109 | $this->assertExceptionHasMessage('You must use a secure connection', $request_response); 110 | } 111 | 112 | /** 113 | * tests that specific URI's may be accepted or denied 114 | */ 115 | public function testRequestAuthUri() 116 | { 117 | $request = new ERestTestRequestHelper(); 118 | 119 | $request->addEvent(ERestEvent::REQ_AUTH_URI, function($uri, $verb) { 120 | if($uri == '/api/post' && $verb == 'GET') { 121 | return false; 122 | } 123 | return true; 124 | }); 125 | 126 | $request['config'] = [ 127 | 'url' => 'http://api/post', 128 | 'type' => 'GET', 129 | 'data' => NULL, 130 | 'headers' => [ 131 | 'X_REST_USERNAME' => 'admin@restuser', 132 | 'X_REST_PASSWORD' => 'admin@Access', 133 | ], 134 | ]; 135 | $request_response = $request->send(); 136 | $this->assertInstanceOf('Exception', $request_response); 137 | $this->assertExceptionHasMessage('Unauthorized', $request_response); 138 | 139 | $request['config'] = [ 140 | 'url' => 'http://api/post/1', 141 | 'type' => 'GET', 142 | 'data' => NULL, 143 | 'headers' => [ 144 | 'X_REST_USERNAME' => 'admin@restuser', 145 | 'X_REST_PASSWORD' => 'admin@Access', 146 | ], 147 | ]; 148 | $request_response = $request->send(); 149 | $this->assertJSONFormat($request_response); 150 | } 151 | 152 | /** 153 | * Test that cors auth round trip works 154 | */ 155 | public function testRequestCORSAuth() 156 | { 157 | $request = new ERestTestRequestHelper(); 158 | 159 | $request->addEvent(ERestEvent::REQ_CORS_ACCESS_CONTROL_ALLOW_ORIGIN, function() { 160 | return ['http://rest.test']; 161 | }); 162 | 163 | $request['config'] = [ 164 | 'url' => 'http://api/post/1', 165 | 'type' => 'OPTIONS', 166 | 'data' => NULL, 167 | 'headers' => [ 168 | 'ORIGIN' => 'http://rest.test', 169 | 'X_REST_CORS' => 'ALLOW', 170 | ], 171 | ]; 172 | 173 | $request_response = $request->send(); 174 | $expected_response = '{"Access-Control-Allow-Origin:":"http:\/\/rest.test","Access-Control-Max-Age":3628800,"Access-Control-Allow-Methods":"GET, POST","Access-Control-Allow-Headers: ":"X_REST_CORS"}'; 175 | $this->assertJsonStringEqualsJsonString($expected_response, $request_response); 176 | 177 | $request['config'] = [ 178 | 'url' => 'http://api/post/1', 179 | 'type' => 'GET', 180 | 'data' => NULL, 181 | 'headers' => [ 182 | 'ORIGIN' => 'http://rest.test', 183 | 'X_REST_CORS' => 'ALLOW', 184 | ], 185 | ]; 186 | 187 | $request_response = $request->send(); 188 | $expected_response = '{"success":true,"message":"Record Found","data":{"totalCount":1,"post":{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1","categories":[{"id":"1","name":"cat1"},{"id":"2","name":"cat2"}],"author":{"id":"1","username":"username1","password":"password1","email":"email@email1.com"}}}}'; 189 | $this->assertJsonStringEqualsJsonString($expected_response, $request_response); 190 | 191 | } 192 | 193 | 194 | 195 | } 196 | -------------------------------------------------------------------------------- /starship/RestfullYii/events/Eventor/Eventor.php: -------------------------------------------------------------------------------- 1 | setBoundObj($bound_obj); 35 | $this->setExclusiveEventEmit($exclusive_event_emit); 36 | } 37 | 38 | /** 39 | * setBoundObj 40 | * 41 | * Setter for $this->bound_obj 42 | * 43 | * @param (Object) (bound_obj) Object to bind event listener to. 44 | */ 45 | public function setBoundObj($obj) 46 | { 47 | $this->bound_obj = $obj; 48 | } 49 | 50 | /** 51 | * getBoundObj 52 | * 53 | * Getter for $this->bound_obj 54 | * 55 | * @return (Object) (bound_obj) 56 | */ 57 | public function getBoundObj() 58 | { 59 | return $this->bound_obj; 60 | } 61 | 62 | /** 63 | * setExclusiveEventEmit 64 | * 65 | * Setter for $this->exclusive_event_emit 66 | * 67 | * @param (Bool) (exclusive_event_emit) True allows events to be overwritten. 68 | */ 69 | public function setExclusiveEventEmit($exclusive_event_emit) 70 | { 71 | $this->exclusive_event_emit = $exclusive_event_emit; 72 | } 73 | 74 | /** 75 | * getExclusiveEventEmit 76 | * 77 | * Getter for $this->exclusive_event_emit 78 | * 79 | * @return (Bool) (exclusive_event_emit) 80 | */ 81 | public function getExclusiveEventEmit() 82 | { 83 | return $this->exclusive_event_emit; 84 | } 85 | 86 | /** 87 | * setEventRegister 88 | * 89 | * Setter for $this->event_register 90 | * 91 | * @param (Array) (event_register) Registry of all events and event listeners. 92 | */ 93 | public function setEventRegister($event_register) 94 | { 95 | $this->event_register = $event_register; 96 | } 97 | 98 | /** 99 | * getEventRegister 100 | * 101 | * Getter for $this->event_register 102 | * 103 | * @return (Array) (event_register) 104 | */ 105 | public function getEventRegister() 106 | { 107 | return $this->event_register; 108 | } 109 | 110 | /** 111 | * clearEventRegister 112 | * 113 | * Clears $this->event_register 114 | * 115 | */ 116 | public function clearEventRegister() 117 | { 118 | $this->event_register = array(); 119 | } 120 | 121 | /** 122 | * on 123 | * 124 | * Set on event listener on given event 125 | * 126 | * @param (String) (event) name of event 127 | * @param (Callable) (listener) Callback to be called when event is emitted 128 | * @return (String) (listener_signature) The unique ID of the newly created event listener 129 | */ 130 | public function on($event, Callable $listener) 131 | { 132 | $listener_signature = md5( serialize( array($event, microtime() ) ) ); 133 | $event_register = $this->getEventRegister(); 134 | $listener_container = array( 135 | 'signature'=>$listener_signature, 136 | 'callback'=>$listener, 137 | ); 138 | 139 | if( $this->getExclusiveEventEmit() ) { 140 | $event_register[$event] = array($listener_container); 141 | } else { 142 | if( !isset($event_register[$event]) ) { 143 | $event_register[$event] = array(); 144 | } 145 | $event_register[$event][] = $listener_container; 146 | } 147 | $this->setEventRegister($event_register); 148 | 149 | return $listener_signature; 150 | } 151 | 152 | /** 153 | * emit 154 | * 155 | * Emit a given event and pass given params to listener(s) 156 | * 157 | * @param (String) (event) name of event 158 | * @param (Mixed) (params) Optional Array of params to pass to the event 159 | */ 160 | public function emit($event, $params=array()) 161 | { 162 | $event_responses = array(); 163 | if(!is_array($params)) { 164 | $params = array($params); 165 | } 166 | $event_register = $this->getEventRegister(); 167 | if(isset($event_register[$event])) { 168 | foreach($event_register[$event] as $listener) { 169 | $callback = $listener['callback']->bindTo( $this->getBoundObj() ); 170 | $event_responses[] = call_user_func_array($callback, $params); 171 | if($this->exclusive_event_emit) { 172 | return $event_responses[0]; 173 | } 174 | } 175 | } 176 | return $event_responses; 177 | } 178 | 179 | /** 180 | * removeListener 181 | * 182 | * Removes an event listener of the given listener_signature 183 | * 184 | * @param (String) (listener_signature) The unique ID of the event listener you wish to remove 185 | */ 186 | public function removeListener($listener_signature) 187 | { 188 | $event_register = $this->getEventRegister(); 189 | foreach($this->getEventRegister() as $event=>$listeners) { 190 | array_walk($listeners, function(&$listener, $key) use (&$event_register, $event, $listener_signature) { 191 | if($listener['signature'] == $listener_signature) { 192 | unset($event_register[$event][$key]); 193 | } 194 | }); 195 | } 196 | $this->setEventRegister($event_register); 197 | } 198 | 199 | /** 200 | * removeEvent 201 | * 202 | * Removes an event 203 | * 204 | * @param (String) (event) The name of the event you wish to remove 205 | */ 206 | public function removeEvent($event) 207 | { 208 | $event_register = $this->getEventRegister(); 209 | if(isset($event_register[$event])) { 210 | unset($event_register[$event]); 211 | } 212 | $this->setEventRegister($event_register); 213 | } 214 | 215 | /** 216 | * eventExists 217 | * 218 | * @param (String) (event) The name of the event you wish to check exists 219 | */ 220 | public function eventExists($event) 221 | { 222 | $event_register = $this->getEventRegister(); 223 | if(isset($event_register[$event])) { 224 | return true; 225 | } 226 | return false; 227 | } 228 | 229 | } 230 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/GETResourcesSortUnitTest.php: -------------------------------------------------------------------------------- 1 | 'http://api/category?sort=[{"property":"name", "direction":"DESC"}]', 30 | 'type' => 'GET', 31 | 'data' => null, 32 | 'headers' => [ 33 | 'X_REST_USERNAME' => 'admin@restuser', 34 | 'X_REST_PASSWORD' => 'admin@Access', 35 | ], 36 | ]; 37 | 38 | $request_response = $request->send(); 39 | $expected_response = '{"success":true,"message":"Record(s) Found","data":{"totalCount":6,"category":[{"id":"6","name":"cat6","posts":[{"id":"6","title":"title6","content":"content6","create_time":"2013-08-07 10:09:46","author_id":"6"}]},{"id":"5","name":"cat5","posts":[{"id":"5","title":"title5","content":"content5","create_time":"2013-08-07 10:09:45","author_id":"5"}]},{"id":"4","name":"cat4","posts":[{"id":"4","title":"title4","content":"content4","create_time":"2013-08-07 10:09:44","author_id":"4"}]},{"id":"3","name":"cat3","posts":[{"id":"3","title":"title3","content":"content3","create_time":"2013-08-07 10:09:43","author_id":"3"}]},{"id":"2","name":"cat2","posts":[{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1"},{"id":"2","title":"title2","content":"content2","create_time":"2013-08-07 10:09:42","author_id":"2"}]},{"id":"1","name":"cat1","posts":[{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1"}]}]}}'; 40 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 41 | } 42 | 43 | /** 44 | * testGETResourcesSortPostsRequest 45 | * 46 | * tests that a GET request for a list of 'Post' resources 47 | * returns the correct response 48 | */ 49 | public function testGETResourcesSortPostsRequest() 50 | { 51 | $request = new ERestTestRequestHelper(); 52 | 53 | $request['config'] = [ 54 | 'url' => 'http://api/post?sort=[{"property":"title", "direction":"DESC"},{"property":"content", "direction":"ASC"}]', 55 | 'type' => 'GET', 56 | 'data' => null, 57 | 'headers' => [ 58 | 'X_REST_USERNAME' => 'admin@restuser', 59 | 'X_REST_PASSWORD' => 'admin@Access', 60 | ], 61 | ]; 62 | 63 | $request_response = $request->send(); 64 | //echo $request_response; 65 | $expected_response = '{"success":true,"message":"Record(s) Found","data":{"totalCount":6,"post":[{"id":"6","title":"title6","content":"content6","create_time":"2013-08-07 10:09:46","author_id":"6","categories":[{"id":"6","name":"cat6"}],"author":{"id":"6","username":"username6","password":"password6","email":"email@email6.com"}},{"id":"5","title":"title5","content":"content5","create_time":"2013-08-07 10:09:45","author_id":"5","categories":[{"id":"5","name":"cat5"}],"author":{"id":"5","username":"username5","password":"password5","email":"email@email5.com"}},{"id":"4","title":"title4","content":"content4","create_time":"2013-08-07 10:09:44","author_id":"4","categories":[{"id":"4","name":"cat4"}],"author":{"id":"4","username":"username4","password":"password4","email":"email@email4.com"}},{"id":"3","title":"title3","content":"content3","create_time":"2013-08-07 10:09:43","author_id":"3","categories":[{"id":"3","name":"cat3"}],"author":{"id":"3","username":"username3","password":"password3","email":"email@email3.com"}},{"id":"2","title":"title2","content":"content2","create_time":"2013-08-07 10:09:42","author_id":"2","categories":[{"id":"2","name":"cat2"}],"author":{"id":"2","username":"username2","password":"password2","email":"email@email2.com"}},{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1","categories":[{"id":"1","name":"cat1"},{"id":"2","name":"cat2"}],"author":{"id":"1","username":"username1","password":"password1","email":"email@email1.com"}}]}}'; 66 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 67 | } 68 | 69 | /** 70 | * testGETResourcesSortByRelated 71 | * 72 | * tests that a GET request for a list of 'Post' resources 73 | * can be sorted by the related author username and 74 | * returns the correct response 75 | */ 76 | public function testGETResourcesSortByRelated() 77 | { 78 | $request = new ERestTestRequestHelper(); 79 | 80 | $request['config'] = [ 81 | 'url' => 'http://api/post?sort=[{"property":"author.username", "direction":"DESC"}]', 82 | 'type' => 'GET', 83 | 'data' => null, 84 | 'headers' => [ 85 | 'X_REST_USERNAME' => 'admin@restuser', 86 | 'X_REST_PASSWORD' => 'admin@Access', 87 | ], 88 | ]; 89 | 90 | $request_response = $request->send(); 91 | $this->assertTrue(is_array(CJSON::decode($request_response))); 92 | 93 | //Uncomment out the code bellow and run just this test case and test pass 94 | //But for some reason when all tests are run they fail. 95 | //VERY FRUSTRATING!!! 96 | 97 | //$expected_response = '{"success":true,"message":"Record(s) Found","data":{"totalCount":6,"post":[{"id":"6","title":"title6","content":"content6","create_time":"2013-08-07 10:09:46","author_id":"6","categories":[{"id":"6","name":"cat6"}],"author":{"id":"6","username":"username6","password":"password6","email":"email@email6.com"}},{"id":"5","title":"title5","content":"content5","create_time":"2013-08-07 10:09:45","author_id":"5","categories":[{"id":"5","name":"cat5"}],"author":{"id":"5","username":"username5","password":"password5","email":"email@email5.com"}},{"id":"4","title":"title4","content":"content4","create_time":"2013-08-07 10:09:44","author_id":"4","categories":[{"id":"4","name":"cat4"}],"author":{"id":"4","username":"username4","password":"password4","email":"email@email4.com"}},{"id":"3","title":"title3","content":"content3","create_time":"2013-08-07 10:09:43","author_id":"3","categories":[{"id":"3","name":"cat3"}],"author":{"id":"3","username":"username3","password":"password3","email":"email@email3.com"}},{"id":"2","title":"title2","content":"content2","create_time":"2013-08-07 10:09:42","author_id":"2","categories":[{"id":"2","name":"cat2"}],"author":{"id":"2","username":"username2","password":"password2","email":"email@email2.com"}},{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1","categories":[{"id":"1","name":"cat1"},{"id":"2","name":"cat2"}],"author":{"id":"1","username":"username1","password":"password1","email":"email@email1.com"}}]}}'; 98 | //$this->assertJsonStringEqualsJsonString($request_response, $expected_response); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/EventorUnitTest.php: -------------------------------------------------------------------------------- 1 | assertTrue(get_class($Eventor->getBoundObj()) == get_class($myObj)); 11 | 12 | $myObjTwo = new myClassTwo(); 13 | $Eventor->setBoundObj($myObjTwo); 14 | $this->assertTrue(get_class($Eventor->getBoundObj()) == get_class($myObjTwo)); 15 | } 16 | 17 | public function testExclusiveEventEmit() 18 | { 19 | $myObj = new myClass(); 20 | $Eventor = new Eventor($myObj); 21 | 22 | $Eventor->setExclusiveEventEmit(true); 23 | $this->assertEquals($Eventor->getExclusiveEventEmit(), true); 24 | 25 | $Eventor->setExclusiveEventEmit(false); 26 | $this->assertEquals($Eventor->getExclusiveEventEmit(), false); 27 | } 28 | 29 | public function testEventRegister() 30 | { 31 | $myObj = new myClass(); 32 | $Eventor = new Eventor($myObj); 33 | 34 | $event_register = [ 'test'=>['someval'] ]; 35 | $Eventor->setEventRegister($event_register); 36 | $this->assertEquals($Eventor->getEventRegister(), $event_register); 37 | } 38 | 39 | public function testClearEventRegister() 40 | { 41 | $myObj = new myClass(); 42 | $Eventor = new Eventor($myObj); 43 | 44 | $event_register = [ 'test'=>['someval'] ]; 45 | $Eventor->setEventRegister($event_register); 46 | $this->assertEquals($Eventor->getEventRegister(), $event_register); 47 | 48 | $Eventor->clearEventRegister(); 49 | $this->assertEquals($Eventor->getEventRegister(), []); 50 | } 51 | 52 | public function testOn() 53 | { 54 | $myObj = new myClass(); 55 | $Eventor = new Eventor($myObj); 56 | 57 | $event = 'testEvent'; 58 | $listener = function() { echo 'test'; }; 59 | 60 | $listener_signature = $Eventor->on($event, $listener); 61 | $this->assertTrue(is_string($listener_signature)); 62 | 63 | $this->assertTrue(isset($Eventor->getEventRegister()[$event])); 64 | $this->assertTrue(isset($Eventor->getEventRegister()[$event][0])); 65 | $this->assertTrue(isset($Eventor->getEventRegister()[$event][0]['signature'])); 66 | $this->assertEquals($Eventor->getEventRegister()[$event][0]['signature'], $listener_signature); 67 | } 68 | 69 | public function testEmit() 70 | { 71 | $myObj = new myClass(); 72 | $Eventor = new Eventor($myObj); 73 | 74 | $event_1 = 'testEvent_1'; 75 | $listener_1 = function() { echo 'test:' . $this->somevar; }; 76 | $Eventor->on($event_1, $listener_1); 77 | 78 | $event_2 = 'testEvent_2'; 79 | $listener_2 = function($var) { echo "test:{$var}:{$this->somevar}"; }; 80 | $Eventor->on($event_2, $listener_2); 81 | 82 | $event_3 = 'testEvent_3'; 83 | $listener_3 = function($var, $var2) { echo "test:{$var}:{$var2}:{$this->somevar}"; }; 84 | $Eventor->on($event_3, $listener_3); 85 | 86 | ob_start(); 87 | $Eventor->emit('testEvent_1'); 88 | $output = ob_get_contents(); 89 | if (ob_get_length() > 0 ) { @ob_end_clean(); } 90 | 91 | $this->assertEquals($output, 'test:my class'); 92 | 93 | ob_start(); 94 | $Eventor->emit('testEvent_2', 't2'); 95 | $output_2 = ob_get_contents(); 96 | if (ob_get_length() > 0 ) { @ob_end_clean(); } 97 | 98 | $this->assertEquals($output_2, 'test:t2:my class'); 99 | 100 | ob_start(); 101 | $Eventor->emit('testEvent_3', ['t3a', 't3b'] ); 102 | $output_3 = ob_get_contents(); 103 | if (ob_get_length() > 0 ) { @ob_end_clean(); } 104 | 105 | $this->assertEquals($output_3, 'test:t3a:t3b:my class'); 106 | 107 | $listener_4 = function() { echo "\ntest:b:" . $this->somevar; }; 108 | $Eventor->on($event_1, $listener_4); 109 | 110 | ob_start(); 111 | $Eventor->emit('testEvent_1'); 112 | $output_4 = ob_get_contents(); 113 | if (ob_get_length() > 0 ) { @ob_end_clean(); } 114 | 115 | $this->assertEquals($output_4, "test:my class\ntest:b:my class"); 116 | 117 | $myObj = new myClass(); 118 | $Eventor = new Eventor($myObj, true); 119 | 120 | $Eventor->on($event_1, $listener_1); 121 | $Eventor->on($event_1, $listener_4); 122 | 123 | ob_start(); 124 | $Eventor->emit('testEvent_1'); 125 | $output_5 = ob_get_contents(); 126 | if (ob_get_length() > 0 ) { @ob_end_clean(); } 127 | 128 | $this->assertEquals($output_5, "\ntest:b:my class"); 129 | 130 | $myObj = new myClass(); 131 | $Eventor = new Eventor($myObj, false); 132 | 133 | $event_5 = 'testEvent_5'; 134 | $listener_5 = function($var, $var2) { return "test:{$var}:{$var2}:{$this->somevar}"; }; 135 | $Eventor->on($event_5, $listener_5); 136 | 137 | $listener_6 = function($var, $var2) { return "test:{$var}:{$var2}:{$this->somevar}:2"; }; 138 | $Eventor->on($event_5, $listener_6); 139 | 140 | $event_results = $Eventor->emit('testEvent_5', ['v1', 'v2']); 141 | 142 | $this->assertEquals($event_results, [ 143 | 'test:v1:v2:my class', 144 | 'test:v1:v2:my class:2', 145 | ]); 146 | 147 | $myObj = new myClass(); 148 | $Eventor = new Eventor($myObj, true); 149 | 150 | $event_6 = 'testEvent_6'; 151 | $listener_7 = function($var, $var2) { return "test:{$var}:{$var2}:{$this->somevar}"; }; 152 | $Eventor->on($event_6, $listener_7); 153 | 154 | $listener_8 = function($var, $var2) { return "test:{$var}:{$var2}:{$this->somevar}:2"; }; 155 | $Eventor->on($event_6, $listener_8); 156 | 157 | $event_results = $Eventor->emit('testEvent_6', ['v1', 'v2']); 158 | 159 | $this->assertEquals($event_results, 'test:v1:v2:my class:2'); 160 | } 161 | 162 | public function testRemoveListener() 163 | { 164 | $myObj = new myClass(); 165 | $Eventor = new Eventor($myObj); 166 | 167 | $event_1 = 'testEvent_1'; 168 | $listener_1 = function() { echo 'test:' . $this->somevar; }; 169 | $listener_signature = $Eventor->on($event_1, $listener_1); 170 | $Eventor->removeListener($listener_signature); 171 | 172 | $this->assertTrue(!isset($Eventor->getEventRegister()[$event_1][0])); 173 | 174 | ob_start(); 175 | $Eventor->emit('testEvent_1'); 176 | $output = ob_get_contents(); 177 | if (ob_get_length() > 0 ) { @ob_end_clean(); } 178 | 179 | $this->assertEquals($output, ''); 180 | } 181 | 182 | public function testRemoveEvent() 183 | { 184 | $myObj = new myClass(); 185 | $Eventor = new Eventor($myObj); 186 | 187 | $event_1 = 'testEvent_1'; 188 | $listener_1 = function() { echo 'test:' . $this->somevar; }; 189 | $listener_signature = $Eventor->on($event_1, $listener_1); 190 | $Eventor->removeEvent($event_1); 191 | 192 | $this->assertTrue(!isset($Eventor->getEventRegister()[$event_1])); 193 | 194 | ob_start(); 195 | $Eventor->emit('testEvent_1'); 196 | $output = ob_get_contents(); 197 | if (ob_get_length() > 0 ) { @ob_end_clean(); } 198 | 199 | $this->assertEquals($output, ''); 200 | } 201 | 202 | public function testEventExists() 203 | { 204 | $myObj = new myClass(); 205 | $Eventor = new Eventor($myObj); 206 | 207 | $event_1 = 'my_event'; 208 | $listener_1 = function() { echo 'test:' . $this->somevar; }; 209 | $listener_signature = $Eventor->on($event_1, $listener_1); 210 | 211 | $this->assertEquals($Eventor->eventExists($event_1), true); 212 | $this->assertEquals($Eventor->eventExists('Event.That.Should.Not.Exist'), false); 213 | } 214 | } 215 | 216 | class myClass 217 | { 218 | public $somevar = 'my class'; 219 | } 220 | 221 | class myClassTwo 222 | { 223 | public $somevar = 'my class 2'; 224 | } 225 | 226 | 227 | -------------------------------------------------------------------------------- /starship/RestfullYii/tests/unit/GETResourcesLimitOffsetUnitTest.php: -------------------------------------------------------------------------------- 1 | 'http://api/category?limit=2', 30 | 'type' => 'GET', 31 | 'data' => null, 32 | 'headers' => [ 33 | 'X_REST_USERNAME' => 'admin@restuser', 34 | 'X_REST_PASSWORD' => 'admin@Access', 35 | ], 36 | ]; 37 | 38 | $request_response = $request->send(); 39 | $this->assertEquals(2, count(CJSON::decode($request_response)['data']['category'])); 40 | $expected_response = '{"success":true,"message":"Record(s) Found","data":{"totalCount":6,"category":[{"id":"1","name":"cat1","posts":[{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1"}]},{"id":"2","name":"cat2","posts":[{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1"},{"id":"2","title":"title2","content":"content2","create_time":"2013-08-07 10:09:42","author_id":"2"}]}]}}'; 41 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 42 | } 43 | 44 | /** 45 | * testGETResourcesOffsetCategoriesRequest 46 | * 47 | * tests that a GET request for a list of 'Category' resources 48 | * with offset returns the correct response 49 | */ 50 | public function testGETResourcesOffsetCategoriesRequest() 51 | { 52 | $request = new ERestTestRequestHelper(); 53 | 54 | $request['config'] = [ 55 | 'url' => 'http://api/category?offset=2', 56 | 'type' => 'GET', 57 | 'data' => null, 58 | 'headers' => [ 59 | 'X_REST_USERNAME' => 'admin@restuser', 60 | 'X_REST_PASSWORD' => 'admin@Access', 61 | ], 62 | ]; 63 | 64 | $request_response = $request->send(); 65 | $this->assertEquals(4, count(CJSON::decode($request_response)['data']['category'])); 66 | $expected_response = '{"success":true,"message":"Record(s) Found","data":{"totalCount":6,"category":[{"id":"3","name":"cat3","posts":[{"id":"3","title":"title3","content":"content3","create_time":"2013-08-07 10:09:43","author_id":"3"}]},{"id":"4","name":"cat4","posts":[{"id":"4","title":"title4","content":"content4","create_time":"2013-08-07 10:09:44","author_id":"4"}]},{"id":"5","name":"cat5","posts":[{"id":"5","title":"title5","content":"content5","create_time":"2013-08-07 10:09:45","author_id":"5"}]},{"id":"6","name":"cat6","posts":[{"id":"6","title":"title6","content":"content6","create_time":"2013-08-07 10:09:46","author_id":"6"}]}]}}'; 67 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 68 | } 69 | 70 | /** 71 | * testGETResourcesLimitOffsetCategoriesRequest 72 | * 73 | * tests that a GET request for a list of 'Category' resources 74 | * with limit & offset returns the correct response 75 | */ 76 | public function testGETResourcesLimitOffsetCategoriesRequest() 77 | { 78 | $request = new ERestTestRequestHelper(); 79 | 80 | $request['config'] = [ 81 | 'url' => 'http://api/category?limit=2&offset=2', 82 | 'type' => 'GET', 83 | 'data' => null, 84 | 'headers' => [ 85 | 'X_REST_USERNAME' => 'admin@restuser', 86 | 'X_REST_PASSWORD' => 'admin@Access', 87 | ], 88 | ]; 89 | 90 | $request_response = $request->send(); 91 | $this->assertEquals(2, count(CJSON::decode($request_response)['data']['category'])); 92 | $expected_response = '{"success":true,"message":"Record(s) Found","data":{"totalCount":6,"category":[{"id":"3","name":"cat3","posts":[{"id":"3","title":"title3","content":"content3","create_time":"2013-08-07 10:09:43","author_id":"3"}]},{"id":"4","name":"cat4","posts":[{"id":"4","title":"title4","content":"content4","create_time":"2013-08-07 10:09:44","author_id":"4"}]}]}}'; 93 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 94 | } 95 | 96 | /** 97 | * testGETResourcesLimitPostsRequest 98 | * 99 | * tests that a GET request for a list of 'Posts' resources 100 | * with limit returns the correct response 101 | */ 102 | public function testGETResourcesLimitPostsRequest() 103 | { 104 | $request = new ERestTestRequestHelper(); 105 | 106 | $request['config'] = [ 107 | 'url' => 'http://api/post?limit=1', 108 | 'type' => 'GET', 109 | 'data' => null, 110 | 'headers' => [ 111 | 'X_REST_USERNAME' => 'admin@restuser', 112 | 'X_REST_PASSWORD' => 'admin@Access', 113 | ], 114 | ]; 115 | 116 | $request_response = $request->send(); 117 | $this->assertEquals(1, count(CJSON::decode($request_response)['data']['post'])); 118 | $expected_response = '{"success":true,"message":"Record(s) Found","data":{"totalCount":6,"post":[{"id":"1","title":"title1","content":"content1","create_time":"2013-08-07 10:09:41","author_id":"1","categories":[{"id":"1","name":"cat1"},{"id":"2","name":"cat2"}],"author":{"id":"1","username":"username1","password":"password1","email":"email@email1.com"}}]}}'; 119 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 120 | } 121 | 122 | /** 123 | * testGETResourcesOffsetPostsRequest 124 | * 125 | * tests that a GET request for a list of 'Post' resources 126 | * with offset returns the correct response 127 | */ 128 | public function testGETResourcesOffsetPostsRequest() 129 | { 130 | $request = new ERestTestRequestHelper(); 131 | 132 | $request['config'] = [ 133 | 'url' => 'http://api/post?offset=5', 134 | 'type' => 'GET', 135 | 'data' => null, 136 | 'headers' => [ 137 | 'X_REST_USERNAME' => 'admin@restuser', 138 | 'X_REST_PASSWORD' => 'admin@Access', 139 | ], 140 | ]; 141 | 142 | $request_response = $request->send(); 143 | $this->assertEquals(1, count(CJSON::decode($request_response)['data']['post'])); 144 | $expected_response = '{"success":true,"message":"Record(s) Found","data":{"totalCount":6,"post":[{"id":"6","title":"title6","content":"content6","create_time":"2013-08-07 10:09:46","author_id":"6","categories":[{"id":"6","name":"cat6"}],"author":{"id":"6","username":"username6","password":"password6","email":"email@email6.com"}}]}}'; 145 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 146 | } 147 | 148 | /** 149 | * testGETResourcesLimitOffsetPostsRequest 150 | * 151 | * tests that a GET request for a list of 'Post' resources 152 | * with limit & offset returns the correct response 153 | */ 154 | public function testGETResourcesLimitOffsetPostsRequest() 155 | { 156 | $request = new ERestTestRequestHelper(); 157 | 158 | $request['config'] = [ 159 | 'url' => 'http://api/post?limit=1&offset=2', 160 | 'type' => 'GET', 161 | 'data' => null, 162 | 'headers' => [ 163 | 'X_REST_USERNAME' => 'admin@restuser', 164 | 'X_REST_PASSWORD' => 'admin@Access', 165 | ], 166 | ]; 167 | 168 | $request_response = $request->send(); 169 | $this->assertEquals(1, count(CJSON::decode($request_response)['data']['post'])); 170 | $expected_response = '{"success":true,"message":"Record(s) Found","data":{"totalCount":6,"post":[{"id":"3","title":"title3","content":"content3","create_time":"2013-08-07 10:09:43","author_id":"3","categories":[{"id":"3","name":"cat3"}],"author":{"id":"3","username":"username3","password":"password3","email":"email@email3.com"}}]}}'; 171 | $this->assertJsonStringEqualsJsonString($request_response, $expected_response); 172 | } 173 | } 174 | --------------------------------------------------------------------------------