From a76a800b427654def4d06d84dc2c35f05aff42c3 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Mon, 22 Mar 2021 16:40:39 -0700 Subject: [PATCH] info.xml - Allow PSR-0 style class-loader declarations Before ------ If an extension defines a class in the style of `CRM_Foo_Bar`, then it *must* use `hook_civicrm_config` and modify the `include_path`. ```php function mymod_civicrm_config(&$config = NULL) { $extRoot = dirname(__FILE__) . DIRECTORY_SEPARATOR; $include_path = $extRoot . PATH_SEPARATOR . get_include_path(); set_include_path($include_path); } ``` Consequently: * The `include_path` gets rather long. * Setting up the extension class-loader is not sufficient for loading these classes. You must wait until the DB has initialized and the `hook_civicrm_config` has fired. After ----- An extension *may* setup classloading in `info.xml`, e.g. ```xml ``` If the `` style is used, then it is possible to scan the extension classes without fully booting the extension. This is a pre-requisite for using interfaces, annotations, or similar for event-registration. Comments -------- * This style closely parallels the `` support in `info.xml`, and it parallels the semantics of `composer.json`. * It is still valid for an extension to set `include_path` -- that works the same as ever. --- CRM/Extension/ClassLoader.php | 11 +++++++++++ CRM/Extension/Info.php | 7 +++++++ tests/phpunit/CRM/Extension/InfoTest.php | 9 ++++++++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CRM/Extension/ClassLoader.php b/CRM/Extension/ClassLoader.php index 2e181a8877..5b0f30725e 100644 --- a/CRM/Extension/ClassLoader.php +++ b/CRM/Extension/ClassLoader.php @@ -14,6 +14,13 @@ */ class CRM_Extension_ClassLoader { + /** + * List of class-loader features that are valid in this version of Civi. + * + * This may be useful for some extensions which enable/disable polyfills based on environment. + */ + const FEATURES = ',psr0,psr4,'; + /** * @var CRM_Extension_Mapper */ @@ -92,6 +99,10 @@ class CRM_Extension_ClassLoader { if (!empty($info->classloader)) { foreach ($info->classloader as $mapping) { switch ($mapping['type']) { + case 'psr0': + $loader->add($mapping['prefix'], CRM_Utils_File::addTrailingSlash($path . '/' . $mapping['path'])); + break; + case 'psr4': $loader->addPsr4($mapping['prefix'], $path . '/' . $mapping['path']); break; diff --git a/CRM/Extension/Info.php b/CRM/Extension/Info.php index 7a0683be43..67a58af265 100644 --- a/CRM/Extension/Info.php +++ b/CRM/Extension/Info.php @@ -175,6 +175,13 @@ class CRM_Extension_Info { 'path' => (string) $psr4->attributes()->path, ]; } + foreach ($val->psr0 as $psr0) { + $this->classloader[] = [ + 'type' => 'psr0', + 'prefix' => (string) $psr0->attributes()->prefix, + 'path' => (string) $psr0->attributes()->path, + ]; + } } elseif ($attr === 'tags') { $this->tags = []; diff --git a/tests/phpunit/CRM/Extension/InfoTest.php b/tests/phpunit/CRM/Extension/InfoTest.php index 77b46076ac..c016abd51c 100644 --- a/tests/phpunit/CRM/Extension/InfoTest.php +++ b/tests/phpunit/CRM/Extension/InfoTest.php @@ -55,7 +55,10 @@ class CRM_Extension_InfoTest extends CiviUnitTestCase { public function testGood_string_extras() { $data = "testbar - + + + + org.civicrm.aorg.civicrm.b "; @@ -65,6 +68,10 @@ class CRM_Extension_InfoTest extends CiviUnitTestCase { $this->assertEquals('testbar', $info->file); $this->assertEquals('Civi\\', $info->classloader[0]['prefix']); $this->assertEquals('Civi', $info->classloader[0]['path']); + $this->assertEquals('psr4', $info->classloader[0]['type']); + $this->assertEquals('CRM_', $info->classloader[1]['prefix']); + $this->assertEquals('', $info->classloader[1]['path']); + $this->assertEquals('psr0', $info->classloader[1]['type']); $this->assertEquals(['org.civicrm.a', 'org.civicrm.b'], $info->requires); } -- 2.25.1