Skip to content

Commit

Permalink
Merge pull request #982 from NatLibFi/issue600-rest-changed-concepts
Browse files Browse the repository at this point in the history
Listing new and modified concepts for a vocabulary in the REST API
  • Loading branch information
joelit authored Jun 15, 2020
2 parents 3f43c24 + a907434 commit c76c510
Show file tree
Hide file tree
Showing 11 changed files with 389 additions and 27 deletions.
55 changes: 55 additions & 0 deletions controller/RestController.php
Original file line number Diff line number Diff line change
Expand Up @@ -1063,4 +1063,59 @@ public function related($request)
$ret = $this->transformPropertyResults($request->getUri(), $request->getLang(), $related, "related", "skos:related");
return $this->returnJson($ret);
}

/**
* Used for querying new concepts in the vocabulary
* @param Request $request
* @return object json-ld wrapped list of changed concepts
*/
public function newConcepts($request)
{
$offset = ($request->getQueryParam('offset') && is_numeric($request->getQueryParam('offset')) && $request->getQueryParam('offset') >= 0) ? $request->getQueryParam('offset') : 0;
$limit = ($request->getQueryParam('limit') && is_numeric($request->getQueryParam('limit')) && $request->getQueryParam('limit') >= 0) ? $request->getQueryParam('limit') : 200;

return $this->changedConcepts($request, 'dc:created', $offset, $limit);
}

/**
* Used for querying modified concepts in the vocabulary
* @param Request $request
* @return object json-ld wrapped list of changed concepts
*/
public function modifiedConcepts($request)
{
$offset = ($request->getQueryParam('offset') && is_numeric($request->getQueryParam('offset')) && $request->getQueryParam('offset') >= 0) ? $request->getQueryParam('offset') : 0;
$limit = ($request->getQueryParam('limit') && is_numeric($request->getQueryParam('limit')) && $request->getQueryParam('limit') >= 0) ? $request->getQueryParam('limit') : 200;

return $this->changedConcepts($request, 'dc:modified', $offset, $limit);
}

/**
* Used for querying changed concepts in the vocabulary
* @param Request $request
* @param int $offset starting index offset
* @param int $limit maximum number of concepts to return
* @return object json-ld wrapped list of changed concepts
*/
private function changedConcepts($request, $prop, $offset, $limit)
{
$changeList = $request->getVocab()->getChangeList($prop, $request->getLang(), $offset, $limit);

$simpleChangeList = array();
foreach($changeList as $conceptInfo) {
if (array_key_exists('date', $conceptInfo)) {
$simpleChangeList[] = array( 'uri' => $conceptInfo['uri'],
'prefLabel' => $conceptInfo['prefLabel'],
'date' => $conceptInfo['date']->format("Y-m-d\TH:i:sO") );
}
}
return $this->returnJson(array_merge_recursive($this->context,
array('@context' => array( '@language' => $request->getLang(),
'prefLabel' => 'skos:prefLabel',
'xsd' => 'http://www.w3.org/2001/XMLSchema#',
'date' => array( '@id' => 'http://purl.org/dc/terms/date', '@type' => 'http://www.w3.org/2001/XMLSchema#dateTime') )
),
array('changeList' => $simpleChangeList)));

}
}
43 changes: 37 additions & 6 deletions controller/WebController.php
Original file line number Diff line number Diff line change
Expand Up @@ -559,22 +559,53 @@ public function invokeGenericErrorPage($request, $message = null)
*/
public function invokeChangeList($request, $prop='dc:created')
{
// set language parameters for gettext
$this->setLanguageProperties($request->getLang());
$vocab = $request->getVocab();
$offset = ($request->getQueryParam('offset') && is_numeric($request->getQueryParam('offset')) && $request->getQueryParam('offset') >= 0) ? $request->getQueryParam('offset') : 0;
$changeList = $vocab->getChangeList($prop, $request->getContentLang(), $request->getLang(), $offset);
$limit = ($request->getQueryParam('limit') && is_numeric($request->getQueryParam('limit')) && $request->getQueryParam('limit') >= 0) ? $request->getQueryParam('limit') : 200;

$changeList = $this->getChangeList($request, $prop, $offset, $limit);
$bydate = $this->formatChangeList($changeList, $request->getLang());

// load template
$template = $this->twig->loadTemplate('changes.twig');

// render template
echo $template->render(
array(
'vocab' => $vocab,
'vocab' => $request->getVocab(),
'languages' => $this->languages,
'request' => $request,
'changeList' => $changeList)
'changeList' => $bydate)
);
}
/**
* Gets the list of newest concepts for a vocabulary according to timestamp indicated by a property
* @param Request $request
* @param string $prop the name of the property eg. 'dc:modified'.
* @param int $offset starting index offset
* @param int $limit maximum number of concepts to return
* @return Array list of concepts
*/
public function getChangeList($request, $prop, $offset=0, $limit=200)
{
// set language parameters for gettext
$this->setLanguageProperties($request->getLang());

return $request->getVocab()->getChangeList($prop, $request->getContentLang(), $offset, $limit);
}

/**
* Formats the list of concepts as labels arranged by modification month
* @param Array $changeList
* @param string $lang the language for displaying dates in the change list
*/
public function formatChangeList($changeList, $lang)
{
$formatByDate = array();
foreach($changeList as $concept) {
$concept['datestring'] = Punic\Calendar::formatDate($concept['date'], 'medium', $lang);
$formatByDate[Punic\Calendar::getMonthName($concept['date'], 'wide', $lang, true) . Punic\Calendar::format($concept['date'], ' y', $lang) ][strtolower($concept['prefLabel'])] = $concept;
}
return $formatByDate;
}

}
14 changes: 5 additions & 9 deletions model/Vocabulary.php
Original file line number Diff line number Diff line change
Expand Up @@ -615,19 +615,15 @@ public function verifyVocabularyLanguage($lang)

/**
* Returns a list of recently changed or entirely new concepts.
* @param string $prop the property uri pointing to timestamps, eg. 'dc:modified'
* @param string $clang content language for the labels
* @param string $lang UI language for the dates
* @param int $offset starting index offset
* @param int $limit maximum number of concepts to return
* @return Array
*/
public function getChangeList($prop, $clang, $lang, $offset)
public function getChangeList($prop, $clang, $offset, $limit)
{
$changelist = $this->getSparql()->queryChangeList($clang, $offset, $prop);
$bydate = array();
foreach($changelist as $concept) {
$concept['datestring'] = Punic\Calendar::formatDate($concept['date'], 'medium', $lang);
$bydate[Punic\Calendar::getMonthName($concept['date'], 'wide', $lang, true) . Punic\Calendar::format($concept['date'], ' y', $lang) ][strtolower($concept['prefLabel'])] = $concept;
}
return $bydate;
return $this->getSparql()->queryChangeList($prop, $clang, $offset, $limit);
}

public function getTitle($lang=null) {
Expand Down
23 changes: 17 additions & 6 deletions model/sparql/GenericSparql.php
Original file line number Diff line number Diff line change
Expand Up @@ -2213,11 +2213,13 @@ public function listConceptGroupContents($groupClass, $group, $lang,$showDepreca

/**
* Generates the sparql query for queryChangeList.
* @param string $lang language of labels to return.
* @param string $prop the property uri pointing to timestamps, eg. 'dc:modified'
* @param string $lang language of labels to return
* @param int $offset offset of results to retrieve; 0 for beginning of list
* @param int $limit maximum number of results to return
* @return string sparql query
*/
private function generateChangeListQuery($lang, $offset, $prop) {
private function generateChangeListQuery($prop, $lang, $offset, $limit=200) {
$fcl = $this->generateFromClause();
$offset = ($offset) ? 'OFFSET ' . $offset : '';

Expand All @@ -2230,8 +2232,9 @@ private function generateChangeListQuery($lang, $offset, $prop) {
FILTER (langMatches(lang(?label), '$lang'))
}
ORDER BY DESC(YEAR(?date)) DESC(MONTH(?date)) LCASE(?label)
LIMIT 200 $offset
LIMIT $limit $offset
EOQ;

return $query;
}

Expand All @@ -2249,7 +2252,12 @@ private function transformChangeListResults($result) {
}

if (isset($row->date)) {
$concept['date'] = $row->date->getValue();
try {
$concept['date'] = $row->date->getValue();
} catch (Exception $e) {
//don't record concepts with malformed dates e.g. 1986-21-00
continue;
}
}

$ret[] = $concept;
Expand All @@ -2259,12 +2267,15 @@ private function transformChangeListResults($result) {

/**
* return a list of recently changed or entirely new concepts
* @param string $prop the property uri pointing to timestamps, eg. 'dc:modified'
* @param string $lang language of labels to return
* @param int $offset offset of results to retrieve; 0 for beginning of list
* @param int $limit maximum number of results to return
* @return array Result array
*/
public function queryChangeList($lang, $offset, $prop) {
$query = $this->generateChangeListQuery($lang, $offset, $prop);
public function queryChangeList($prop, $lang, $offset, $limit) {
$query = $this->generateChangeListQuery($prop, $lang, $offset, $limit);

$result = $this->query($query);
return $this->transformChangeListResults($result);
}
Expand Down
4 changes: 4 additions & 0 deletions rest.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@
$controller->groups($request);
} elseif ($parts[2] == 'groupMembers') {
$controller->groupMembers($request);
} elseif ($parts[2] == 'new') {
$controller->newConcepts($request);
} elseif ($parts[2] == 'modified') {
$controller->modifiedConcepts($request);
} else {
header("HTTP/1.0 404 Not Found");
echo ("404 Not Found");
Expand Down
142 changes: 142 additions & 0 deletions swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -1121,6 +1121,110 @@
]
}
},
"/{vocid}/new": {
"get": {
"summary": "New concepts in the vocabulary",
"parameters": [
{
"name": "vocid",
"in": "path",
"description": "a Skosmos vocabulary identifier e.g. \"stw\" or \"yso\"",
"required": true,
"type": "string"
},
{
"name": "lang",
"in": "query",
"description": "label language, e.g. \"en\" or \"fi\"",
"required": false,
"type": "string"
},
{
"name": "offset",
"in": "query",
"description": "offset of the starting index",
"required": false,
"type": "number"
},
{
"name": "limit",
"in": "query",
"description": "maximum number of concepts to return",
"required": false,
"type": "number"
}
],
"produces": [
"application/ld+json"
],
"responses": {
"200": {
"description": "list of most recently created concepts of the vocabulary",
"schema": {
"$ref": "#/definitions/changedConceptsResult"
}
},
"404": {
"description": "no vocabulary could be found with the requested id"
}
},
"tags": [
"Vocabulary-specific methods"
]
}
},
"/{vocid}/modified": {
"get": {
"summary": "Modified concepts in the vocabulary",
"parameters": [
{
"name": "vocid",
"in": "path",
"description": "a Skosmos vocabulary identifier e.g. \"stw\" or \"yso\"",
"required": true,
"type": "string"
},
{
"name": "lang",
"in": "query",
"description": "label language, e.g. \"en\" or \"fi\"",
"required": false,
"type": "string"
},
{
"name": "offset",
"in": "query",
"description": "offset of the starting index",
"required": false,
"type": "number"
},
{
"name": "limit",
"in": "query",
"description": "maximum number of concepts to return",
"required": false,
"type": "number"
}
],
"produces": [
"application/ld+json"
],
"responses": {
"200": {
"description": "list of most recently created concepts of the vocabulary",
"schema": {
"$ref": "#/definitions/changedConceptsResult"
}
},
"404": {
"description": "no vocabulary could be found with the requested id"
}
},
"tags": [
"Vocabulary-specific methods"
]
}
},
"/{vocid}/groupMembers": {
"get": {
"summary": "Members of the requested concept group",
Expand Down Expand Up @@ -2281,6 +2385,44 @@
"vocabName",
"typeLabel"
]
},
"changedConceptsResult": {
"type": "object",
"properties": {
"changeList": {
"type": "array",
"description": "List of changed concepts",
"items": {
"$ref": "#/definitions/changedConcept"
}
}
},
"required": [
"changeList"
]
},
"changedConcept": {
"type": "object",
"properties": {
"uri": {
"type": "string",
"description": "URI of the concept"
},
"prefLabel": {
"type": "string",
"description": "Preferred label of the concept"
},
"date": {
"type": "string",
"format": "date-time",
"description": "Time stamp"
}
},
"required": [
"uri",
"prefLabel",
"date"
]
}
}
}
Loading

0 comments on commit c76c510

Please sign in to comment.