Skip to content

Commit

Permalink
Update for changes to API v1.0.0 (CO-2110)
Browse files Browse the repository at this point in the history
  • Loading branch information
Benn Oshrin committed Jun 30, 2021
1 parent 8a8ebd4 commit d772dba
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 64 deletions.
1 change: 1 addition & 0 deletions app/config/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
$routes->put('/api/:matchgrid_id/v1/people/:sor/:sorid', ['controller' => 'TierApi', 'action' => 'match']);
$routes->post('/api/:matchgrid_id/v1/people/:sor/:sorid', ['controller' => 'TierApi', 'action' => 'search']);
// This doesn't match and we end up in current(), so we just check there
// Also, as of API v1.0.0, search over GET has been removed
// $routes->get('/api/:matchgrid_id/v1/people/:sor/:sorid?*', ['controller' => 'TierApi', 'action' => 'search']);
$routes->delete('/api/:matchgrid_id/v1/people/:sor/:sorid', ['controller' => 'TierApi', 'action' => 'remove']);
$routes->get('/api/:matchgrid_id/v1/people/:sor/:sorid', ['controller' => 'TierApi', 'action' => 'current']);
Expand Down
19 changes: 12 additions & 7 deletions app/src/Command/DatabaseCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* limitations under the License.
*
* @link http://www.internet2.edu/comanage COmanage Project
* @package match
* @package common
* @since COmanage Common v1.0.0
* @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
*/
Expand Down Expand Up @@ -54,7 +54,7 @@ class DatabaseCommand extends Command {
* @return ConsoleOptionParser ConsoleOptionParser
*/

protected function buildOptionParser(ConsoleOptionParser $parser) {
protected function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser {
$parser->addOption('not', [
'short' => 'n',
'boolean' => true,
Expand All @@ -67,7 +67,7 @@ protected function buildOptionParser(ConsoleOptionParser $parser) {
/**
* Execute the Database Command.
*
* @since COmanage Match v1.0.0, COmanage Registry v5.0.0
* @since COmanage Match v1.0.0, COmanage Registry v6.0.0
* @param Arguments $args Command Arguments
* @param ConsoleIo $io Console IO
* @throws RuntimeException
Expand All @@ -93,6 +93,8 @@ public function execute(Arguments $args, ConsoleIo $io) {
throw new \RuntimeException(__($COmponent.'.er.file', [$schemaFile]));
}

$io->out(__($COmponent.'.cmd.db.schema', [$schemaFile]));

$json = file_get_contents($schemaFile);

$schemaConfig = json_decode($json);
Expand Down Expand Up @@ -231,8 +233,8 @@ public function execute(Arguments $args, ConsoleIo $io) {

try {
// We manually call compare so we can get the SchemaDiff object. We need
// this for toSaveSql(), which won't drop undocumented tables (like the
// matchgrids, which are dynamically created and so won't be in the
// this for toSaveSql(), which we use to avoid dropping undocumented tables
// (like the matchgrids, which are dynamically created and so won't be in the
// schema file).
// $diffSql = $curSchema->getMigrateToSql($schema, $conn->getDatabasePlatform());
$comparator = new Comparator();
Expand All @@ -245,12 +247,13 @@ public function execute(Arguments $args, ConsoleIo $io) {
// needs to be fixed.

foreach($diffSql as $sql) {
// XXX At some point do this only if $verbose
$io->out($sql);

if($cfg['driver'] == 'Cake\Database\Driver\Postgres'
&& preg_match("/^DROP SEQUENCE [a-z]*_id_seq/", $sql)) {
// Remove the DROP SEQUENCE statements in $fromSql because they're Postgres automagic
// being misinterpretted. (Note toSaveSql might mask this now.)
// being misinterpreted. (Note toSaveSql might mask this now.)
// XXX Maybe debug and file a PR to not emit DROP SEQUENCE on PG for autoincrementesque fields?
$io->out("Skipping sequence drop");
} else {
Expand All @@ -262,7 +265,9 @@ public function execute(Arguments $args, ConsoleIo $io) {
}

if(!$doSQL) {
$io->out('** SQL NOT EXECUTED **');
$io->out(__($COmponent.'.cmd.db.noop'));
} else {
$io->out(__($COmponent.'.cmd.db.ok'));
}
}
catch(\Exception $e) {
Expand Down
18 changes: 7 additions & 11 deletions app/src/Controller/TierApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public function current() {
// This is actually a Search Only request via GET, but routes.php doesn't
// quite want to send the request to search(). Regardless, we don't
// (currently) support search over GET, so throw an error.
// And as of API v1.0.0, search over GET has been removed.

throw new \Cake\Http\Exception\MethodNotAllowedException("GET not supported for Search Only, use POST instead");
}
Expand Down Expand Up @@ -455,7 +456,7 @@ protected function doRemove(\App\Lib\Match\MatchService $MatchService) {
}

/**
* Handle an API Match Request request, ie: GET /v1/matchRequest/id
* Handle an API Match Request request, ie: GET /v1/matchRequests/id
*
* @since COmanage Match v1.0.0
* @param MatchService $MatchService Match Service
Expand All @@ -474,7 +475,7 @@ protected function doViewMatchRequest(\App\Lib\Match\MatchService $MatchService)
// Parse the original request
$origReq = $results->getResultsForJson('current');

if(!empty($origReq['referenceId'])) {
if(!empty($origReq['meta']['referenceId'])) {
// This is a resolved request, so handle it a bit differently
$this->statusCode = 200;
$this->result = $origReq;
Expand All @@ -487,16 +488,11 @@ protected function doViewMatchRequest(\App\Lib\Match\MatchService $MatchService)
// the moment we don't try to catch that.
$this->statusCode = 300;

// Extract the SOR and SORID
$sor = $origReq['sorAttributes']['sor'];
$sorid = null;
$this->result['matchRequest'] = $this->request->getParam('id');

foreach($origReq['sorAttributes']['identifiers'] as $id) {
if($id['type'] == 'sor') {
$sorid = $id['identifier'];
break;
}
}
// Extract the SOR and SORID
$sor = $origReq['meta']['sorLabel'];
$sorid = $origReq['meta']['sorId'];

// Use AttributeManager to parse the current record back into database format for searching
$AttributeManager = new \App\Lib\Match\AttributeManager();
Expand Down
16 changes: 12 additions & 4 deletions app/src/Lib/Match/MatchService.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ public function getRequest(int $id) {
FROM " . $this->mgTable . "
WHERE id=?";

$row = $this->dbc->GetRow($sql, [$id]);
$stmt = $this->dbc->Prepare($sql);

$row = $this->dbc->GetRow($stmt, [$id]);

if($row === false) {
throw new \RuntimeException($this->dbc->errorMsg());
Expand Down Expand Up @@ -301,7 +303,9 @@ public function getSorAttributes(string $sor, string $sorid) {
WHERE sor=?
AND sorid=?";

$attrs = $this->dbc->GetRow($sql, [$sor, $sorid]);
$stmt = $this->dbc->Prepare($sql);

$attrs = $this->dbc->GetRow($stmt, [$sor, $sorid]);

if($attrs === false) {
throw new \RuntimeException($this->dbc->errorMsg());
Expand All @@ -326,7 +330,9 @@ public function getSorIds(string $sor) {
FROM " . $this->mgTable . "
WHERE sor=?";

$sorids = $this->dbc->GetCol($sql, [$sor]);
$stmt = $this->dbc->Prepare($sql);

$sorids = $this->dbc->GetCol($stmt, [$sor]);

if($sorids === false) {
throw new \RuntimeException($this->dbc->errorMsg());
Expand Down Expand Up @@ -446,8 +452,10 @@ public function remove(string $sor, string $sorid) {
AND sorid=?
RETURNING id"; // Postgres SQL Extension

$stmt = $this->dbc->Prepare($sql);

// This should only ever match zero or one rows
$ret = $this->dbc->GetOne($sql, [$sor, $sorid]);
$ret = $this->dbc->GetOne($stmt, [$sor, $sorid]);

if($ret === false) {
throw new \RuntimeException($this->dbc->errorMsg());
Expand Down
104 changes: 62 additions & 42 deletions app/src/Lib/Match/ResultManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,56 @@ public function count() {
return count($this->results);
}

/**
* Filter Metadata attributes in preparation for the generation of a Match Result.
*
* @since COmanage Match v1.0.0
* @param array $parsed Record attributes
* @param string $referenceId Reference ID, if known
* @return array Attributes parsed into 'meta' and 'sorAttributes'
*/

protected function filterMetadata($parsed, $referenceId=null) {
$ret = array();

if($referenceId) {
$ret['meta']['referenceId'] = $referenceId;
}

foreach(array_keys($parsed) as $attr) {
switch($attr) {
case 'matchRequest':
// Force to a string as per the spec (internally we use an int)
$ret['meta'][$attr] = (string)$parsed[$attr];
break;
case 'request_time':
case 'resolution_time':
// Timestamps, format and inflect name
$ret['meta'][\Cake\Utility\Inflector::variable($attr)] = strftime("%FT%TZ",
strtotime($parsed[$attr]));
break;
case 'sor':
$ret['meta']['sorLabel'] = $parsed[$attr];
break;
default:
// Any other attribute is not metadata, so just copy to sorAttributes
$ret['sorAttributes'][$attr] = $parsed[$attr];
break;
}
}

// If an SOR ID is present in an Identifier, copy it to the metadata
// (but leave the original where it was).

$sorId = \Cake\Utility\Hash::extract($parsed, "identifiers.{n}[type=sor].identifier");

if(!empty($sorId)) {
$ret['meta']['sorId'] = $sorId[0];
}

return $ret;
}

/**
* Get the Confidence Mode for this set of results.
*
Expand Down Expand Up @@ -159,7 +209,10 @@ public function getResultsForJson($mode="search") {

foreach($this->results as $referenceId => $sorRow) {
// Note $candidate is not used by mode=pending
$candidate = ['referenceId' => $referenceId];
$candidate = [
'referenceId' => $referenceId,
'sorRecords' => []
];

foreach($sorRow as $rowId => $attrs) {
$parsed = ['matchRequest' => $rowId];
Expand Down Expand Up @@ -205,51 +258,18 @@ public function getResultsForJson($mode="search") {

if($mode == 'current') {
// There should only be one entry, so return it directly
$candidate['sorAttributes'] = $parsed;

// Bump up request and resolution times
$candidate['requestTime'] = strftime("%FT%TZ",
strtotime($candidate['sorAttributes']['request_time']));

unset($candidate['sorAttributes']['request_time']);

if(!empty($candidate['sorAttributes']['resolution_time'])) {
$candidate['resolutionTime'] = strftime("%FT%TZ",
strtotime($candidate['sorAttributes']['resolution_time']));
}
unset($candidate['sorAttributes']['resolution_time']);

return $candidate;
return $this->filterMetadata($parsed, $referenceId);
} elseif($mode == 'pending') {
$ret[$rowId] = ['attributes' => $parsed];

// Bump up request and resolution times
$ret[$rowId]['requestTime'] = strftime("%FT%TZ", strtotime($parsed['request_time']));

unset($ret[$rowId]['attributes']['request_time']);

if(!empty($parsed['resolution_time'])) {
$ret[$rowId]['resolutionTime'] = strftime("%FT%TZ", strtotime($parsed['resolution_time']));
}
unset($ret[$rowId]['attributes']['resolution_time']);

if(!empty($referenceId)) {
$ret[$rowId]['referenceId'] = $referenceId;
}
$ret[$rowId] = $this->filterMetadata($parsed, $referenceId);
} else {
// Bump up request time, there shouldn't be a resolution_time for
// pending requests
$candidate['requestTime'] = strftime("%FT%TZ",
strtotime($parsed['request_time']));

unset($parsed['request_time']);
unset($parsed['resolution_time']);

$candidate['attributes'][] = $parsed;

$ret[] = $candidate;
// Search Reference ID
$candidate['sorRecords'][] = $this->filterMetadata($parsed, $referenceId);
}
}

if($mode != 'pending') {
$ret[] = $candidate;
}
}

return $ret;
Expand Down

0 comments on commit d772dba

Please sign in to comment.