diff --git a/CRM/Geocoder/Upgrader.php b/CRM/Geocoder/Upgrader.php index 988c7c5..96d7860 100644 --- a/CRM/Geocoder/Upgrader.php +++ b/CRM/Geocoder/Upgrader.php @@ -18,6 +18,89 @@ public function install() { civicrm_api3('Setting', 'create', ['geoProvider' => 'Geocoder']); } + /** + * This function should be called by CRM_Extension_Upgrader_Base::onPostInstall + * in order to be able to work on managed entities + * only during install (and not during upgrade) + */ + public function postInstall() { + $this->metadataEnableOnPostInstall(); + + } + + /** + * Some providers are not enabled through the managed entities, + * but uses metadata to require activation on install. + */ + protected function metadataEnableOnPostInstall() { + $geoCoders = []; + //defined in geocoder.php + geocoder_civicrm_geo_managed($geoCoders); + /* we only need to enable geocoders that are not marked as active but that are enabled on install*/ + + $geoCodersToEnableOnPostInstall = array_filter($geoCoders, function($geocoder) { + return static::managedEntityHasName($geocoder) + && static::managedEntityIsEnabledOnInstall($geocoder) + && static::managedEntityIsNotActive($geocoder); + + }); + + $geoCodersNames = array_map(function($geocoder) { + return $geocoder['name']; + }, $geoCodersToEnableOnPostInstall); + array_walk($geoCodersNames, function($geoCoderName) { + static::activateGeocoder($geoCoderName); + }); + + } + + /** + * Activate a geocoder by its name + * @param $geoCoderName string name of the GeoCoder to activate + * @return void + * @throws \CiviCRM_API3_Exception + */ + protected static function activateGeocoder($geoCoderName) { + /*api3 does error checking itself, so there is less need to do checking*/ + $geoCoderId = civicrm_api3('Geocoder', 'getvalue', ['return' => "id", 'name' => $geoCoderName]); + civicrm_api3('Geocoder', 'create', ['id' => $geoCoderId, 'is_active' => 1]); + } + + /** + * Check whether a geocoder has a name + * according to a managed entity definition + * @param $geocoder array Array corresponding to a geocoder managed entity (as per geocoder_civicrm_geo_managed) + * @return bool + */ + protected static function managedEntityHasName($geocoder) { + return is_array($geocoder) && array_key_exists('name', $geocoder) + && is_string($geocoder['name']); + } + + /** + * Check whether a geocoder should be enabled on install or not, + * according to a managed entity definition + * @param $geocoder array Array corresponding to a geocoder managed entity (as per geocoder_civicrm_geo_managed) + * @return bool + */ + protected static function managedEntityIsEnabledOnInstall($geocoder) { + return is_array($geocoder) && array_key_exists('metadata', $geocoder) + && is_array($geocoder['metadata']) && array_key_exists('is_enabled_on_install', $geocoder['metadata']) + && $geocoder['metadata']['is_enabled_on_install'] === TRUE; + } + + /** + * Check whether a geocoder should be active or not, + * according to a manged entity definition + * @param $geocoder array Array corresponding to a geocoder managed entity (as per geocoder_civicrm_geo_managed) + * @return bool : return true if the geocoder should not be active ; false otherwise + */ + protected static function managedEntityIsNotActive($geocoder) { + return is_array($geocoder) && array_key_exists('params', $geocoder) + && is_array($geocoder['params']) && array_key_exists('is_active', $geocoder['params']) + && $geocoder['params']['is_active'] === FALSE; + } + /** * Add parameter column in DB * @@ -29,17 +112,17 @@ public function upgrade_1100() { return TRUE; } - /** - * Update the URL for Open Street Map end point - * - * @throws \CiviCRM_API3_Exception - */ - public function upgrade_1200() { - $this->ctx->log->info( 'Applying update 1200: Update the URL for Open Street Map end point' ); - CRM_Core_DAO::executeQuery( "UPDATE `civicrm_geocoder` SET `url` = 'https://nominatim.openstreetmap.org' WHERE `url` LIKE '%nominatim.openstreetmap.org%'" ); + /** + * Update the URL for Open Street Map end point + * + * @throws \CiviCRM_API3_Exception + */ + public function upgrade_1200() { + $this->ctx->log->info('Applying update 1200: Update the URL for Open Street Map end point'); + CRM_Core_DAO::executeQuery("UPDATE `civicrm_geocoder` SET `url` = 'https://nominatim.openstreetmap.org' WHERE `url` LIKE '%nominatim.openstreetmap.org%'"); - return TRUE; - } + return TRUE; + } /** * Add new providers. @@ -73,7 +156,7 @@ private function update_providers() { * Example: Run an external SQL script when the module is uninstalled. */ public function uninstall() { - $this->executeSqlFile('sql/uninstall.sql'); + $this->executeSqlFile('sql/uninstall.sql'); civicrm_api3('Setting', 'create', ['geoProvider' => 'null']); } diff --git a/tests/phpunit/UpgraderTest.php b/tests/phpunit/UpgraderTest.php new file mode 100644 index 0000000..ce1cd59 --- /dev/null +++ b/tests/phpunit/UpgraderTest.php @@ -0,0 +1,79 @@ + "abc"], TRUE], + + ]; + + } + + /** + * @dataProvider managedEntityHasNameDataProvider + * @param $entity + * @param $expected + * @return void + * @throws ReflectionException + */ + public function testManagedEntityHasName($entity, $expected) { + $method = new ReflectionMethod("CRM_Geocoder_Upgrader::managedEntityHasName"); + $method->setAccessible(TRUE); + $computed = $method->invoke(NULL, $entity); + $this->assertEquals($expected, $computed); + } + + public function managedEntityIsEnabledOnInstallDataProvider() { + return [ + [NULL, FALSE], + [[], FALSE], + [["metadata" => NULL], FALSE], + [["metadata" => []], FALSE], + [["metadata" => ["is_enabled_on_install" => FALSE]], FALSE], + [["metadata" => ["is_enabled_on_install" => TRUE]], TRUE], + ]; + } + + /** + * @dataProvider managedEntityIsEnabledOnInstallDataProvider + * @param $entity + * @param $expected + * @return void + * @throws ReflectionException + */ + public function testManagedEntityIsEnabledOnInstall($entity, $expected) { + $method = new ReflectionMethod("CRM_Geocoder_Upgrader::managedEntityIsEnabledOnInstall"); + $method->setAccessible(TRUE); + $computed = $method->invoke(NULL, $entity); + $this->assertEquals($expected, $computed); + } + + public function managedEntityIsNotActiveDataProvider() { + return [ + [NULL, FALSE], + [[], FALSE], + [["params" => NULL], FALSE], + [["params" => []], FALSE], + [["params" => ["is_active" => FALSE]], TRUE], + [["metadata" => ["is_active" => TRUE]], FALSE], + ]; + } + + /** + * @dataProvider managedEntityIsNotActiveDataProvider + * @param $entity + * @param $expected + * @return void + * @throws ReflectionException + */ + public function testManagedEntityIsNotActive($entity, $expected) { + $method = new ReflectionMethod("CRM_Geocoder_Upgrader::managedEntityIsNotActive"); + $method->setAccessible(TRUE); + $computed = $method->invoke(NULL, $entity); + $this->assertEquals($expected, $computed); + } + +}