From a61d3452819d640e3c24463fc614786a06a1088a Mon Sep 17 00:00:00 2001 From: James Mullaney Date: Tue, 11 Feb 2014 10:35:00 +0000 Subject: [PATCH 1/5] ADded DocumentType constants --- app/controllers/xapi/ActivityController.php | 6 ++++-- app/controllers/xapi/StateController.php | 6 ++++-- app/locker/repository/Document/DocumentType.php | 7 +++++++ 3 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 app/locker/repository/Document/DocumentType.php diff --git a/app/controllers/xapi/ActivityController.php b/app/controllers/xapi/ActivityController.php index 32935d7af3..946aa7323c 100644 --- a/app/controllers/xapi/ActivityController.php +++ b/app/controllers/xapi/ActivityController.php @@ -7,7 +7,7 @@ class ActivityController extends BaseController { /** * Document Repository */ - protected $document; + protected $document, $type; /** * Construct @@ -19,6 +19,8 @@ public function __construct(Document $document){ $this->document = $document; $this->beforeFilter('@getLrs'); + $this->document_type = DocumentType::STATE; + } /** @@ -47,7 +49,7 @@ public function store(){ //validate if( $this->validate( $profile ) && $this->validateActivity( $profile['contents'] ) ){ - $store = $this->document->store( $this->lrs->_id, $profile['id'], $profile['contents'], 'activityProfile' ); + $store = $this->document->store( $this->lrs->_id, $profile['id'], $profile['contents'], $this->document_type ); if( $store ){ return \Response::json( array( 'ok', 204 ) ); diff --git a/app/controllers/xapi/StateController.php b/app/controllers/xapi/StateController.php index 9d74d8e7f2..dcb455f795 100644 --- a/app/controllers/xapi/StateController.php +++ b/app/controllers/xapi/StateController.php @@ -7,7 +7,7 @@ class StateController extends BaseController { /** * Document Repository */ - protected $document; + protected $document, $document_type; /** * Construct @@ -19,6 +19,8 @@ public function __construct(Document $document){ $this->document = $document; $this->beforeFilter('@getLrs'); + $this->document_type = DocumentType::STATE; + } @@ -53,7 +55,7 @@ public function store(){ //validate if( $this->validate( $state ) && $this->validateState( $state['contents'] ) ){ - $store = $this->document->store( $this->lrs->_id, $state['id'], $state['contents'], 'state' ); + $store = $this->document->store( $this->lrs->_id, $state['id'], $state['contents'], $this->document_type ); if( $store ){ return \Response::json( array( 'ok', 204 ) ); diff --git a/app/locker/repository/Document/DocumentType.php b/app/locker/repository/Document/DocumentType.php new file mode 100644 index 0000000000..69143856b6 --- /dev/null +++ b/app/locker/repository/Document/DocumentType.php @@ -0,0 +1,7 @@ + Date: Tue, 11 Feb 2014 10:44:33 +0000 Subject: [PATCH 2/5] DocumentType namespacing --- app/controllers/xapi/ActivityController.php | 1 + app/controllers/xapi/StateController.php | 1 + 2 files changed, 2 insertions(+) diff --git a/app/controllers/xapi/ActivityController.php b/app/controllers/xapi/ActivityController.php index 946aa7323c..6f809f8011 100644 --- a/app/controllers/xapi/ActivityController.php +++ b/app/controllers/xapi/ActivityController.php @@ -1,6 +1,7 @@ Date: Tue, 11 Feb 2014 15:27:28 +0000 Subject: [PATCH 3/5] Added DocumentController and new methods to check for parameters --- app/controllers/xapi/ActivityController.php | 15 +--- app/controllers/xapi/DocumentController.php | 85 +++++++++++++++++++ app/controllers/xapi/StateController.php | 72 ++++++---------- .../Document/DocumentRepository.php | 4 +- .../Document/EloquentDocumentRepository.php | 35 ++++++-- 5 files changed, 143 insertions(+), 68 deletions(-) create mode 100644 app/controllers/xapi/DocumentController.php diff --git a/app/controllers/xapi/ActivityController.php b/app/controllers/xapi/ActivityController.php index 6f809f8011..01cd458876 100644 --- a/app/controllers/xapi/ActivityController.php +++ b/app/controllers/xapi/ActivityController.php @@ -3,12 +3,7 @@ use \Locker\Repository\Document\DocumentRepository as Document; use Locker\Repository\Document\DocumentType as DocumentType; -class ActivityController extends BaseController { - - /** - * Document Repository - */ - protected $document, $type; +class ActivityController extends DocumentController { /** * Construct @@ -16,12 +11,8 @@ class ActivityController extends BaseController { * @param DocumentRepository $document */ public function __construct(Document $document){ - - $this->document = $document; - $this->beforeFilter('@getLrs'); - - $this->document_type = DocumentType::STATE; - + parent::__construct($document); + $this->document_type = DocumentType::ACTIVITY; } /** diff --git a/app/controllers/xapi/DocumentController.php b/app/controllers/xapi/DocumentController.php new file mode 100644 index 0000000000..182350f925 --- /dev/null +++ b/app/controllers/xapi/DocumentController.php @@ -0,0 +1,85 @@ +document = $document; + $this->beforeFilter('@getLrs'); + $this->beforeFilter('@setParameters'); + } + + /** + * Used to filter required paramters on an incoming request + * @param array $required a list of expected parameters and allows types + * + */ + public function checkParams( $required = array(), $optional=array(), $data = null ){ + + $return_data = array(); + + if( is_null($data) ){ + $data = $this->params; + } + + //loop through all required parameters + foreach( $required as $name=>&$expected_types ){ + //check the parameter has been passed + if( !isset($data[$name]) ){ + \App::abort(400, 'Required parameter is missing - '.$name ); + } + + if( !empty($expected_types) ){ + $this->checkTypes( $name, $data[$name], $expected_types ); + } + + $return_data[$name] = $data[$name]; + } + + foreach( $optional as $name=>$expected_types ){ + if( isset($data[$name]) ){ + if( !empty($expected_types) ){ + $this->checkTypes( $name, $data[$name], $expected_types ); + } + + $return_data[$name] = $data[$name]; + } + } + + return $return_data; + } + + public function checkTypes($name, $value, $expected_types ){ + //convert expected type string into array + if( is_string($expected_types) ) $expected_types = array($expected_types); + + //get the paramter type + $type = gettype($value); + + //error on any unexpected parameter types + if( !in_array( $type, $expected_types ) ){ + \App::abort(400, sprintf( "`%s` is not an accepted type - expected %s - received %s", $name, implode(',', $expected_types), $type ) ); + } + + //Check if we haev requested a JSON parameter + if( in_array('json', $expected_types ) ){ + if( !is_object( json_decode($value) ) ){ + \App::abort(400, sprintf( "`%s` is not an accepted type - expected a JSON formatted string", $name ) ); + } + } + } + + + +} diff --git a/app/controllers/xapi/StateController.php b/app/controllers/xapi/StateController.php index 8fbb0d53a5..ec7eefbca1 100644 --- a/app/controllers/xapi/StateController.php +++ b/app/controllers/xapi/StateController.php @@ -3,12 +3,7 @@ use \Locker\Repository\Document\DocumentRepository as Document; use Locker\Repository\Document\DocumentType as DocumentType; -class StateController extends BaseController { - - /** - * Document Repository - */ - protected $document, $document_type; +class StateController extends DocumentController { /** * Construct @@ -17,8 +12,7 @@ class StateController extends BaseController { */ public function __construct(Document $document){ - $this->document = $document; - $this->beforeFilter('@getLrs'); + parent::__construct($document); $this->document_type = DocumentType::STATE; @@ -33,11 +27,13 @@ public function __construct(Document $document){ * @return Response */ public function index(){ + $data = $this->checkParams(array( + 'activityId' => 'string', + 'actor' => array('string', 'json'), + ), $this->params ); - $documents = $this->document->all(); - + $documents = $this->document->all( $this->lrs->_id, $data['activityId'], $data['actor'] ); return \Response::json( $documents->toArray() ); - } /** @@ -47,25 +43,26 @@ public function index(){ */ public function store(){ - $request = \Request::instance(); - $incoming_data = $request->getContent(); + $state = $this->checkParams( + array( + 'activityId' => 'string', + 'actor' => array('string', 'json'), + 'stateId' => 'string', + 'content' => '' + ), + array( + 'registration' => 'string' + ), + $this->params + ); - //convert to array - $state = json_decode($incoming_data, TRUE); - //validate - if( $this->validate( $state ) && $this->validateState( $state['contents'] ) ){ - - $store = $this->document->store( $this->lrs->_id, $state['id'], $state['contents'], $this->document_type ); - - if( $store ){ - return \Response::json( array( 'ok', 204 ) ); - } + $store = $this->document->store( $this->lrs->_id, $state, $this->document_type ); + if( $store ){ + return \Response::json( array( 'ok', 204 ) ); } - return \Response::json( array( 'error', 400 ) ); - } /** @@ -78,7 +75,7 @@ public function show( $stateId ){ $document = $this->document->find( $this->lrs->_id, $stateId ); - return \Response::json( $document->toArray() ); + return \Response::json( $document->toArray() ); } @@ -112,29 +109,8 @@ public function destroy($id) **/ public function validateState( $data ){ - //now check required keys exist - if( !array_key_exists('activityId', $data) - || !array_key_exists('actor', $data) - || !array_key_exists('stateId', $data)){ - return false; - } - - //check activityId is string - if( !is_string( $data['activityId'] ) ){ - return false; - } - - //check actor is array - if( !is_array( $data['actor'] ) ){ - return false; - } - - //check stateId is string - if( !is_string( $data['stateId'] ) ){ - return false; - } - return true; + } diff --git a/app/locker/repository/Document/DocumentRepository.php b/app/locker/repository/Document/DocumentRepository.php index 0cc2afe999..bac8b59059 100644 --- a/app/locker/repository/Document/DocumentRepository.php +++ b/app/locker/repository/Document/DocumentRepository.php @@ -2,10 +2,10 @@ interface DocumentRepository { - public function store( $lrs, $id, $contents, $apitype ); + public function store( $lrs, $data, $apitype ); public function find( $lrs, $stateId ); - public function all( $lrs, $activityid ); + public function all( $lrs, $activityId, $actor ); } \ No newline at end of file diff --git a/app/locker/repository/Document/EloquentDocumentRepository.php b/app/locker/repository/Document/EloquentDocumentRepository.php index 6d42b46fe2..e07027265a 100644 --- a/app/locker/repository/Document/EloquentDocumentRepository.php +++ b/app/locker/repository/Document/EloquentDocumentRepository.php @@ -20,10 +20,11 @@ public function __construct( DocumentAPI $documentapi ){ } - public function all( $lrs, $activityId ){ + public function all( $lrs, $activityId, $actor ){ return $this->documentapi->where('lrs', $lrs) - ->where('contents.activityId', $activityId) - ->select('contents.stateId') + ->where('activityId', $activityId) + ->where('actor', json_decode($actor)) + ->select('stateId') ->get(); } @@ -33,14 +34,36 @@ public function find( $lrs, $stateId ){ ->first(); } - public function store( $lrs, $id, $contents, $apitype ){ + public function store( $lrs, $data, $apitype ){ $new_document = $this->documentapi; $new_document->lrs = $lrs; //LL specific $new_document->apitype = $apitype; //LL specific - $new_document->id = $id; + + switch( $new_document->apitype ){ + case DocumentType::STATE: + $new_document->activityId = $data['activityId']; + $new_document->actor = json_decode($data['actor']); + $new_document->stateId = $data['stateId']; + $new_document->registration = isset($data['registration']) ? $data['registration'] : null; + break; + case DocumentType::ACTIVITY: + $new_document->activityId = $data['activityId']; + $new_document->profileId = $data['profileId']; + break; + case DocumentType::AGENT: + + break; + } + + //@todo add update as per spec https://github.com/adlnet/xAPI-Spec/blob/master/xAPI.md#miscdocument - $new_document->contents = $contents; + if( is_object( json_decode($data['content'] ) ) ){ + $new_document->content = json_decode($data['content']); + } else { + $new_document->content = "..path/to/file/to.do"; + } + if( $new_document->save() ){ return true; From 9b65c1c7dfb85d99825920381cf353ecca95c22a Mon Sep 17 00:00:00 2001 From: James Mullaney Date: Tue, 11 Feb 2014 15:34:41 +0000 Subject: [PATCH 4/5] Added contributor details and changed field to documentType --- README.md | 1 + app/controllers/xapi/StateController.php | 2 +- .../repository/Document/EloquentDocumentRepository.php | 9 +++++---- composer-public.json | 5 +++++ 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 499171bc61..84c785b0a0 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ There are several ways you can get involved with Learning Locker. Visit our site * HT2 (http://ht2.co.uk) * Dave Tosh (http://davetosh.com) +* James Mullaney [mailto:james@ht2.co.uk](james@ht2.co.uk) #### Copyright diff --git a/app/controllers/xapi/StateController.php b/app/controllers/xapi/StateController.php index ec7eefbca1..923553d544 100644 --- a/app/controllers/xapi/StateController.php +++ b/app/controllers/xapi/StateController.php @@ -32,7 +32,7 @@ public function index(){ 'actor' => array('string', 'json'), ), $this->params ); - $documents = $this->document->all( $this->lrs->_id, $data['activityId'], $data['actor'] ); + $documents = $this->document->all( $this->lrs->_id, $this->document_type, $data['activityId'], $data['actor'] ); return \Response::json( $documents->toArray() ); } diff --git a/app/locker/repository/Document/EloquentDocumentRepository.php b/app/locker/repository/Document/EloquentDocumentRepository.php index e07027265a..b20f83d53f 100644 --- a/app/locker/repository/Document/EloquentDocumentRepository.php +++ b/app/locker/repository/Document/EloquentDocumentRepository.php @@ -20,8 +20,9 @@ public function __construct( DocumentAPI $documentapi ){ } - public function all( $lrs, $activityId, $actor ){ + public function all( $lrs, $documentType, $activityId, $actor ){ return $this->documentapi->where('lrs', $lrs) + ->where('documentType', $documentType) ->where('activityId', $activityId) ->where('actor', json_decode($actor)) ->select('stateId') @@ -34,13 +35,13 @@ public function find( $lrs, $stateId ){ ->first(); } - public function store( $lrs, $data, $apitype ){ + public function store( $lrs, $data, $documentType ){ $new_document = $this->documentapi; $new_document->lrs = $lrs; //LL specific - $new_document->apitype = $apitype; //LL specific + $new_document->documentType = $documentType; //LL specific - switch( $new_document->apitype ){ + switch( $new_document->documentType ){ case DocumentType::STATE: $new_document->activityId = $data['activityId']; $new_document->actor = json_decode($data['actor']); diff --git a/composer-public.json b/composer-public.json index c5cff7235a..4be658d8d8 100644 --- a/composer-public.json +++ b/composer-public.json @@ -9,6 +9,11 @@ "name": "HT2", "email": "hello@ht2.co.uk", "role": "sponsor" + }, + { + "name": "James Mullaney", + "email": "james@ht2.co.uk", + "role": "Developer" } ], "name": "learninglocker/learninglocker", From d852d8f7c49a785ae4e12fc8ed19f8410ad35b1d Mon Sep 17 00:00:00 2001 From: James Mullaney Date: Tue, 11 Feb 2014 15:37:34 +0000 Subject: [PATCH 5/5] Updated DocumentRepository interface --- app/locker/repository/Document/DocumentRepository.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/locker/repository/Document/DocumentRepository.php b/app/locker/repository/Document/DocumentRepository.php index bac8b59059..fc361ce447 100644 --- a/app/locker/repository/Document/DocumentRepository.php +++ b/app/locker/repository/Document/DocumentRepository.php @@ -2,10 +2,10 @@ interface DocumentRepository { - public function store( $lrs, $data, $apitype ); + public function store( $lrs, $data, $documentType ); public function find( $lrs, $stateId ); - public function all( $lrs, $activityId, $actor ); + public function all( $lrs, $documentType, $activityId, $actor ); } \ No newline at end of file