1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
<?php
/**
* Matomo - free/libre analytics platform
*
* @link https://matomo.org
* @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
namespace Piwik\Plugin;
use Piwik\Log;
use Piwik\Plugin\Manager as PluginManager;
use Exception;
/**
* Factory class with methods to find and instantiate Plugin components.
*/
class ComponentFactory
{
/**
* Create a component instance that exists within a specific plugin. Uses the component's
* unqualified class name and expected base type.
*
* This method will only create a class if it is located within the component type's
* associated subdirectory.
*
* @param string $pluginName The name of the plugin the component is expected to belong to,
* eg, `'DevicesDetection'`.
* @param string $componentClassSimpleName The component's class name w/o namespace, eg,
* `"GetKeywords"`.
* @param string $componentTypeClass The fully qualified class name of the component type, eg,
* `"Piwik\Plugin\Report"`.
*
* @template T of object
* @phpstan-param class-string<T> $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 $pluginName|false 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<T> $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;
}
}
}
|