| 1 | <?php |
| 2 | |
| 3 | /** |
| 4 | * Scan for files which implement common Civi-PHP interfaces. |
| 5 | * |
| 6 | * Specifically, this listens to `hook_scanClasses` and reports any classes with Civi-related |
| 7 | * interfaces (eg `CRM_Foo_BarInterface` or `Civi\Foo\BarInterface`). For example: |
| 8 | * |
| 9 | * - \Civi\Core\HookInterface |
| 10 | * - \Civi\Test\ExampleDataInterface |
| 11 | * - \Civi\WorkflowMessage\WorkflowMessageInterface |
| 12 | * |
| 13 | * If you are adding this to an existing extension, take care that you meet these assumptions: |
| 14 | * |
| 15 | * - Classes live in 'CRM_' ('./CRM/**.php') or 'Civi\' ('./Civi/**.php'). |
| 16 | * - Class files only begin with uppercase letters. |
| 17 | * - Class files only contain alphanumerics. |
| 18 | * - Class files never have multiple dots in the name. ("CRM/Foo.php" is a class; "CRM/Foo.bar.php" is not). |
| 19 | * - The ONLY files which match these patterns are STRICTLY class files. |
| 20 | * - The ONLY classes which match these patterns are SAFE/INTENDED for use with `hook_scanClasses`. |
| 21 | * |
| 22 | * To minimize unintended activations, this only loads Civi interfaces. It skips other interfaces. |
| 23 | * |
| 24 | * @mixinName scan-classes |
| 25 | * @mixinVersion 1.0.0 |
| 26 | * @since 5.52 |
| 27 | * |
| 28 | * @param CRM_Extension_MixInfo $mixInfo |
| 29 | * On newer deployments, this will be an instance of MixInfo. On older deployments, Civix may polyfill with a work-a-like. |
| 30 | * @param \CRM_Extension_BootCache $bootCache |
| 31 | * On newer deployments, this will be an instance of MixInfo. On older deployments, Civix may polyfill with a work-a-like. |
| 32 | */ |
| 33 | |
| 34 | /** |
| 35 | * @param \CRM_Extension_MixInfo $mixInfo |
| 36 | * @param \CRM_Extension_BootCache $bootCache |
| 37 | */ |
| 38 | return function ($mixInfo, $bootCache) { |
| 39 | /** |
| 40 | * @param \Civi\Core\Event\GenericHookEvent $event |
| 41 | */ |
| 42 | Civi::dispatcher()->addListener('hook_civicrm_scanClasses', function ($event) use ($mixInfo) { |
| 43 | if (!$mixInfo->isActive()) { |
| 44 | return; |
| 45 | } |
| 46 | |
| 47 | $cache = \Civi\Core\ClassScanner::cache('structure'); |
| 48 | $cacheKey = $mixInfo->longName; |
| 49 | $all = $cache->get($cacheKey); |
| 50 | if ($all === NULL) { |
| 51 | $baseDir = CRM_Utils_File::addTrailingSlash($mixInfo->getPath()); |
| 52 | $all = []; |
| 53 | |
| 54 | \Civi\Core\ClassScanner::scanFolders($all, $baseDir, 'CRM', '_'); |
| 55 | \Civi\Core\ClassScanner::scanFolders($all, $baseDir, 'Civi', '\\'); |
| 56 | if (defined('CIVICRM_TEST')) { |
| 57 | \Civi\Core\ClassScanner::scanFolders($all, "$baseDir/tests/phpunit", 'CRM', '_'); |
| 58 | \Civi\Core\ClassScanner::scanFolders($all, "$baseDir/tests/phpunit", 'Civi', '\\'); |
| 59 | } |
| 60 | $cache->set($cacheKey, $all, \Civi\Core\ClassScanner::TTL); |
| 61 | } |
| 62 | |
| 63 | $event->classes = array_merge($event->classes, $all); |
| 64 | }); |
| 65 | |
| 66 | }; |