From 9d1f53bb1187061e19e9c5e846624415b2c083ab Mon Sep 17 00:00:00 2001 From: Rodrigo Goncalves <rodrigo.g@ufsc.br> Date: Tue, 27 Aug 2024 14:14:23 +0000 Subject: [PATCH] Routes for update SmartDataContext --- context/api/controller/crud.php | 86 ++++++++++++- context/api/persistence/smartdatacontext.php | 30 +++++ context/api/routes.php | 2 + context/api/swagger/openapi.yaml | 123 +++++++++++++++++++ context/tests/CrudTest.php | 77 +++++++++--- 5 files changed, 301 insertions(+), 17 deletions(-) diff --git a/context/api/controller/crud.php b/context/api/controller/crud.php index e7a262a..8c0c197 100644 --- a/context/api/controller/crud.php +++ b/context/api/controller/crud.php @@ -76,7 +76,10 @@ class Crud { return $this->return_error($response, $errors, 400); } - $smartdatacontextids = $this->_get_value_or_default($body, 'smartDataContextIds', []); + $smartdatacontextids = $this->_get_value_or_default($body, 'smartDataContextIds', null); + if (! isset($smartdatacontextids)) { + return $this->return_error($response, ['Missing smartDataContextIds'], 400); + } if (! is_array($smartdatacontextids)) { $smartdatacontextids = [$smartdatacontextids]; } @@ -106,7 +109,10 @@ class Crud { return $this->return_error($response, $errors, 400); } - $smartdatacontextids = $this->_get_value_or_default($body, 'smartDataContextIds', []); + $smartdatacontextids = $this->_get_value_or_default($body, 'smartDataContextIds', null); + if (! isset($smartdatacontextids)) { + return $this->return_error($response, ['Missing smartDataContextIds'], 400); + } if (! is_array($smartdatacontextids)) { $smartdatacontextids = [$smartdatacontextids]; } @@ -246,4 +252,80 @@ class Crud { return $body[$key]; } } + + function update(Request $request, Response $response, array $params) { + // Basic validation + [$domain, $body, $errors] = $this->_basicValidation($params, $request, $response); + if ($errors) { + return $this->return_error($response, $errors, 400); + } + + $id = $this->_get_value_or_default($params, 'id', null); + if (!$id) { + return $this->return_error($response, ["missing SmartDataContextID"], 400); + } + + // Validate properties only present in the request body + $updateData = []; + if (isset($body['content'])) { + $contentErrors = SmartDataContext::ValidateContent($body['content']); + if ($contentErrors) { + $errors = array_merge($errors, $contentErrors); + } + $updateData['content'] = $body['content']; + } + + if (isset($body['features'])) { + $featuresErrors = SmartDataContext::ValidateFeatures($body['features']); + if ($featuresErrors) { + $errors = array_merge($errors, $featuresErrors); + } + $updateData['features'] = $body['features']; + } + + $t0Set = isset($body['t0']); + $t1Set = isset($body['t1']); + if ($t0Set && $t1Set) { + $timestampErrors = SmartDataContext::ValidateTimestamp($body['t0'], $body['t1']); + if ($timestampErrors) { + $errors = array_merge($errors, $timestampErrors); + } + $updateData['t0'] = $body['t0']; + $updateData['t1'] = $body['t1']; + } elseif ($t0Set || $t1Set) { + // Error if only one of t0 or t1 is set + $errors[] = "Both t0 and t1 must be provided together."; + } + + if (isset($body['smartDataSources'])) { + $smartDataSourcesErrors = SmartDataContext::ValidateSmartDataSources($body['smartDataSources']); + if ($smartDataSourcesErrors) { + $errors = array_merge($errors, $smartDataSourcesErrors); + } + $updateData['smartDataSources'] = $body['smartDataSources']; + } + + if (isset($body['smartDataUnits'])) { + $smartDataUnitsErrors = SmartDataContext::ValidateSmartDataUnits($body['smartDataUnits']); + if ($smartDataUnitsErrors) { + $errors = array_merge($errors, $smartDataUnitsErrors); + } + $updateData['smartDataUnits'] = $body['smartDataUnits']; + } + + if ($errors) { + return $this->return_error($response, $errors, 400); + } + + // Call the update method from SmartDataContextCrud + $persistence = new SmartDataContextCrud($this->_get_db()); + $result = $persistence->update($domain, $id, $updateData); + + if ($result['success']) { + return $this->return_json($response, $result['contents']); + } else { + return $this->return_error($response, $result['errors'], 400); + } + } + } \ No newline at end of file diff --git a/context/api/persistence/smartdatacontext.php b/context/api/persistence/smartdatacontext.php index 5b433e1..9db8324 100644 --- a/context/api/persistence/smartdatacontext.php +++ b/context/api/persistence/smartdatacontext.php @@ -196,4 +196,34 @@ class SmartDataContextCrud { return ["success" => false, "errors" => [$exception->getMessage()]]; } } + + public function update($domain, $id, array $updateData): array { + // Find the document in the MongoDB collection using the id field value + $collection = $this->getCollection($domain); + $document = $collection->findOne(["id" => $id]); + + // Check if the document exists + if ($document === null) { + return ["success" => false, "errors" => ["SmartDataContext with id $id not found"]]; + } + + // Update the document's properties using the associative array received + $updateFields = []; + foreach ($updateData as $key => $value) { + $updateFields[$key] = $value; + } + + // Prepare the update query + $updateQuery = ['$set' => $updateFields]; + + // Update the document in the MongoDB collection + try { + $collection->updateOne(["id" => $id], $updateQuery); + $updatedDocument = $collection->findOne(["id" => $id]); + return ["success" => true, "contents" => json_decode(json_encode($updatedDocument), false)]; + } catch (Exception $e) { + return ["success" => false, "errors" => [$e->getMessage()]]; + } + } + } \ No newline at end of file diff --git a/context/api/routes.php b/context/api/routes.php index 06f6dbe..1b61cd3 100644 --- a/context/api/routes.php +++ b/context/api/routes.php @@ -12,6 +12,8 @@ function setupRoutes(App $app) { $app->post('/query/{domain}', '\SmartDataContext\Controller\Crud:query'); $app->post('/contexts/{domain}', '\SmartDataContext\Controller\Crud:contexts'); + $app->post('/update/{domain}/{id}', '\SmartDataContext\Controller\Crud:update'); + # Documentation $app->get('/docs', function ($request, Response $response) { $response->getBody()->write(file_get_contents(__DIR__ . '/swagger/swagger-ui.html')); diff --git a/context/api/swagger/openapi.yaml b/context/api/swagger/openapi.yaml index 24ca9ee..4803beb 100644 --- a/context/api/swagger/openapi.yaml +++ b/context/api/swagger/openapi.yaml @@ -487,3 +487,126 @@ paths: items: type: string example: ["Invalid id"] + /api/v1_1/context.php#update: + post: + summary: Updates an existing SmartDataContext + description: Updates the properties of an existing SmartDataContext using the provided ID and request body. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + command: + type: string + description: The command to update a SmartDataContext, including the ID. + example: "/update/88690087-a4f4-4e1d-8c8d-8c67d19ddaed" + request: + type: object + description: The object containing the properties to be updated in the SmartDataContext. + properties: + domain: + type: string + description: The domain of the SmartDataContext. + example: "test" + t0: + type: integer + description: Start time for the SmartDataContext. + example: 1000 + t1: + type: integer + description: End time for the SmartDataContext. + example: 2000 + content: + type: object + description: The content to be updated in the SmartDataContext. + example: {"meta": "updated"} + features: + type: object + description: Updated features of the SmartDataContext. + properties: + tags: + type: array + items: + type: string + example: ["newtag"] + smartDataSources: + type: array + items: + oneOf: + - type: string + - type: array + items: + type: integer + description: The updated SmartDataSources. + example: ["signature", [2, 2, 2, 2]] + smartDataUnits: + type: array + items: + type: integer + description: The updated SmartDataUnits. + example: [20, 22] + required: + - command + - request + responses: + '200': + description: Successfully updated SmartDataContext. + content: + application/json: + schema: + type: object + properties: + result: + type: object + properties: + id: + type: string + example: "88690087-a4f4-4e1d-8c8d-8c67d19ddaed" + t0: + type: integer + example: 1000 + t1: + type: integer + example: 2000 + content: + type: object + properties: + meta: + type: string + example: "updated" + features: + type: object + properties: + tags: + type: array + items: + type: string + example: ["newtag"] + smartDataSources: + type: array + items: + oneOf: + - type: string + - type: array + items: + type: integer + example: ["signature", [2, 2, 2, 2]] + smartDataUnits: + type: array + items: + type: integer + example: [20, 22] + '400': + description: Invalid request due to validation errors. + content: + application/json: + schema: + type: object + properties: + errors: + type: array + items: + type: string + example: ["Invalid command format", "Both t0 and t1 must be set together"] diff --git a/context/tests/CrudTest.php b/context/tests/CrudTest.php index 278742d..68a5e4d 100644 --- a/context/tests/CrudTest.php +++ b/context/tests/CrudTest.php @@ -101,8 +101,8 @@ class CrudTest extends BaseTest $response->getBody()->rewind(); $body = json_decode($response->getBody()->getContents(), true); $this->assertTrue(array_key_exists('result', $body), 'missing result'); - $this->assertTrue(array_key_exists('smartdataid', $body['result']), 'missing smartdataid'); - $id = $body['result']['smartdataid']; + $this->assertTrue(array_key_exists('smartDataContextId', $body['result']), 'missing smartdataid'); + $id = $body['result']['smartDataContextId']; $response = $this->app->handle($this->_createRequest('GET', "/get/test/$id")); $this->assertEquals(200, $response->getStatusCode(), json_encode($response->getBody())); $response->getBody()->rewind(); @@ -120,10 +120,10 @@ class CrudTest extends BaseTest $response->getBody()->rewind(); $body = json_decode($response->getBody()->getContents(), true); $this->assertTrue(array_key_exists('result', $body), 'missing result'); - $this->assertTrue(array_key_exists('smartdataid', $body['result']), 'missing smartdataid'); - $id = $body['result']['smartdataid']; + $this->assertTrue(array_key_exists('smartDataContextId', $body['result']), 'missing smartdataid'); + $id = $body['result']['smartDataContextId']; - $body = ["smartdataids" => [$id], "smartDataSources" => ["ae7666", [4,5,6,7], [1,2,3,5]], "smartDataUnits" => [111,222]]; + $body = ["smartDataContextIds" => [$id], "smartDataSources" => ["ae7666", [4,5,6,7], [1,2,3,5]], "smartDataUnits" => [111,222]]; $response = $this->app->handle($this->_createRequest('POST', '/associate/test', $body)); $this->assertEquals(200, $response->getStatusCode(), json_encode($response->getBody())); $response->getBody()->rewind(); @@ -141,10 +141,10 @@ class CrudTest extends BaseTest $response->getBody()->rewind(); $body = json_decode($response->getBody()->getContents(), true); $this->assertTrue(array_key_exists('result', $body), 'missing result'); - $this->assertTrue(array_key_exists('smartdataid', $body['result']), 'missing smartdataid'); - $id = $body['result']['smartdataid']; + $this->assertTrue(array_key_exists('smartDataContextId', $body['result']), 'missing smartdataid'); + $id = $body['result']['smartDataContextId']; - $body = ["smartdataids" => [$id], "smartDataSources" => ["ae7666", [4,5,6,7], [1,2,3,5]], "smartDataUnits" => [111,222]]; + $body = ["smartDataContextIds" => [$id], "smartDataSources" => ["ae7666", [4,5,6,7], [1,2,3,5]], "smartDataUnits" => [111,222]]; $response = $this->app->handle($this->_createRequest('POST', '/associate/test', $body)); $this->assertEquals(200, $response->getStatusCode(), json_encode($response->getBody())); $response->getBody()->rewind(); @@ -152,7 +152,7 @@ class CrudTest extends BaseTest $this->assertEquals(4, count($body['result'][0]['result']['smartDataSources']), "Wrong number of smartDataSources associated"); $this->assertEquals(2, count($body['result'][0]['result']['smartDataUnits']), "Wrong number of smartDataUnits associated"); - $body = ["smartdataids" => [$id], "smartDataSources" => ["ae7666", [4,5,6,7]], "smartDataUnits" => [222]]; + $body = ["smartDataContextIds" => [$id], "smartDataSources" => ["ae7666", [4,5,6,7]], "smartDataUnits" => [222]]; $response = $this->app->handle($this->_createRequest('POST', '/unassociate/test', $body)); $this->assertEquals(200, $response->getStatusCode(), json_encode($response->getBody())); $response->getBody()->rewind(); @@ -169,10 +169,10 @@ class CrudTest extends BaseTest $response->getBody()->rewind(); $body = json_decode($response->getBody()->getContents(), true); $this->assertTrue(array_key_exists('result', $body), 'missing result'); - $this->assertTrue(array_key_exists('smartdataid', $body['result']), 'missing smartdataid'); - $id = $body['result']['smartdataid']; + $this->assertTrue(array_key_exists('smartDataContextId', $body['result']), 'missing smartdataid'); + $id = $body['result']['smartDataContextId']; - $body = ["smartdataids" => [$id], "smartDataSources" => ["ae7666", [4,5,6,7], [1,2,3,5]], "smartDataUnits" => [111,222]]; + $body = ["smartDataContextIds" => [$id], "smartDataSources" => ["ae7666", [4,5,6,7], [1,2,3,5]], "smartDataUnits" => [111,222]]; $response = $this->app->handle($this->_createRequest('POST', '/associate/test', $body)); $this->assertEquals(200, $response->getStatusCode(), json_encode($response->getBody())); $response->getBody()->rewind(); @@ -198,10 +198,10 @@ class CrudTest extends BaseTest $response->getBody()->rewind(); $body = json_decode($response->getBody()->getContents(), true); $this->assertTrue(array_key_exists('result', $body), 'missing result'); - $this->assertTrue(array_key_exists('smartdataid', $body['result']), 'missing smartdataid'); - $id = $body['result']['smartdataid']; + $this->assertTrue(array_key_exists('smartDataContextId', $body['result']), 'missing smartdataid'); + $id = $body['result']['smartDataContextId']; - $body = ["smartdataids" => [$id], "smartDataSources" => ["ae7666", [4,5,6,7], [1,2,3,5]], "smartDataUnits" => [111,222]]; + $body = ["smartDataContextIds" => [$id], "smartDataSources" => ["ae7666", [4,5,6,7], [1,2,3,5]], "smartDataUnits" => [111,222]]; $response = $this->app->handle($this->_createRequest('POST', "/associate/$domain", $body)); $this->assertEquals(200, $response->getStatusCode(), json_encode($response->getBody())); $response->getBody()->rewind(); @@ -217,4 +217,51 @@ class CrudTest extends BaseTest $body = json_decode($response->getBody()->getContents(), true); $this->assertGreaterThan(0, count($body['result']), "Wrong number of results"); } + + + public function testUpdateWithTimestampsAndContent() { + // Step 1: Create a document + $body = ["content" => ["meta" => true], "features" => ["tags" => "sim"], "smartDataUnits" => [10, 12]]; + $response = $this->app->handle($this->_createRequest('POST', '/create/test', $body)); + + $this->assertEquals(200, $response->getStatusCode(), json_encode($response->getBody())); + $response->getBody()->rewind(); + $body = json_decode($response->getBody()->getContents(), true); + $this->assertTrue(array_key_exists('result', $body), 'missing result'); + $this->assertTrue(array_key_exists('smartDataContextId', $body['result']), 'missing smartDataContextId'); + $id = $body['result']['smartDataContextId']; + + // Step 2: Update the document with t0 and t1 + $updateBody = ["t0" => 1000, "t1" => 2000]; + $response = $this->app->handle($this->_createRequest('POST', "/update/test/$id", $updateBody)); + + $this->assertEquals(200, $response->getStatusCode(), json_encode($response->getBody())); + $response->getBody()->rewind(); + $updatedBody = json_decode($response->getBody()->getContents(), true); + $this->assertTrue(array_key_exists('result', $updatedBody), 'missing result'); + $this->assertEquals($updatedBody['result']['t0'], 1000, 't0 was not updated correctly'); + $this->assertEquals($updatedBody['result']['t1'], 2000, 't1 was not updated correctly'); + + // Step 3: Update the document with new content + $newContent = ["content" => ["meta" => "updated"]]; + $response = $this->app->handle($this->_createRequest('POST', "/update/test/$id", $newContent)); + + $this->assertEquals(200, $response->getStatusCode(), json_encode($response->getBody())); + $response->getBody()->rewind(); + $updatedContentBody = json_decode($response->getBody()->getContents(), true); + $this->assertTrue(array_key_exists('result', $updatedContentBody), 'missing result'); + $this->assertEquals($updatedContentBody['result']['content']['meta'], "updated", 'content was not updated correctly'); + + // Step 4: Get the updated document and verify + $response = $this->app->handle($this->_createRequest('GET', "/get/test/$id")); + $this->assertEquals(200, $response->getStatusCode(), json_encode($response->getBody())); + $response->getBody()->rewind(); + $finalBody = json_decode($response->getBody()->getContents(), true); + $this->assertTrue(array_key_exists('result', $finalBody), 'missing result'); + $this->assertEquals($finalBody['result']['id'], $id, 'wrong smartdataid'); + $this->assertEquals($finalBody['result']['t0'], 1000, 't0 mismatch'); + $this->assertEquals($finalBody['result']['t1'], 2000, 't1 mismatch'); + $this->assertEquals($finalBody['result']['content']['meta'], "updated", 'content meta mismatch'); + } + } -- GitLab