From 7422a2305c50bc5b8ef2d15b71cbf56689e5f8d5 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Thu, 7 Feb 2019 00:49:37 -0500 Subject: [PATCH] Implement basic APIv4 support --- ext/afform/Civi/Api4/Action/Afform/Create.php | 11 +++ ext/afform/Civi/Api4/Action/Afform/Delete.php | 19 ++++ ext/afform/Civi/Api4/Action/Afform/Get.php | 11 +++ .../Civi/Api4/Action/Afform/GetFields.php | 14 +++ ext/afform/Civi/Api4/Action/Afform/Revert.php | 36 +++++++ ext/afform/Civi/Api4/Action/Afform/Update.php | 13 +++ ext/afform/Civi/Api4/Afform.php | 15 +++ ext/afform/Civi/Api4/AfformCrudTrait.php | 95 +++++++++++++++++++ .../tests/phpunit/api/v4/AfformTest.php | 82 ++++++++++++++++ 9 files changed, 296 insertions(+) create mode 100644 ext/afform/Civi/Api4/Action/Afform/Create.php create mode 100644 ext/afform/Civi/Api4/Action/Afform/Delete.php create mode 100644 ext/afform/Civi/Api4/Action/Afform/Get.php create mode 100644 ext/afform/Civi/Api4/Action/Afform/GetFields.php create mode 100644 ext/afform/Civi/Api4/Action/Afform/Revert.php create mode 100644 ext/afform/Civi/Api4/Action/Afform/Update.php create mode 100644 ext/afform/Civi/Api4/Afform.php create mode 100644 ext/afform/Civi/Api4/AfformCrudTrait.php create mode 100644 ext/afform/tests/phpunit/api/v4/AfformTest.php diff --git a/ext/afform/Civi/Api4/Action/Afform/Create.php b/ext/afform/Civi/Api4/Action/Afform/Create.php new file mode 100644 index 0000000000..971eddfca4 --- /dev/null +++ b/ext/afform/Civi/Api4/Action/Afform/Create.php @@ -0,0 +1,11 @@ +createSiteLocalPath($afform['name'], $file); + if (file_exists($metaPath)) { + if (!@unlink($metaPath)) { + throw new \API_Exception("Failed to remove afform overrides in $file"); + } + } + } + } + + // We may have changed list of files covered by the cache. + $scanner->clear(); + + // FIXME if `server_route` changes, then flush the menu cache. + // FIXME if asset-caching is enabled, then flush the asset cache + } + +} diff --git a/ext/afform/Civi/Api4/Action/Afform/Update.php b/ext/afform/Civi/Api4/Action/Afform/Update.php new file mode 100644 index 0000000000..03dc840bad --- /dev/null +++ b/ext/afform/Civi/Api4/Action/Afform/Update.php @@ -0,0 +1,13 @@ +where) === 1 && $this->where[0][0] === 'name' && $this->where[0][1] == '=') { + $names = [$this->where[0][2]]; + } + else { + $names = array_keys($scanner->findFilePaths()); + } + + $values = []; + foreach ($names as $name) { + $record = $scanner->getMeta($name); + $layout = $scanner->findFilePath($name, 'layout.html'); + if ($layout) { + // FIXME check for file existence+substance+validity + $record['layout'] = $converter->convertHtmlToArray(file_get_contents($layout)); + } + $values[] = $record; + } + + return $this->processArrayData($values); + } + + /** + * Write a record as part of a create/update action. + * + * @param array $record + * The record to write to the DB. + * @return array + * The record after being written to the DB (e.g. including newly assigned "id"). + * @throws \API_Exception + */ + protected function writeObject($record) { + /** @var \CRM_Afform_AfformScanner $scanner */ + $scanner = \Civi::service('afform_scanner'); + $converter = new \CRM_Afform_ArrayHtml(); + + if (empty($record['name']) || !preg_match('/^[a-zA-Z][a-zA-Z0-9\-]*$/', $record['name'])) { + throw new \API_Exception("Afform.create: name is a mandatory field. It should use alphanumerics and dashes."); + } + $name = $record['name']; + + // FIXME validate all field data. + $updates = _afform_fields_filter($record); + + // Create or update layout.html. + if (isset($updates['layout'])) { + $layoutPath = $scanner->createSiteLocalPath($name, 'layout.html'); + \ CRM_Utils_File::createDir(dirname($layoutPath)); + file_put_contents($layoutPath, $converter->convertArrayToHtml($updates['layout'])); + // FIXME check for writability then success. Report errors. + } + + // Create or update meta.json. + $orig = \Civi\Api4\Afform::get()->addWhere('name', '=', $name)->execute(); + + if (isset($orig[0])) { + $meta = _afform_fields_filter(array_merge($orig[0], $updates)); + } + else { + $meta = $updates; + } + unset($meta['layout']); + unset($meta['name']); + if (!empty($meta)) { + $metaPath = $scanner->createSiteLocalPath($name, \CRM_Afform_AfformScanner::METADATA_FILE); + // printf("[%s] Update meta %s: %s\n", $name, $metaPath, print_R(['updates'=>$updates, 'meta'=>$meta], 1)); + \CRM_Utils_File::createDir(dirname($metaPath)); + file_put_contents($metaPath, json_encode($meta, JSON_PRETTY_PRINT)); + // FIXME check for writability then success. Report errors. + } + + // We may have changed list of files covered by the cache. + $scanner->clear(); + + // FIXME if `server_route` changes, then flush the menu cache. + // FIXME if asset-caching is enabled, then flush the asset cache. + + return $updates; + } + +} diff --git a/ext/afform/tests/phpunit/api/v4/AfformTest.php b/ext/afform/tests/phpunit/api/v4/AfformTest.php new file mode 100644 index 0000000000..1a0f01994c --- /dev/null +++ b/ext/afform/tests/phpunit/api/v4/AfformTest.php @@ -0,0 +1,82 @@ +installMe(__DIR__) + ->install(['org.civicrm.api4']) + ->apply(); + } + + /** + * The setup() method is executed before the test is executed (optional). + */ + public function setUp() { + parent::setUp(); + CRM_Core_Config::singleton()->userPermissionTemp = new CRM_Core_Permission_Temp(); + CRM_Core_Config::singleton()->userPermissionTemp->grant('administer CiviCRM'); + } + + /** + * The tearDown() method is executed after the test was executed (optional) + * This can be used for cleanup. + */ + public function tearDown() { + parent::tearDown(); + } + + /** + * This takes the bundled `examplepage` and performs some API calls on it. + */ + public function testGetUpdateRevert() { + Civi\Api4\Afform::revert()->addWhere('name', '=', 'examplepage')->execute(); + + $message = 'The initial Afform.get should return default data'; + $result = Civi\Api4\Afform::get()->addWhere('name', '=', 'examplepage')->execute(); + $result->indexBy('name'); + $this->assertEquals('examplepage', $result['examplepage']['name'], $message); + $this->assertEquals('', $result['examplepage']['title'], $message); + $this->assertEquals('', $result['examplepage']['description'], $message); + $this->assertEquals('civicrm/example-page', $result['examplepage']['server_route'], $message); + $this->assertTrue(is_array($result['examplepage']['layout']), $message); + + $message = 'After updating with Afform.create, the revised data should be returned'; + $result = Civi\Api4\Afform::update() + ->addWhere('name', '=', 'examplepage') + ->addValue('description', 'The temporary description') + ->execute(); + $this->assertEquals('examplepage', $result[0]['name'], $message); + $this->assertEquals('The temporary description', $result[0]['description'], $message); + + $message = 'After updating, the Afform.get API should return blended data'; + $result = Civi\Api4\Afform::get()->addWhere('name', '=', 'examplepage')->execute(); + $this->assertEquals('examplepage', $result[0]['name'], $message); + $this->assertEquals('', $result[0]['title'], $message); + $this->assertEquals('The temporary description', $result[0]['description'], $message); + $this->assertEquals('civicrm/example-page', $result[0]['server_route'], $message); + $this->assertTrue(is_array($result[0]['layout']), $message); + + Civi\Api4\Afform::revert()->addWhere('name', '=', 'examplepage')->execute(); + $message = 'After reverting, te final Afform.get should return default data'; + $result = Civi\Api4\Afform::get()->addWhere('name', '=', 'examplepage')->execute(); + $this->assertEquals('examplepage', $result[0]['name'], $message); + $this->assertEquals('', $result[0]['title'], $message); + $this->assertEquals('', $result[0]['description'], $message); + $this->assertEquals('civicrm/example-page', $result[0]['server_route'], $message); + $this->assertTrue(is_array($result[0]['layout']), $message); + } + +} -- 2.25.1