Skip to content

Commit

Permalink
[API] Visit patch request to start next stage
Browse files Browse the repository at this point in the history
  • Loading branch information
laemtl committed Jun 14, 2021
1 parent 6859c08 commit 9291868
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 4 deletions.
2 changes: 0 additions & 2 deletions modules/api/docs/LorisRESTAPI_v0.0.4-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -419,8 +419,6 @@ The JSON object is of the form:
A PUT of the same format but with only the Meta fields will create the VisitLabel
for this candidate, in an unstarted stage if the Visit label provided is valid.
PATCH is not supported for Visit Labels.
It will return a 404 Not Found if the visit label does not exist for this candidate
(as well as anything under the /candidates/$CandID/$VisitLabel hierarchy)
Expand Down
121 changes: 119 additions & 2 deletions modules/api/php/endpoints/candidate/visit/visit.class.inc
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class Visit extends Endpoint implements \LORIS\Middleware\ETagCalculator
{
return [
'GET',
'PATCH',
'PUT',
];
}
Expand Down Expand Up @@ -95,7 +96,6 @@ class Visit extends Endpoint implements \LORIS\Middleware\ETagCalculator
if (!$this->_visit->isAccessibleBy($user)) {
return new \LORIS\Http\Response\JSON\Forbidden('Permission denied');
}

}

$pathparts = $request->getAttribute('pathparts');
Expand All @@ -104,6 +104,9 @@ class Visit extends Endpoint implements \LORIS\Middleware\ETagCalculator
case 'GET':
return $this->_handleGET();

case 'PATCH':
return $this->_handlePATCH($request);

case 'PUT':
return $this->_handlePUT($request);

Expand Down Expand Up @@ -171,10 +174,123 @@ class Visit extends Endpoint implements \LORIS\Middleware\ETagCalculator
);
}

/**
* Handles a PATCH request.
* For now, only support a NextStageDate argument to start next stage.
*
* @param ServerRequestInterface $request The incoming PSR7 request
*
* @return ResponseInterface The outgoing PSR7 response
*/
private function _handlePATCH(ServerRequestInterface $request): ResponseInterface
{
$data = json_decode((string) $request->getBody(), true);
$meta = $data['Meta'] ?? [];
$nextStageDate = $data['NextStageDate'] ?? null;

$requiredfields = [
'CandID',
'Visit',
'Site',
'Battery',
'Project',
];
$diff = array_diff($requiredfields, array_keys($meta));

if (!empty($diff)) {
return new \LORIS\Http\Response\JSON\BadRequest(
'Field(s) missing: ' . implode(', ', $diff)
);
}

if (!$nextStageDate) {
return new \LORIS\Http\Response\JSON\BadRequest(
'There is no stage date specified'
);
}

$date_format = 'YYYY-MM-DD';
$date = DateTime::createFromFormat($date_format, $nextStageDate);
if (!($date && $date->format($date_format) === $nextStageDate)) {
return new \LORIS\Http\Response\JSON\BadRequest(
'The date specified is invalid. Date must be of the form YYYY-MM-DD'
);
}

if ($nextStageDate > date($date_format)) {
return new \LORIS\Http\Response\JSON\BadRequest(
'The date specified must be not later than today'
);
}

$sessionID = \NDB_Factory::singleton()->database()->pselectOne(
"SELECT ID FROM session
WHERE CandID=:cid AND Visit_label=:vl",
[
"cid" => $meta['CandID'],
"vl" => $meta['Visit']
]
);

if (empty($sessionID)) {
return new \LORIS\Http\Response\JSON\BadRequest(
"There is no Session with the provided criteria"
);
}

$session = \TimePoint::singleton(new \SessionID($sessionID));
if ($session->getCurrentStage() !== 'Not Started') {
return new \LORIS\Http\Response\JSON\Conflict(
'This visit is already started'
);
}

$newStage = $session->getNextStage();
if (!$newStage) {
return new \LORIS\Http\Response\JSON\Conflict(
"Next stage is null"
);
}

// start that stage
$session->startStage($newStage);

// set the date for the new stage
$session->setData(["Date_".$newStage => $nextStageDate]);

// create a new battery object && new battery
$candidate = \Candidate::singleton($session->getCandID());

// First visit ?
$firstVisit = false;
try {
if ($candidate->getFirstVisit() == $session->getVisitLabel()) {
$firstVisit = true;
}
} catch (\LorisException $e) {
}

$battery = new \NDB_BVL_Battery;
// select a specific time point (sessionID) for the battery
$battery->selectBattery(new \SessionID($sessionID));

// add instruments to the time point
$battery->createBattery(
$request->getAttribute("loris"),
$session->getSubprojectID(),
$newStage,
$session->getVisitLabel(),
$session->getCenterID(),
$firstVisit
);

return new \LORIS\Http\Response\JSON\OK();
}

/**
* Handles a PUT request that creates or replace a candidate visit
*
* TODO: There is no way to validate the the visit_label in the url
* TODO: There is no way to validate the visit_label in the url
* fits the json data of the request because it is removed from the
* pathparts in the calling class. The correct way to do it would be
* to pass a "light" timepoint class that contains the visit_label but
Expand Down Expand Up @@ -255,6 +371,7 @@ class Visit extends Endpoint implements \LORIS\Middleware\ETagCalculator
$timepoint = \NDB_Factory::singleton()->timepoint(
new \SessionID(strval($sessionid))
);

if ($timepoint->getCurrentStage() !== 'Not Started') {
return new \LORIS\Http\Response\JSON\Conflict(
'This visit is already started'
Expand Down

0 comments on commit 9291868

Please sign in to comment.