$componentTypeClass * * @return T|null A new instance of the desired component or null if not found. If the * plugin is not loaded or activated or the component is not located in * in the sub-namespace specified by `$componentTypeClass::COMPONENT_SUBNAMESPACE`, * this method will return null. */ public static function factory($pluginName, $componentClassSimpleName, $componentTypeClass) { if (empty($pluginName) || empty($componentClassSimpleName)) { Log::debug( "ComponentFactory::%s: empty plugin name or component simple name requested (%s, %s)", __FUNCTION__, $pluginName, $componentClassSimpleName ); return null; } $plugin = self::getActivatedPlugin(__FUNCTION__, $pluginName); if (empty($plugin)) { return null; } $subnamespace = $componentTypeClass::COMPONENT_SUBNAMESPACE; $desiredComponentClass = 'Piwik\\Plugins\\' . $pluginName . '\\' . $subnamespace . '\\' . $componentClassSimpleName; $components = $plugin->findMultipleComponents($subnamespace, $componentTypeClass); foreach ($components as $class) { if ($class === $desiredComponentClass) { return new $class(); } } Log::debug( "ComponentFactory::%s: Could not find requested component (args = ['%s', '%s', '%s']).", __FUNCTION__, $pluginName, $componentClassSimpleName, $componentTypeClass ); return null; } /** * Finds a component instance that satisfies a given predicate. * * @param string $componentTypeClass The fully qualified class name of the component type, eg, * `"Piwik\Plugin\Report"`. * @param string|false $pluginName The name of the plugin the component is expected to belong to, * eg, `'DevicesDetection'`. * @param callable $predicate * * @template T of object * @phpstan-param class-string $componentTypeClass * @phpstan-param callable(T): bool $predicate * * @return T|null The component that satisfies $predicate or null if not found. */ public static function getComponentIf($componentTypeClass, $pluginName, $predicate) { $pluginManager = PluginManager::getInstance(); // get components to search through $subnamespace = $componentTypeClass::COMPONENT_SUBNAMESPACE; if (empty($pluginName)) { $components = $pluginManager->findMultipleComponents($subnamespace, $componentTypeClass); } else { $plugin = self::getActivatedPlugin(__FUNCTION__, $pluginName); if (empty($plugin)) { return null; } $components = $plugin->findMultipleComponents($subnamespace, $componentTypeClass); } // find component that satisfieds predicate foreach ($components as $class) { $component = new $class(); if ($predicate($component)) { return $component; } } Log::debug( "ComponentFactory::%s: Could not find component that satisfies predicate (args = ['%s', '%s', '%s']).", __FUNCTION__, $componentTypeClass, $pluginName, get_class($predicate) ); return null; } /** * @param string $function * @param string $pluginName * @return null|\Piwik\Plugin */ private static function getActivatedPlugin($function, $pluginName) { $pluginManager = PluginManager::getInstance(); try { if (!$pluginManager->isPluginActivated($pluginName)) { Log::debug( "ComponentFactory::%s: component for deactivated plugin ('%s') requested.", $function, $pluginName ); return null; } return $pluginManager->getLoadedPlugin($pluginName); } catch (Exception $e) { Log::debug($e); return null; } } }