Skip to content

Commit fca911f

Browse files
authored
Merge pull request #452 from jjrom/develop
[Catalog] Creation simplification
2 parents b6335f8 + 89cef93 commit fca911f

11 files changed

+125
-92
lines changed

app/resto/core/RestoConstants.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class RestoConstants
2020
// [IMPORTANT] Starting resto 7.x, default routes are defined in RestoRouter class
2121

2222
// resto version
23-
const VERSION = '9.0.0-RC16';
23+
const VERSION = '9.0.0-RC17';
2424

2525
/* ============================================================
2626
* NEVER EVER TOUCH THESE VALUES

app/resto/core/api/STACAPI.php

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ public function getCatalogs($params)
290290
}
291291

292292
// This is /catalogs/*
293-
return $this->processPath($params['segments'], $params);
293+
return $this->processPath($params['segments'], $params);
294294
}
295295

296296
/**
@@ -392,13 +392,12 @@ public function addCatalog($params, $body)
392392
*/
393393
$body['rtype'] = 'catalog';
394394
$body['id'] = $this->getIdPath($body, $parentId);
395-
$baseUrl = $this->context->core['baseUrl'];
396-
397-
if ($this->catalogsFunctions->getCatalog($body['id'], $baseUrl) !== null) {
395+
396+
if ($this->catalogsFunctions->getCatalog($body['id'], $this->context->core['baseUrl']) !== null) {
398397
RestoLogUtil::httpError(409, 'Catalog ' . $body['id'] . ' already exists');
399398
}
400399

401-
return RestoLogUtil::success('Catalog added', $this->catalogsFunctions->storeCatalogs(array($body), $baseUrl, $this->user->profile['id'], null, null, true));
400+
return RestoLogUtil::success('Catalog added', $this->catalogsFunctions->storeCatalogs(array($body), $this->context, $this->user->profile['id'], null, null, true));
402401

403402
}
404403

@@ -492,7 +491,7 @@ public function updateCatalog($params, $body)
492491
}
493492
}
494493

495-
return $this->catalogsFunctions->updateCatalog($catalogs[0], $this->user->profile['id'], $this->context->core['baseUrl']) ? RestoLogUtil::success('Catalog updated') : RestoLogUtil::error('Cannot update catalog');
494+
return $this->catalogsFunctions->updateCatalog($catalogs[0], $this->user->profile['id'], $this->context) ? RestoLogUtil::success('Catalog updated') : RestoLogUtil::error('Cannot update catalog');
496495
}
497496

498497
/**
@@ -1337,6 +1336,11 @@ private function processPath($segments, $params = array())
13371336

13381337
// The path is the catalog identifier
13391338
$parentAndChilds = $this->getParentAndChilds(join('/', $segments), $params);
1339+
1340+
if ( !isset($parentAndChilds) ) {
1341+
return RestoLogUtil::httpError(404);
1342+
}
1343+
13401344
$catalog = array(
13411345
'stac_version' => STACAPI::STAC_VERSION,
13421346
'id' => $segments[count($segments) -1 ],
@@ -1472,6 +1476,10 @@ private function getParentAndChilds($catalogId, $params)
14721476
'id' => $catalogId,
14731477
'q' => $params['q'] ?? null
14741478
), $this->context->core['baseUrl'], true);
1479+
1480+
if ( empty($catalogs) ) {
1481+
return null;
1482+
}
14751483

14761484
$parentAndChilds = array(
14771485
'parent' => $catalogs[0] ?? null,

app/resto/core/dbfunctions/CatalogsFunctions.php

Lines changed: 26 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -200,13 +200,13 @@ public function getCatalogItems($catalogId, $baseUrl)
200200
* !! THIS FUNCTION IS THREAD SAFE !!
201201
*
202202
* @param array $catalogs
203-
* @param string $baseUrl
203+
* @param RestoContext $context
204204
* @param string $userid
205205
* @param RestoCollection $collection
206206
* @param string $featureId
207207
* @param boolean addBeginCommit // True means that call is already within a BEGIN/COMMIT block
208208
*/
209-
public function storeCatalogs($catalogs, $baseUrl, $userid, $collection, $featureId, $addBeginCommit)
209+
public function storeCatalogs($catalogs, $context, $userid, $collection, $featureId, $addBeginCommit)
210210
{
211211

212212
// Empty catalogs - do nothing
@@ -223,7 +223,7 @@ public function storeCatalogs($catalogs, $baseUrl, $userid, $collection, $featur
223223
}
224224

225225
for ($i = count($catalogs); $i--;) {
226-
$this->storeCatalog($catalogs[$i], $userid, $baseUrl, $collectionId, $featureId);
226+
$this->storeCatalog($catalogs[$i], $userid, $context, $collectionId, $featureId);
227227
}
228228

229229
// Update all counters at the same time for a given featureId
@@ -251,10 +251,10 @@ public function storeCatalogs($catalogs, $baseUrl, $userid, $collection, $featur
251251
*
252252
* @param array $catalog
253253
* @param string $userid
254-
* @param string $baseUrl
254+
* @param RestoContext $context
255255
* @return boolean
256256
*/
257-
public function updateCatalog($catalog, $userid, $baseUrl)
257+
public function updateCatalog($catalog, $userid, $context)
258258
{
259259

260260
if ( !isset($catalog['id']) ) {
@@ -274,7 +274,7 @@ public function updateCatalog($catalog, $userid, $baseUrl)
274274
);
275275

276276
$set = array();
277-
$cleanLinks = $this->getCleanLinks($catalog, $userid, $baseUrl);
277+
$cleanLinks = $this->getCleanLinks($catalog, $userid, $context);
278278
$catalog['links'] = $cleanLinks['links'];
279279

280280
foreach (array_keys($catalog) as $key ) {
@@ -402,11 +402,11 @@ public function removeCatalog($catalogId)
402402
*
403403
* @param array $catalog
404404
* @param string $userid
405-
* @param string $baseUrl
405+
* @param RestoContext $context
406406
* @param string $collectionId
407407
* @param string $featureId
408408
*/
409-
private function storeCatalog($catalog, $userid, $baseUrl, $collectionId, $featureId)
409+
private function storeCatalog($catalog, $userid, $context, $collectionId, $featureId)
410410
{
411411
// Empty catalog - do nothing
412412
if (!isset($catalog)) {
@@ -418,7 +418,7 @@ private function storeCatalog($catalog, $userid, $baseUrl, $collectionId, $featu
418418
$catalog['id'] = rtrim($catalog['id'], '/');
419419
}
420420

421-
$cleanLinks = $this->getCleanLinks($catalog, $userid, $baseUrl);
421+
$cleanLinks = $this->getCleanLinks($catalog, $userid, $context);
422422

423423
$insert = 'INSERT INTO ' . $this->dbDriver->targetSchema . '.catalog (id, title, description, level, counters, owner, links, visibility, rtype, created) SELECT $1,$2,$3,$4,$5,$6,$7,$8,$9,now() ON CONFLICT (id) DO NOTHING';
424424
$this->dbDriver->pQuery($insert, array(
@@ -478,21 +478,6 @@ private function storeCatalog($catalog, $userid, $baseUrl, $collectionId, $featu
478478
*/
479479
$this->addInternalItems($cleanLinks['internalItems'], $catalog['id']);
480480

481-
/*
482-
* Now the tricky part - change catalogs level
483-
*/
484-
for ($i = 0, $ii = count($cleanLinks['updateCatalogs']); $i < $ii; $i++) {
485-
$updateCatalogs = $cleanLinks['updateCatalogs'][$i];
486-
$this->dbDriver->pQuery('UPDATE ' . $this->dbDriver->targetSchema . '.catalog SET id=$2, level=level + 1 WHERE lower(id)=lower($1)', array(
487-
$updateCatalogs['id'],
488-
$catalog['id'] . '/' . $updateCatalogs['id']
489-
), 500, 'Cannot update child link ' . $updateCatalogs['id']);
490-
$this->dbDriver->pQuery('UPDATE ' . $this->dbDriver->targetSchema . '.catalog_feature SET path=$2 WHERE path=$1', array(
491-
RestoUtil::path2ltree($updateCatalogs['id']),
492-
RestoUtil::path2ltree($catalog['id'] . '/' . $updateCatalogs['id'])
493-
), 500, 'Cannot update catalog feature association for child link ' . $updateCatalogs['id']);
494-
}
495-
496481
return $catalog;
497482

498483
}
@@ -691,20 +676,19 @@ private function insertIntoCatalogFeature($featureId, $path, $catalogId, $collec
691676
*
692677
* @param array $catalog
693678
* @param string userid
694-
* @param string $baseUrl
679+
* @param string $context
695680
* @return array
696681
*/
697-
private function getCleanLinks($catalog, $userid, $baseUrl) {
682+
private function getCleanLinks($catalog, $userid, $context) {
698683

699684
$output = array(
700685
'links' => array(),
701-
'updateCatalogs' => array(),
702686
'internalItems' => array()
703687
);
704688

705689
if ( !isset($catalog['links']) ) {
706690
return $output;
707-
}
691+
};
708692

709693
for ($i = 0, $ii = count($catalog['links']); $i < $ii; $i++) {
710694
$link = $catalog['links'][$i];
@@ -723,18 +707,21 @@ private function getCleanLinks($catalog, $userid, $baseUrl) {
723707
*/
724708
if ( in_array($link['rel'], array('item', 'items')) ) {
725709

726-
if ( !str_starts_with($link['href'], $baseUrl . RestoRouter::ROUTE_TO_COLLECTIONS ) ) {
710+
if ( !str_starts_with($link['href'], $context->core['baseUrl'] . RestoRouter::ROUTE_TO_COLLECTIONS ) ) {
727711
$output['links'][] = $link;
728712
continue;
729713
}
730714

731-
$exploded = explode('/', substr($link['href'], strlen($baseUrl . RestoRouter::ROUTE_TO_COLLECTIONS) + 1));
715+
$exploded = explode('/', substr($link['href'], strlen($context->core['baseUrl'] . RestoRouter::ROUTE_TO_COLLECTIONS) + 1));
732716
// A item endpoint is /collections/{collectionId}/items/{featureId}
733717
if (count($exploded) === 3) {
718+
719+
// Eventually convert collection alias to real collection id
720+
$collectionId = (new CollectionsFunctions($this->dbDriver))->aliasToCollectionId($exploded[0]) ?? $exploded[0];
734721
$internalItem = array(
735722
'id' => RestoUtil::isValidUUID($exploded[2]) ? $exploded[2] : RestoUtil::toUUID($exploded[2]),
736723
'href' => $link['href'],
737-
'collection' => $exploded[0]
724+
'collection' => $collectionId
738725
);
739726
$output['internalItems'][] = $internalItem;
740727

@@ -754,8 +741,8 @@ private function getCleanLinks($catalog, $userid, $baseUrl) {
754741
/*
755742
* Avoid cycling (i.e. catalog self referencing one of its parent)
756743
*/
757-
if (str_starts_with($link['href'], $baseUrl . RestoRouter::ROUTE_TO_CATALOGS )) {
758-
$exploded = explode('/', substr($link['href'], strlen($baseUrl . RestoRouter::ROUTE_TO_CATALOGS) + 1));
744+
if (str_starts_with($link['href'], $context->core['baseUrl'] . RestoRouter::ROUTE_TO_CATALOGS )) {
745+
$exploded = explode('/', substr($link['href'], strlen($context->core['baseUrl'] . RestoRouter::ROUTE_TO_CATALOGS) + 1));
759746
if ( count($exploded) <= count(explode('/', $catalog['id'])) ) {
760747
return RestoLogUtil::httpError(400, 'Child ' . $link['href'] . ' is invalid because it references a parent resource');
761748
}
@@ -764,29 +751,24 @@ private function getCleanLinks($catalog, $userid, $baseUrl) {
764751
/*
765752
* Store local collection within links
766753
*/
767-
if (str_starts_with($link['href'], $baseUrl . RestoRouter::ROUTE_TO_COLLECTIONS )) {
754+
if (str_starts_with($link['href'], $context->core['baseUrl'] . RestoRouter::ROUTE_TO_COLLECTIONS )) {
768755
$output['links'][] = $link;
769756
continue;
770757
}
771758

772759
}
773760

774-
$exploded = explode($baseUrl . RestoRouter::ROUTE_TO_CATALOGS . '/', $link['href']);
761+
$exploded = explode($context->core['baseUrl'] . RestoRouter::ROUTE_TO_CATALOGS . '/', $link['href']);
775762
if ( count($exploded) !== 2) {
776-
return RestoLogUtil::httpError(400, 'One link child has an external href i.e. not starting with ' . $baseUrl . RestoRouter::ROUTE_TO_CATALOGS);
763+
return RestoLogUtil::httpError(400, 'One link child has an external href i.e. not starting with ' . $context->core['baseUrl'] . RestoRouter::ROUTE_TO_CATALOGS);
777764
}
778765

779-
$childCatalog = $this->getCatalog($exploded[1], $baseUrl);
766+
$childCatalog = $this->getCatalog($exploded[1], $context->core['baseUrl']);
780767
if ( $childCatalog === null ) {
781-
return RestoLogUtil::httpError(400, 'Catalog child ' . $link['href'] . ' does not exist in database');
768+
return RestoLogUtil::httpError(400, 'Catalog child ' . $link['href'] . ' does not exist');
782769
}
783770

784-
if ($childCatalog['level'] === 1 && $childCatalog['owner'] === $userid) {
785-
array_push($output['updateCatalogs'], ...$this->getCatalogs(array('id' => $childCatalog['id']), $baseUrl, true));
786-
}
787-
else {
788-
$output['links'][] = $link;
789-
}
771+
$output['links'][] = $link;
790772

791773
}
792774

app/resto/core/dbfunctions/FeaturesFunctions.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ public function storeFeature($id, $collection, $featureArray)
361361
/*
362362
* Store catalogs
363363
*/
364-
(new CatalogsFunctions($this->dbDriver))->storeCatalogs($keysAndValues['catalogs'], $collection->context->core['baseUrl'], $collection->user->profile['id'], $collection, $result['id'], false);
364+
(new CatalogsFunctions($this->dbDriver))->storeCatalogs($keysAndValues['catalogs'], $collection->context, $collection->user->profile['id'], $collection, $result['id'], false);
365365

366366
/*
367367
* Commit everything - rollback if one of the inserts failed
@@ -520,7 +520,7 @@ public function updateFeature($feature, $collection, $newFeatureArray)
520520
$feature->id
521521
)
522522
);
523-
(new CatalogsFunctions($this->dbDriver))->storeCatalogs($keysAndValues['catalogs'], $collection->context->core['baseUrl'], $collection->user->profile['id'], $collection, $feature->id, false);
523+
(new CatalogsFunctions($this->dbDriver))->storeCatalogs($keysAndValues['catalogs'], $collection->context, $collection->user->profile['id'], $collection, $feature->id, false);
524524

525525
/*
526526
* Commit

docs/COLLECTIONS_AND_CATALOGS.md

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,34 +40,35 @@ Then get the feature :
4040

4141
*Note: Any user with the "createFeature" right can insert a feature to a collection he owns ([see rights](./USERS.md))*
4242

43-
curl -X POST -d@examples/features/dummySargasse.json "http://admin:admin@localhost:5252/collections/S2/items"
44-
4543
## Catalogs
4644

45+
### Create a dummy collection
46+
47+
# Create a dummy collection
48+
curl -X POST -d@examples/collections/DummyCollection.json "http://admin:admin@localhost:5252/collections"
49+
4750
### Create a catalog
4851

4952
# Create a catalog - user with the "createCatalog" right can create a catalog
5053
curl -X POST -d@examples/catalogs/dummyCatalog.json "http://admin:admin@localhost:5252/catalogs"
5154

52-
### Create a catalog with existing childs
53-
54-
# This will raise an error because catalog' childs does not exist. They must be created first
55-
curl -X POST -d@examples/catalogs/dummyCatalogWithChilds.json "http://admin:admin@localhost:5252/catalogs"
56-
57-
# Good way: ingest childs then parent
58-
curl -X POST -d@examples/catalogs/dummyCatalogChild1.json "http://admin:admin@localhost:5252/catalogs"
59-
curl -X POST -d@examples/catalogs/dummyCatalogChild2.json "http://admin:admin@localhost:5252/catalogs"
60-
curl -X POST -d@examples/catalogs/dummyCatalogWithChilds.json "http://admin:admin@localhost:5252/catalogs"
61-
6255
### Create a catalog under an existing catalog
6356

64-
# The catalog dummyCatalogChild1 is posted under /catalogs/dummyCatalog
65-
curl -X POST -d@examples/catalogs/dummyCatalogChild1.json "http://admin:admin@localhost:5252/catalogs/dummyCatalog"
57+
**[IMPORTANT]** You cannot create a catalog with childs in links because a child cannot exist before its parent. The good way
58+
is to create an empty catalog then add its childs through the POST API
59+
# This will raise an error because the catalog references childs that do not exist.
60+
curl -X POST -d@examples/catalogs/dummyCatalogWithChilds_invalid.json "http://admin:admin@localhost:5252/catalogs"
6661

62+
# Good way: ingest parent without childs then add childs under parent
63+
curl -X POST -d@examples/catalogs/dummyCatalogWithChilds_valid.json "http://admin:admin@localhost:5252/catalogs"
64+
curl -X POST -d@examples/catalogs/dummyCatalogChild1.json "http://admin:admin@localhost:5252/catalogs/dummyCatalogWithChilds"
65+
curl -X POST -d@examples/catalogs/dummyCatalogChild2.json "http://admin:admin@localhost:5252/catalogs/dummyCatalogWithChilds"
66+
6767
## Create a catalog under an existing catalog that cycle on itself
6868

6969
# The catalog dummyCatalogCycling is posted under /catalogs/dummyCatalogChild1 but reference one of this
7070
# parent as a child which is forbiden
71+
curl -X POST -d@examples/catalogs/dummyCatalogChild1.json "http://admin:admin@localhost:5252/catalogs/dummyCatalog"
7172
curl -X POST -d@examples/catalogs/dummyCatalogCycling.json "http://admin:admin@localhost:5252/catalogs/dummyCatalog/dummyCatalogChild1"
7273

7374
### Create a catalog with item
@@ -76,6 +77,10 @@ Then get the feature :
7677
# It references :
7778
# * a local item that is added to catalog_feature table
7879
# * an external item that is kept as referenced within the links column in catalog table
80+
81+
# First POST the item because it should exist before referencing it within the catalog
82+
curl -X POST -d@examples/features/dummySargasse.json "http://admin:admin@localhost:5252/collections/DummyCollection/items"
83+
7984
curl -X POST -d@examples/catalogs/dummyCatalogWithItem.json "http://admin:admin@localhost:5252/catalogs/dummyCatalog/dummyCatalogChild1"
8085

8186
### Update a catalog

examples/catalogs/dummyCatalogWithChilds.json

Lines changed: 0 additions & 21 deletions
This file was deleted.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"id": "dummyCatalogWithChilds",
3+
"title": "Dummy Catalog with childs",
4+
"type": "Catalog",
5+
"description":"This catalog has childs - this is invalid because they must exist before and a child cannot exist before its parent",
6+
"stac_version":"1.0.0",
7+
"links":[
8+
{
9+
"rel":"child",
10+
"href":"http://127.0.0.1:5252/catalogs/dummyCatalogWithChilds/dummyCatalogChild1"
11+
},
12+
{
13+
"rel":"child",
14+
"href":"http://127.0.0.1:5252/catalogs/dummyCatalogWithChilds/dummyCatalogChild2"
15+
},
16+
{
17+
"rel":"child",
18+
"href":"http://127.0.0.1:5252/collections/DummyCollection"
19+
}
20+
]
21+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"id": "dummyCatalogWithChilds",
3+
"title": "Dummy Catalog with childs",
4+
"type": "Catalog",
5+
"description":"This catalog has no childs - they will be added later on",
6+
"stac_version":"1.0.0",
7+
"links":[]
8+
}

0 commit comments

Comments
 (0)