/** * * Process HTTP PUT request on collections * * collections/{collection} | Update {collection} * collections/{collection}/{feature} | Update {feature} * * @param array $segments * @param array $data */ private function PUT_collections($segments, $data) { /* * {collection} is mandatory and no modifier is allowed */ if (!isset($segments[1]) || isset($segments[3])) { RestoLogUtil::httpError(404); } $collection = new RestoCollection($segments[1], $this->context, $this->user, array('autoload' => true)); $featureIdentifier = isset($segments[2]) ? $segments[2] : null; if (isset($featureIdentifier)) { $feature = new RestoFeature($this->context, $this->user, array('featureIdentifier' => $featureIdentifier, 'collection' => $collection)); if (!$feature->isValid()) { RestoLogUtil::httpError(404); } } /* * Only owner of the collection can update it */ if (!$this->user->hasRightsTo(RestoUser::UPDATE, array('collection' => $collection))) { RestoLogUtil::httpError(403); } /* * collections/{collection} */ if (!isset($feature)) { $collection->loadFromJSON($data, true); if ($this->context->storeQuery === true) { $this->user->storeQuery($this->context->method, 'update', $collection->name, null, $this->context->query, $this->context->getUrl()); } return RestoLogUtil::success('Collection ' . $collection->name . ' updated'); } else { RestoLogUtil::httpError(501); } }
/** * * Process HTTP GET request on collections * * @param array $segments */ private function GET_collections($segments) { if (isset($segments[1])) { $collection = new RestoCollection($segments[1], $this->context, $this->user, array('autoload' => true)); } if (isset($segments[2])) { $feature = new RestoFeature($this->context, $this->user, array('featureIdentifier' => $segments[2], 'collection' => $collection)); if (!$feature->isValid()) { RestoLogUtil::httpError(404); } } /** * Collection descriptions * * @SWG\Get( * tags={"collections"}, * path="/collections.{format}", * summary="Describe", * description="Returns a list of all collection descriptions including license information and collection content statistics (i.e. number of products, etc.)", * produces={"application/json"}, * @SWG\Parameter( * name="format", * in="path", * description="Output format", * required=true, * type="string", * @SWG\Items(type="string"), * enum={"json"} * ), * @SWG\Response( * response="200", * description="List of all collection descriptions" * ) * ) * */ if (!isset($collection)) { return new RestoCollections($this->context, $this->user, array('autoload' => true)); } else { if (!isset($feature->identifier)) { return $collection; } else { if (!isset($segments[3])) { if ($this->context->storeQuery === true) { $this->user->storeQuery($this->context->method, 'resource', $collection->name, $feature->identifier, $this->context->query, $this->context->getUrl()); } return $feature; } else { if ($segments[3] === 'download') { return $this->downloadFeature($collection, $feature, isset($this->context->query['_tk']) ? $this->context->query['_tk'] : null); } else { if ($segments[3] === 'wms') { return $this->viewFeature($collection, $feature, isset($this->context->query['_tk']) ? $this->context->query['_tk'] : null); } else { RestoLogUtil::httpError(404); } } } } } }
/** * Generate items informations * * Get an array containing two lists : * -> items : Downloadable items with url * -> errors : Not downloadable items with explanations * * @return array */ private function generateItemsInformations() { /* * Features with errors */ $errors = array(); /* * Features without errors */ $items = array(); /* * Loop over items */ foreach ($this->order['items'] as $item) { /* * Check if item get an id */ if (!isset($item['id'])) { array_push($errors, array('type' => 'Feature', 'ErrorMessage' => 'Wrong item', 'ErrorCode' => 404, 'properties' => isset($item['properties']) ? $item['properties'] : null)); continue; } /* * Create RestoFeature */ $feature = new RestoFeature($this->context, $this->user, array('featureIdentifier' => $item['id'])); /* * Check if User is fullfilling license requirements */ if (!$feature->getLicense()->isApplicableToUser($this->user)) { array_push($errors, array('type' => 'Feature', 'id' => $feature->identifier, 'ErrorMessage' => 'User does not fulfill license requirements', 'ErrorCode' => 403, 'properties' => isset($item['properties']) ? $item['properties'] : null)); continue; } /* * Check if user has to sign license */ if ($feature->getLicense()->hasToBeSignedByUser($this->user)) { array_push($errors, array('type' => 'Feature', 'id' => $feature->identifier, 'ErrorMessage' => 'User has to sign license', 'ErrorCode' => 3002, 'license' => $feature->getLicense()->toArray(), 'properties' => isset($item['properties']) ? $item['properties'] : null)); continue; } /* * Check if item is valid */ if (!isset($item['properties']) || !isset($item['properties']['services']) || !isset($item['properties']['services']['download'])) { array_push($errors, array('type' => 'Feature', 'id' => $feature->identifier, 'ErrorMessage' => 'Invalid item', 'ErrorCode' => 404, 'properties' => isset($item['properties']) ? $item['properties'] : null)); continue; } /* * Check is item is downloadable */ if (!isset($item['properties']['services']['download']['url']) || !RestoUtil::isUrl($item['properties']['services']['download']['url'])) { array_push($errors, array('type' => 'Feature', 'id' => $feature->identifier, 'ErrorMessage' => 'Item not downloadable', 'ErrorCode' => 404, 'properties' => isset($item['properties']) ? $item['properties'] : null)); continue; } /* * Check user rights */ if (!$this->user->hasRightsTo(RestoUser::DOWNLOAD, array('collectionName' => $item['properties']['collection'], 'featureIdentifier' => $feature->identifier))) { array_push($errors, array('type' => 'Feature', 'id' => $feature->identifier, 'ErrorMessage' => "User hasn't enough rights. Please contact an administrator", 'ErrorCode' => 403, 'properties' => isset($item['properties']) ? $item['properties'] : null)); continue; } /* * Update local download url with a shared link */ $exploded = explode('?', $item['properties']['services']['download']['url']); if ($exploded[0] === $this->context->baseUrl . join('/', array('/collections', $item['properties']['collection'], $feature->identifier, 'download'))) { $item['properties']['services']['download']['url'] = $this->getSharedLink($item['properties']['services']['download']['url']); } /* * Add item to downloadable items list */ array_push($items, array('type' => 'Feature', 'id' => $feature->identifier, 'properties' => isset($item['properties']) ? $item['properties'] : null)); } /* * Return array containing errors and downloadable items */ return array('errors' => $errors, 'items' => $items); }
/** * @depends testFeatureCollection * * Test order exception */ public function testRestoOrder() { $this->initContext(); $order = $this->admin->placeOrder(array(array('c5dc1f32-002d-5ee9-bd4a-c690461eb734'))); $_order = new RestoOrder($this->admin, $this->context, $order['orderId']); $json_decode = json_decode($_order->toJSON(true), true); $this->assertEquals('success', $json_decode['status']); $this->assertEquals(404, $json_decode['order']['errors'][0]['ErrorCode']); $meta4 = $_order->toMETA4(); $feature = new RestoFeature($this->context, $this->admin, array('featureIdentifier' => 'c5dc1f32-002d-5ee9-bd4a-c690461eb734')); $order = $this->admin->placeOrder(array($feature->toArray())); $_order = new RestoOrder($this->admin, $this->context, $order['orderId']); $json_decode = json_decode($_order->toJSON(true), true); $this->assertEquals(403, $json_decode['order']['errors'][0]['ErrorCode']); $profile = array('userid' => 3, 'groups' => 'default', 'email' => 'test_email_order', 'password' => 'test_password', 'username' => 'test_username', 'givenname' => 'test_givenname', 'lastname' => 'test_lastname', 'country' => 'FR', 'organization' => 'FR', 'flags' => 'REGISTERED', 'topics' => null, 'validatedby' => 'admin', 'validationdate' => 'now()', 'activated' => 1); $user = new RestoUser($profile, $this->context); $order = $user->placeOrder(array($feature->toArray())); $_order = new RestoOrder($user, $this->context, $order['orderId']); $json_decode = json_decode($_order->toJSON(true), true); $this->assertEquals(3002, $json_decode['order']['errors'][0]['ErrorCode']); $license = new RestoLicense($this->context, 'Example', true); $user->signLicense($license); $order = $user->placeOrder(array($feature->toArray())); $_order = new RestoOrder($user, $this->context, $order['orderId']); $json_decode = json_decode($_order->toJSON(true), true); $this->assertEquals($order['orderId'], $json_decode['order']['orderId']); $this->assertEquals('c5dc1f32-002d-5ee9-bd4a-c690461eb734', $json_decode['order']['items'][0]['id']); $meta4 = $_order->toMETA4(); $fake_array = $feature->toArray(); $fake_array['properties']['services']['download']['url'] = null; $order = $user->placeOrder(array($fake_array)); $_order = new RestoOrder($user, $this->context, $order['orderId']); $json_decode = json_decode($_order->toJSON(true), true); $this->assertEquals(404, $json_decode['order']['errors'][0]['ErrorCode']); $this->assertEquals('Item not downloadable', $json_decode['order']['errors'][0]['ErrorMessage']); $fake_array['properties'] = null; $order = $user->placeOrder(array($fake_array)); $_order = new RestoOrder($user, $this->context, $order['orderId']); $json_decode = json_decode($_order->toJSON(true), true); $this->assertEquals(404, $json_decode['order']['errors'][0]['ErrorCode']); $this->assertEquals('Invalid item', $json_decode['order']['errors'][0]['ErrorMessage']); /* * TODO : test $meta4 content */ }
/** * * Process collections * * collections/{collection} | Delete {collection} * collections/{collection}/{feature} | Delete {feature} * * @param array $segments */ private function DELETE_collections($segments) { /* * {collection} is mandatory and no modifier is allowed */ if (!isset($segments[1]) || isset($segments[3])) { RestoLogUtil::httpError(404); } $collection = new RestoCollection($segments[1], $this->context, $this->user, array('autoload' => true)); if (isset($segments[2])) { $feature = new RestoFeature($this->context, $this->user, array('featureIdentifier' => $segments[2], 'collection' => $collection)); if (!$feature->isValid()) { RestoLogUtil::httpError(404); } } /* * Only owner of a collection can delete it */ if (!$this->user->hasRightsTo(RestoUser::UPDATE, array('collection' => $collection))) { RestoLogUtil::httpError(403); } /** * collections/{collection} * * @SWG\Delete( * tags={"collection"}, * path="/collections/{collectionId}", * summary="Delete collection", * description="Delete collection {collectionId} if collection is not empty", * operationId="deleteCollection", * produces={"application/json"}, * @SWG\Parameter( * name="collectionId", * in="path", * description="Collection identifier", * required=true, * type="string", * @SWG\Items(type="string") * ), * @SWG\Response( * response="200", * description="Acknowledgment on successful collection deletion" * ), * @SWG\Response( * response="404", * description="Collection not found" * ), * @SWG\Response( * response="403", * description="Forbidden" * ) * ) */ if (!isset($feature)) { $collection->removeFromStore(); /* * Store query */ if ($this->context->storeQuery === true) { $this->user->storeQuery($this->context->method, 'remove', $collection->name, null, $this->context->query, $this->context->getUrl()); } return RestoLogUtil::success('Collection ' . $collection->name . ' deleted'); } else { $feature->removeFromStore(); /* * Store query */ if ($this->context->storeQuery === true) { $this->user->storeQuery($this->context->method, 'remove', $collection->name, $feature->identifier, $this->context->query, $this->context->getUrl()); } return RestoLogUtil::success('Feature ' . $feature->identifier . ' deleted', array('featureIdentifier' => $feature->identifier)); } }
/** * Refresh tags for feature * * @param RestoFeature $feature */ public function refresh($feature) { $featureArray = $feature->toArray(); $this->context->dbDriver->update(RestoDatabaseDriver::KEYWORDS, array('feature' => $feature, 'keywords' => $this->getKeywords($this->removeReservedProperties($featureArray['properties']), $featureArray['geometry']))); }
/** * Update feature keywords * * @param RestoFeature $feature * @param array $keywords * @throws Exception */ public function updateFeatureKeywords($feature, $keywords) { $toUpdate = array(); /* * Store new keywords */ if (is_array($keywords)) { $columns = array_merge(array('keywords' => '\'' . pg_escape_string(json_encode($keywords)) . '\''), $this->landuseColumns($keywords)); $columns[$feature->collection->model->getDbKey('hashes')] = '\'{' . join(',', $this->getHashes($keywords)) . '}\''; foreach ($columns as $columnName => $columnValue) { array_push($toUpdate, $columnName . '=' . $columnValue); } } if (empty($toUpdate)) { RestoLogUtil::httpError(400, 'Nothing to update for ' . $feature->identifier); } try { /* * Begin transaction */ $this->dbDriver->query('BEGIN'); /* * Remove previous facets */ $this->removeFeatureFacets($feature->toArray()); /* * Update feature */ $this->dbDriver->query('UPDATE resto.features SET ' . join(',', $toUpdate) . ' WHERE identifier = \'' . pg_escape_string($feature->identifier) . '\''); /* * Store new facets */ $this->storeKeywordsFacets($feature->collection, $keywords, true); /* * Commit */ $this->dbDriver->query('COMMIT'); } catch (Exception $e) { $this->dbDriver->query('ROLLBACK'); RestoLogUtil::httpError(500, 'Cannot update feature ' . $feature->identifier); } return true; }