Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
project
/project
smarty/templates_c
.gitmodules
project-*
Expand Down
4 changes: 2 additions & 2 deletions modules/api/php/endpoints/candidates.class.inc
Original file line number Diff line number Diff line change
Expand Up @@ -211,12 +211,12 @@ class Candidates extends Endpoint implements \LORIS\Middleware\ETagCalculator
$candid = \Candidate::createNew(
new \CenterID("$centerid"),
$data['Candidate']['DoB'],
$data['Candidate']['EDC'],
$data['Candidate']['EDC'] ?? null,
$sex,
$pscid,
$project->getId()
);
} catch (\LorisException $e) {
} catch (\LorisException | \InvalidArgumentException | \Exception $e) {
return new \LORIS\Http\Response\JSON\BadRequest($e->getMessage());
}

Expand Down
3 changes: 3 additions & 0 deletions modules/api/php/endpoints/project/project.class.inc
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ class Project extends Endpoint implements \LORIS\Middleware\ETagCalculator
case 'instruments':
$handler = new Instruments($this->_project);
break;
case 'subprojects':
$handler = new Subprojects($this->_project);
break;
case 'visits':
$handler = new Visits($this->_project);
break;
Expand Down
145 changes: 145 additions & 0 deletions modules/api/php/endpoints/project/subproject/subproject.class.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<?php declare(strict_types=1);
/**
* This implements the Subproject page class under Project
*
* PHP Version 7
*
* @category API
* @package Loris
* @author Xavier Lecours Boucher <xavier.lecours@mcin.ca>
* @license http://www.gnu.org/licenses/gpl-3.0.txt GPLv3
* @link https://github.com/aces/Loris
*/
namespace LORIS\api\Endpoints\Project\Subproject;

use \Psr\Http\Message\ServerRequestInterface;
use \Psr\Http\Message\ResponseInterface;
use \LORIS\api\Endpoint;

/**
* A class for handling the /projects/$projectname/subprojects/$subproject
* endpoint.
*
* @category API
* @package Loris
* @author Xavier Lecours Boucher <xavier.lecours@mcin.ca>
* @license http://www.gnu.org/licenses/gpl-3.0.txt GPLv3
* @link https://github.com/aces/Loris
*/
class Subproject extends Endpoint implements \LORIS\Middleware\ETagCalculator
{
/**
* A cache of the results of the endpoint, so that
* it doesn't need to be recalculated for the ETag and handler
*/
private $_cache;

/**
* The requested instrument
*/
private $_subproject;

/**
* Contructor for the subproject endpoint
*
* @param \Subproject $subproject The subproject
*/
public function __construct(\Subproject $subproject)
{
$this->_subproject = $subproject;
}

/**
* Return which methods are supported by this endpoint.
*
* @return array supported HTTP methods
*/
protected function allowedMethods() : array
{
return ['GET'];
}

/**
* Versions of the LORIS API which are supported by this
* endpoint.
*
* @return array a list of supported API versions.
*/
protected function supportedVersions() : array
{
return [
'v0.0.4-dev',
];
}

/**
* Handles a HTTP request
*
* @param ServerRequestInterface $request The incoming PSR7 request
*
* @return ResponseInterface The outgoing PSR7 response
*/
public function handle(ServerRequestInterface $request) : ResponseInterface
{
$pathparts = $request->getAttribute('pathparts');
if (count($pathparts) !== 0) {
return new \LORIS\Http\Response\JSON\NotFound();
}

switch ($request->getMethod()) {
case 'GET':
return $this->_handleGET($request);

case 'OPTIONS':
return (new \LORIS\Http\Response())
->withHeader('Allow', $this->allowedMethods());
default:
return new \LORIS\Http\Response\JSON\MethodNotAllowed(
$this->allowedMethods()
);
}
}

/**
* Create an array representation of this endpoint's reponse body
*
* @return ResponseInterface The outgoing PSR7 response
*/
private function _handleGET(): ResponseInterface
{
if (isset($this->_cache)) {
return $this->_cache;
}

$data = json_decode(json_encode($this->_subproject), true);
$visits = array_reduce(
$this->_subproject->getVisits(),
function ($carry, $item) {
// This is just changing the keys from visit_label to VisitLabel
// It should probably be delegated to a view object.
array_push($carry, ['VisitLabel' => $item['visit_label']]);
return $carry;
},
[]
);

$data['Visits'] = $visits;

$this->_cache = new \LORIS\Http\Response\JsonResponse($data);

return $this->_cache;
}

/**
* Implements the ETagCalculator interface
*
* @param ServerRequestInterface $request The PSR7 incoming request.
*
* @return string etag summarizing value of this request.
*/
public function ETag(ServerRequestInterface $request) : string
{
return md5(json_encode($this->_handleGET($request)->getBody()));
}
}

160 changes: 160 additions & 0 deletions modules/api/php/endpoints/project/subprojects.class.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
<?php declare(strict_types=1);
/**
* This implements the Subprojects endpoint class
*
* PHP Version 7
*
* @category API
* @package Loris
* @license http://www.gnu.org/licenses/gpl-3.0.txt GPLv3
* @link https://github.com/aces/Loris
*/

namespace LORIS\api\Endpoints\Project;

use \Psr\Http\Message\ServerRequestInterface;
use \Psr\Http\Message\ResponseInterface;
use \LORIS\api\Endpoint;

/**
* A class for handling the /projects/{project}/subprojects endpoint.
*
* @category API
* @package Loris
* @license http://www.gnu.org/licenses/gpl-3.0.txt GPLv3
* @link https://github.com/aces/Loris
*/
class Subprojects extends Endpoint implements \LORIS\Middleware\ETagCalculator
{
/**
* A cache of the results of the projects/ endpoint, so that it doesn't
* need to be recalculated for the ETag and handler
*/
private $_cache;

/**
* The requested project
*/
private $_project;

/**
* Contructor
*
* @param \Project $project the requested project
*/
public function __construct(\Project $project)
{
$this->_project = $project;
}

/**
* Return which methods are supported by this endpoint.
*
* @return array supported HTTP methods
*/
protected function allowedMethods() : array
{
return ['GET'];
}

/**
* Versions of the LORIS API which are supported by this
* endpoint.
*
* @return array a list of supported API versions.
*/
protected function supportedVersions() : array
{
return [
'v0.0.4-dev',
];
}

/**
* Handles a HTTP request
*
* @param ServerRequestInterface $request The incoming PSR7 request
*
* @return ResponseInterface The outgoing PSR7 response
*/
public function handle(ServerRequestInterface $request) : ResponseInterface
{
$pathparts = $request->getAttribute('pathparts');
if (count($pathparts) === 0) {
switch ($request->getMethod()) {
case 'GET':
return $this->_handleGET();

case 'OPTIONS':
return (new \LORIS\Http\Response())
->withHeader('Allow', $this->allowedMethods());
default:
return new \LORIS\Http\Response\JSON\MethodNotAllowed(
$this->allowedMethods()
);
}
}

// Delegate to subproject specific endpoint.
$subproject_name = urldecode($pathparts[0] ?? '');

try {
$subproject = $this->_project->getSubproject($subproject_name);
} catch (\NotFound $e) {
return new \LORIS\Http\Response\JSON\NotFound();
}

$endpoint = new Subproject\Subproject($subproject);

// Removing `/subprojects/<subproject_name>` from pathparts.
$pathparts = array_slice($pathparts, 2);
$request = $request->withAttribute('pathparts', $pathparts);

return $endpoint->process($request, $endpoint);
}

/**
* Generates a JSON representation of this projecti subprojects following the API
* specification.
*
* @return ResponseInterface
*/
private function _handleGET(): ResponseInterface
{
if (isset($this->_cache)) {
return $this->_cache;
}

$subprojects = array_map(
function ($subproject) {
return [
'SubprojectID' => $subproject['subprojectId'],
'Title' => $subproject['title'],
'UseEDC' => $subproject['useEDC'],
'WindowDifference' => $subproject['windowDifference'],
'RecruitmentTarget' => $subproject['recruitmentTarget']
];
},
$this->_project->getSubprojects()
);

$array = [
'Subprojects' => $subprojects
];

$this->_cache = new \LORIS\Http\Response\JsonResponse($array);

return $this->_cache;
}
/**
* Implements the ETagCalculator interface
*
* @param ServerRequestInterface $request The PSR7 incoming request.
*
* @return string etag summarizing value of this request.
*/
public function ETag(ServerRequestInterface $request) : string
{
return md5(json_encode($this->_handleGet($request)->getBody()));
}
}
4 changes: 4 additions & 0 deletions modules/api/php/endpoints/projects.class.inc
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ class Projects extends Endpoint implements \LORIS\Middleware\ETagCalculator
return new \LORIS\Http\Response\JSON\NotFound();
}

if (!$project->isAccessibleBy($user)) {
return new \LORIS\Http\Response\JSON\Forbidden();
}

$endpoint = new Project\Project($project);

// Removing `/projects/<project_name>` from pathparts.
Expand Down
Loading