diff --git a/app/availableplugins/SqlConnector/src/Model/Table/SqlProvisionersTable.php b/app/availableplugins/SqlConnector/src/Model/Table/SqlProvisionersTable.php index cad696d51..1151e215e 100644 --- a/app/availableplugins/SqlConnector/src/Model/Table/SqlProvisionersTable.php +++ b/app/availableplugins/SqlConnector/src/Model/Table/SqlProvisionersTable.php @@ -29,6 +29,7 @@ namespace SqlConnector\Model\Table; +use App\Model\Entity\ProvisioningTarget; use Cake\Datasource\ConnectionManager; use Cake\ORM\RulesChecker; use Cake\ORM\Table; @@ -230,8 +231,7 @@ class SqlProvisionersTable extends Table { 'source' => 'TermsAndConditions', 'source_table' => 'terms_and_conditions', 'related' => [], - 'archives' => true, - 'callback' => 'processTAndC' + 'archives' => true ], 'Types' => [ 'table' => 'types', @@ -372,39 +372,16 @@ public function localAfterSave(\Cake\Event\EventInterface $event, \Cake\Datasour return true; } - /** - * Process T&C for export, by converting Mostly Static Pages to their URLs. - * - * @since COmanage Registry v5.3.0 - * @param array $row Result row from query - */ - - protected function processTAndC(array $row) { - if(!empty($row['mostly_static_page_id']) - // If both a URL and MSP are specified, the URL takes precedence - && empty($row['url'])) { - // Map the MSP to its URL and include that instead - $MSPTable = TableRegistry::getTableLocator()->get("MostlyStaticPages"); - - $msp = $MSPTable->get($row['mostly_static_page_id']); - - $row['url'] = $msp->url; - } - - return $row; - } - /** * Provision object data to the provisioning target. - * - * @since COmanage Registry v5.0.0 - * @param ProvisioningTarget $provisioningTarget SqlProvisioner configuration - * @param string $className Class name of primary object being provisioned - * @param object $data Provisioning data in Entity format (eg: \App\Model\Entity\Person) - * @param ProvisioningEligibilityEnum $eligibility Provisioning Eligibility Enum + * + * @param ProvisioningTarget $provisioningTarget SqlProvisioner configuration + * @param string $className Class name of primary object being provisioned + * @param object $data Provisioning data in Entity format (eg: \App\Model\Entity\Person) + * @param string $eligibility Provisioning Eligibility Enum * @return array Array of status, comment, and optional identifier + * @since COmanage Registry v5.0.0 */ - public function provision( \App\Model\Entity\ProvisioningTarget $provisioningTarget, string $className, @@ -494,12 +471,12 @@ public function status( * Sync an entity to the target database schema. * * @since COmanage Registry v5.0.0 - * @param SqlProvisioner $SqlProvisioner SqlProvisioner configuration - * @param string $entityName Entity name of primary object being provisioned - * @param object $data Provisioning data in Entity format (eg: \App\Model\Entity\Person) - * @param ProvisioningEligibilityEnum $eligibility Provisioning Eligibility Enum - * @param string $dataSource Datasource to provision to - * @return array Array of status, comment, and optional identifier + * @param \SqlConnector\Model\Entity\SqlProvisioner $SqlProvisioner SqlProvisioner configuration + * @param string $entityName Entity name of primary object being provisioned + * @param object $data Provisioning data in Entity format (eg: \App\Model\Entity\Person) + * @param string $eligibility Provisioning Eligibility Enum + * @param string $dataSource Datasource to provision to + * @return array Array of status, comment, and optional identifier */ protected function syncEntity( @@ -759,12 +736,12 @@ public function syncReferenceData(int $id, string $dataSource='targetdb') { * Sync related entities to the target database schema. * * @since COmanage Registry v5.0.0 - * @param SqlProvisioner $SqlProvisioner SqlProvisioner configuration - * @param string $parentEntityName Entity name of primary object being provisioned - * @param string $relatedEntityName Entity name of related object being provisioned - * @param object $parentData Provisioning data in Entity format (eg: \App\Model\Entity\Person) for parent - * @param ProvisioningEligibilityEnum $eligibility Provisioning Eligibility Enum - * @param string $dataSource Datasource to provision to + * @param \SqlConnector\Model\Entity\SqlProvisioner $SqlProvisioner SqlProvisioner configuration + * @param string $parentEntityName Entity name of primary object being provisioned + * @param string $relatedEntityName Entity name of related object being provisioned + * @param object $parentData Provisioning data in Entity format (eg: \App\Model\Entity\Person) for parent + * @param string $eligibility Provisioning Eligibility Enum + * @param string $dataSource Datasource to provision to */ protected function syncRelatedEntities( diff --git a/app/config/bootstrap.php b/app/config/bootstrap.php index f4dcc6ecc..0f4c9f185 100644 --- a/app/config/bootstrap.php +++ b/app/config/bootstrap.php @@ -253,7 +253,7 @@ \Cake\Utility\Inflector::rules('uninflected', ['cous' => 'cous']); \Cake\Utility\Inflector::rules('irregular', ['meta' => 'meta']); // \Cake\Utility\Inflector::rules('irregular', ['terms_and_condition' => 'terms_and_conditions']); -\Cake\Utility\Inflector::rules('uninflected', ['terms_and_conditions' => 'terms_and_conditions']); +\Cake\Utility\Inflector::rules('uninflected', ['TermsAndConditions', 'terms_and_conditions']); /* * Define some constants diff --git a/app/src/Controller/TermsAndConditionsController.php b/app/src/Controller/TermsAndConditionsController.php index 4bdb8de6c..d30814b4d 100644 --- a/app/src/Controller/TermsAndConditionsController.php +++ b/app/src/Controller/TermsAndConditionsController.php @@ -99,22 +99,6 @@ public function agree(string $id) { return $this->redirect(['action' => 'review', '?' => ['co_id' => $this->getCOID()]]); } - /** - * Callback run prior to the request render. - * - * @since COmanage Registry v5.1.0 - * @param EventInterface $event Cake Event - * @return \Cake\Http\Response HTTP Response - */ - - public function beforeRender(\Cake\Event\EventInterface $event) { - $this->set('vv_base_url', \Cake\Routing\Router::url( - url: "/" . $this->getCOID(), - full: true - )); - - return parent::beforeRender($event); - } /** * Proxy an Agreement on behalf of a Person. diff --git a/app/src/Model/Entity/TAndCAgreement.php b/app/src/Model/Entity/TAndCAgreement.php index bd2044691..dbc2ba0b5 100644 --- a/app/src/Model/Entity/TAndCAgreement.php +++ b/app/src/Model/Entity/TAndCAgreement.php @@ -29,14 +29,50 @@ namespace App\Model\Entity; +use Cake\Core\Configure; use Cake\ORM\Entity; +use Cake\ORM\TableRegistry; class TAndCAgreement extends Entity { use \App\Lib\Traits\EntityMetaTrait; - + use \App\Lib\Traits\LabeledLogTrait; + protected array $_accessible = [ '*' => true, 'id' => false, 'slug' => false, ]; + + /** + * Get the URL for this Terms and Conditions Agreement. + * + * @since COmanage Registry v5.3.0 + * @return string|null URL + */ + + protected function _getUrl(): ?string { + // If the associated TermsAndConditions is already loaded, check it first + if(!empty($this->terms_and_conditions)) { + return $this->terms_and_conditions->url; + } + + // Otherwise look up the Terms and Conditions if terms_and_conditions_id is present + if(!empty($this->terms_and_conditions_id)) { + try { + $TermsAndConditions = TableRegistry::getTableLocator()->get('TermsAndConditions'); + + return $TermsAndConditions->get($this->terms_and_conditions_id)->url; + } catch(\Exception $e) { + // We will rethrow here to facilitate debugging + if (Configure::read('debug')) { + throw $e; + } + + $this->llog('error', $e->getMessage()); + return null; + } + } + + return null; + } } \ No newline at end of file diff --git a/app/src/Model/Entity/TermsAndConditions.php b/app/src/Model/Entity/TermsAndConditions.php index 0cd04e432..a992791e5 100644 --- a/app/src/Model/Entity/TermsAndConditions.php +++ b/app/src/Model/Entity/TermsAndConditions.php @@ -29,14 +29,53 @@ namespace App\Model\Entity; +use Cake\Core\Configure; use Cake\ORM\Entity; +use Cake\ORM\TableRegistry; class TermsAndConditions extends Entity { use \App\Lib\Traits\EntityMetaTrait; - + use \App\Lib\Traits\LabeledLogTrait; + protected array $_accessible = [ '*' => true, 'id' => false, 'slug' => false, ]; + + /** + * Get the URL for this Terms and Conditions as a virtual field. + * + * @param string|null $url Existing URL field value + * @return string|null URL + * @throws \Exception + * @since COmanage Registry v5.3.0 + */ + protected function _getUrl(?string $url = null): ?string { + if(!empty($url)) { + return $url; + } + + if(!empty($this->mostly_static_page?->url)) { + return $this->mostly_static_page->url; + } + + if(!empty($this->mostly_static_page_id)) { + try { + $MSPTable = TableRegistry::getTableLocator()->get('MostlyStaticPages'); + $msp = $MSPTable->get($this->mostly_static_page_id); + return $msp->url; + } catch(\Exception $e) { + // We will rethrow here to facilitate debugging + if (Configure::read('debug')) { + throw $e; + } + + $this->llog('error', $e->getMessage()); + return null; + } + } + + return null; + } } \ No newline at end of file diff --git a/app/src/Model/Table/PeopleTable.php b/app/src/Model/Table/PeopleTable.php index 4d45589a2..990e32fe3 100644 --- a/app/src/Model/Table/PeopleTable.php +++ b/app/src/Model/Table/PeopleTable.php @@ -506,6 +506,11 @@ public function marshalProvisioningData(int $id): array { 'Types' ], 'Pronouns', + // TAndCAgreements are provisionable sub-objects, but TermsAndConditions + // and MostlyStaticPages are configuration and are not provisionable. + // We do not contain TermsAndConditions => MostlyStaticPages here to maintain + // loose coupling and avoid synchronization/ownership issues; provisioners + // can resolve the T&C URL via the TAndCAgreement virtual field or reference data. 'TAndCAgreements', 'TelephoneNumbers' => [ 'Types' ], 'Urls' => [ 'Types' ] diff --git a/app/templates/TermsAndConditions/columns.inc b/app/templates/TermsAndConditions/columns.inc index 620e141ba..f1248e8fd 100644 --- a/app/templates/TermsAndConditions/columns.inc +++ b/app/templates/TermsAndConditions/columns.inc @@ -49,13 +49,6 @@ $rowActions = [ [ 'icon' => 'arrow_outward', 'label' => __d('operation', 'visit.tandc'), - 'callbackUrl' => function($entity) use ($vv_base_url) { - // There should always be either a Mostly Static Page or a URL to reference. - if(!empty($entity->mostly_static_page->name)) { - // The T&C is a mostly static page. Provide a link to it. - return $vv_base_url . '/' . $entity->mostly_static_page->name; - } - return $entity->url; - } + 'callbackUrl' => static fn($entity) => $entity->url ] ];