]> git.mxchange.org Git - friendica.git/commitdiff
Introduce dynamic hook loading
authorPhilipp <admin@philipp.info>
Sun, 2 Jul 2023 21:56:56 +0000 (23:56 +0200)
committerPhilipp <admin@philipp.info>
Sun, 16 Jul 2023 16:43:35 +0000 (18:43 +0200)
- Dynamically load addon files
- Dynamically load hooks
- Rewrite Logger-logic to use new hook logic (Monolog is working again)

43 files changed:
bin/auth_ejabberd.php
bin/console.php
bin/daemon.php
bin/worker.php
index.php
src/Core/Addon/Capabilities/ICanLoadAddons.php [new file with mode: 0644]
src/Core/Addon/Exception/AddonInvalidConfigFileException.php [new file with mode: 0644]
src/Core/Addon/Model/AddonLoader.php [new file with mode: 0644]
src/Core/Hooks/Capabilities/HookType.php [new file with mode: 0644]
src/Core/Hooks/Capabilities/IAmAStrategy.php [deleted file]
src/Core/Hooks/Capabilities/ICanCreateInstances.php [new file with mode: 0644]
src/Core/Hooks/Capabilities/ICanManageInstances.php [deleted file]
src/Core/Hooks/Capabilities/ICanRegisterInstances.php [new file with mode: 0644]
src/Core/Hooks/Exceptions/HookConfigException.php [new file with mode: 0644]
src/Core/Hooks/Model/DiceInstanceManager.php [new file with mode: 0644]
src/Core/Hooks/Model/InstanceManager.php [deleted file]
src/Core/Hooks/Util/HookFileManager.php [new file with mode: 0644]
src/Core/Logger/Capabilities/ICheckLoggerSettings.php [new file with mode: 0644]
src/Core/Logger/Capabilities/IHaveCallIntrospections.php
src/Core/Logger/Capabilities/LogChannel.php [new file with mode: 0644]
src/Core/Logger/Exception/LogLevelException.php
src/Core/Logger/Exception/LoggerArgumentException.php
src/Core/Logger/Exception/LoggerException.php
src/Core/Logger/Exception/LoggerInvalidException.php [deleted file]
src/Core/Logger/Exception/LoggerUnusableException.php [new file with mode: 0644]
src/Core/Logger/Factory/AbstractLoggerTypeFactory.php [new file with mode: 0644]
src/Core/Logger/Factory/Logger.php
src/Core/Logger/Factory/ProfilerLogger.php [new file with mode: 0644]
src/Core/Logger/Factory/StreamLogger.php [new file with mode: 0644]
src/Core/Logger/Factory/SyslogLogger.php [new file with mode: 0644]
src/Core/Logger/Type/README.md [deleted file]
src/Core/Logger/Type/StreamLogger.php
src/Core/Logger/Type/SyslogLogger.php
src/Core/Logger/Util/FileSystem.php [new file with mode: 0644]
src/Core/Logger/Util/LoggerSettingsCheck.php [new file with mode: 0644]
src/DI.php
src/Module/Admin/Summary.php
src/Util/FileSystem.php [deleted file]
static/dependencies.config.php
static/hooks.config.php [new file with mode: 0644]
tests/Util/Hooks/InstanceMocks/FakeInstance.php
tests/src/Core/Hooks/Model/InstanceManagerTest.php
tests/src/Core/Logger/StreamLoggerTest.php

index 40e7d3b97c3e80ec678837f02a49e5a14d6cfb6c..b923009e642555c2142b566065d34d7719f98222 100755 (executable)
@@ -58,6 +58,7 @@ if (php_sapi_name() !== 'cli') {
 
 use Dice\Dice;
 use Friendica\App\Mode;
+use Friendica\Core\Logger\Capabilities\LogChannel;
 use Friendica\Security\ExAuth;
 use Psr\Log\LoggerInterface;
 
@@ -78,7 +79,10 @@ chdir($directory);
 require dirname(__DIR__) . '/vendor/autoload.php';
 
 $dice = (new Dice())->addRules(include __DIR__ . '/../static/dependencies.config.php');
-$dice = $dice->addRule(LoggerInterface::class,['constructParams' => ['auth_ejabberd']]);
+/** @var \Friendica\Core\Addon\Capabilities\ICanLoadAddons $addonLoader */
+$addonLoader = $dice->create(\Friendica\Core\Addon\Capabilities\ICanLoadAddons::class);
+$dice = $dice->addRules($addonLoader->getActiveAddonConfig('dependencies'));
+$dice = $dice->addRule(LoggerInterface::class,['constructParams' => [LogChannel::AUTH_JABBERED]]);
 
 \Friendica\DI::init($dice);
 \Friendica\Core\Logger\Handler\ErrorHandler::register($dice->create(\Psr\Log\LoggerInterface::class));
index e1bc6b498547f4e15e368ad429c489333a474bd9..b2cde10823f7c1a8af7bc672605e5f60f573f1b4 100755 (executable)
@@ -26,13 +26,17 @@ if (php_sapi_name() !== 'cli') {
 }
 
 use Dice\Dice;
+use Friendica\Core\Logger\Capabilities\LogChannel;
 use Friendica\DI;
 use Psr\Log\LoggerInterface;
 
 require dirname(__DIR__) . '/vendor/autoload.php';
 
 $dice = (new Dice())->addRules(include __DIR__ . '/../static/dependencies.config.php');
-$dice = $dice->addRule(LoggerInterface::class,['constructParams' => ['console']]);
+/** @var \Friendica\Core\Addon\Capabilities\ICanLoadAddons $addonLoader */
+$addonLoader = $dice->create(\Friendica\Core\Addon\Capabilities\ICanLoadAddons::class);
+$dice = $dice->addRules($addonLoader->getActiveAddonConfig('dependencies'));
+$dice = $dice->addRule(LoggerInterface::class, ['constructParams' => [LogChannel::CONSOLE]]);
 
 /// @fixme Necessary until Hooks inside the Logger can get loaded without the DI-class
 DI::init($dice);
index e550aea891ed157adad7b585019598a68dab80b5..1f0bb7079d21075b93abeff5a467b41f4c07d06b 100755 (executable)
@@ -38,7 +38,6 @@ use Friendica\Core\Worker;
 use Friendica\Database\DBA;
 use Friendica\DI;
 use Friendica\Util\DateTimeFormat;
-use Psr\Log\LoggerInterface;
 
 // Get options
 $shortopts = 'f';
@@ -60,7 +59,10 @@ if (!file_exists('index.php') && (sizeof($_SERVER['argv']) != 0)) {
 require dirname(__DIR__) . '/vendor/autoload.php';
 
 $dice = (new Dice())->addRules(include __DIR__ . '/../static/dependencies.config.php');
-$dice = $dice->addRule(LoggerInterface::class,['constructParams' => ['daemon']]);
+/** @var \Friendica\Core\Addon\Capabilities\ICanLoadAddons $addonLoader */
+$addonLoader = $dice->create(\Friendica\Core\Addon\Capabilities\ICanLoadAddons::class);
+$dice = $dice->addRules($addonLoader->getActiveAddonConfig('dependencies'));
+$dice = $dice->addRule(LoggerInterface::class,['constructParams' => [Logger\Capabilities\LogChannel::DAEMON]]);
 
 DI::init($dice);
 \Friendica\Core\Logger\Handler\ErrorHandler::register($dice->create(\Psr\Log\LoggerInterface::class));
index a742132480b923adc203faded953d028660a768d..18a41e06436fab83fdc78fca66ddf64c0c438984 100755 (executable)
@@ -29,6 +29,7 @@ if (php_sapi_name() !== 'cli') {
 use Dice\Dice;
 use Friendica\App;
 use Friendica\App\Mode;
+use Friendica\Core\Logger\Capabilities\LogChannel;
 use Friendica\Core\Update;
 use Friendica\Core\Worker;
 use Friendica\DI;
@@ -54,7 +55,10 @@ if (!file_exists("index.php") && (sizeof($_SERVER["argv"]) != 0)) {
 require dirname(__DIR__) . '/vendor/autoload.php';
 
 $dice = (new Dice())->addRules(include __DIR__ . '/../static/dependencies.config.php');
-$dice = $dice->addRule(LoggerInterface::class,['constructParams' => ['worker']]);
+/** @var \Friendica\Core\Addon\Capabilities\ICanLoadAddons $addonLoader */
+$addonLoader = $dice->create(\Friendica\Core\Addon\Capabilities\ICanLoadAddons::class);
+$dice = $dice->addRules($addonLoader->getActiveAddonConfig('dependencies'));
+$dice = $dice->addRule(LoggerInterface::class,['constructParams' => [LogChannel::WORKER]]);
 
 DI::init($dice);
 \Friendica\Core\Logger\Handler\ErrorHandler::register($dice->create(\Psr\Log\LoggerInterface::class));
index 90df9c00e9b77d56d3a1d192836fc48ff772ddad..ce82470b6421d48eeb5ba44fea2d567a816069ee 100644 (file)
--- a/index.php
+++ b/index.php
@@ -30,6 +30,9 @@ if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
 require __DIR__ . '/vendor/autoload.php';
 
 $dice = (new Dice())->addRules(include __DIR__ . '/static/dependencies.config.php');
+/** @var \Friendica\Core\Addon\Capabilities\ICanLoadAddons $addonLoader */
+$addonLoader = $dice->create(\Friendica\Core\Addon\Capabilities\ICanLoadAddons::class);
+$dice = $dice->addRules($addonLoader->getActiveAddonConfig('dependencies'));
 $dice = $dice->addRule(Friendica\App\Mode::class, ['call' => [['determineRunMode', [false, $_SERVER], Dice::CHAIN_CALL]]]);
 
 \Friendica\DI::init($dice);
diff --git a/src/Core/Addon/Capabilities/ICanLoadAddons.php b/src/Core/Addon/Capabilities/ICanLoadAddons.php
new file mode 100644 (file)
index 0000000..a28826f
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2023, the Friendica project
+ *
+ * @license   GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Addon\Capabilities;
+
+/**
+ * Interface for loading Addons specific content
+ */
+interface ICanLoadAddons
+{
+       /**
+        * Returns a merged config array of all active addons for a given config-name
+        *
+        * @param string $configName The config-name (config-file at the static directory, like 'hooks' => '{addon}/static/hooks.config.php)
+        *
+        * @return array the merged array
+        */
+       public function getActiveAddonConfig(string $configName): array;
+}
diff --git a/src/Core/Addon/Exception/AddonInvalidConfigFileException.php b/src/Core/Addon/Exception/AddonInvalidConfigFileException.php
new file mode 100644 (file)
index 0000000..3bb41be
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2023, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Addon\Exception;
+
+use Throwable;
+
+/**
+ * Exception in case one or more config files of the addons are invalid
+ */
+class AddonInvalidConfigFileException extends \RuntimeException
+{
+       public function __construct($message = "", $code = 0, Throwable $previous = null)
+       {
+               parent::__construct($message, 500, $previous);
+       }
+}
diff --git a/src/Core/Addon/Model/AddonLoader.php b/src/Core/Addon/Model/AddonLoader.php
new file mode 100644 (file)
index 0000000..707601a
--- /dev/null
@@ -0,0 +1,70 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2023, the Friendica project
+ *
+ * @license   GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Addon\Model;
+
+use Friendica\Core\Addon\Capabilities\ICanLoadAddons;
+use Friendica\Core\Addon\Exception\AddonInvalidConfigFileException;
+use Friendica\Core\Config\Capability\IManageConfigValues;
+use Friendica\Util\Strings;
+
+class AddonLoader implements ICanLoadAddons
+{
+       const STATIC_PATH = 'static';
+       /** @var string */
+       protected $basePath;
+       /** @var IManageConfigValues */
+       protected $config;
+
+       public function __construct(string $basePath, IManageConfigValues $config)
+       {
+               $this->basePath = $basePath;
+               $this->config   = $config;
+       }
+
+       /** {@inheritDoc} */
+       public function getActiveAddonConfig(string $configName): array
+       {
+               $addons       = array_keys(array_filter($this->config->get('addons') ?? []));
+               $returnConfig = [];
+
+               foreach ($addons as $addon) {
+                       $addonName = Strings::sanitizeFilePathItem(trim($addon));
+
+                       $configFile = $this->basePath . '/addon/' . $addonName . '/' . static::STATIC_PATH . '/' . $configName . '.config.php';
+
+                       if (!file_exists($configFile)) {
+                               // Addon unmodified, skipping
+                               continue;
+                       }
+
+                       $config = include $configFile;
+
+                       if (!is_array($config)) {
+                               throw new AddonInvalidConfigFileException('Error loading config file ' . $configFile);
+                       }
+
+                       $returnConfig = array_merge_recursive($returnConfig, $config);
+               }
+
+               return $returnConfig;
+       }
+}
diff --git a/src/Core/Hooks/Capabilities/HookType.php b/src/Core/Hooks/Capabilities/HookType.php
new file mode 100644 (file)
index 0000000..6fea41e
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2023, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Hooks\Capabilities;
+
+interface HookType
+{
+       /**
+        * Defines the key for the list of strategy-hooks.
+        *
+        * @see https://refactoring.guru/design-patterns/strategy
+        */
+       const STRATEGY = 'strategy';
+       /**
+        * Defines the key for the list of decorator-hooks.
+        *
+        * @see  https://refactoring.guru/design-patterns/decorator
+        */
+       const DECORATOR = 'decorator';
+       const EVENT     = 'event';
+}
diff --git a/src/Core/Hooks/Capabilities/IAmAStrategy.php b/src/Core/Hooks/Capabilities/IAmAStrategy.php
deleted file mode 100644 (file)
index 017cb56..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2023, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Core\Hooks\Capabilities;
-
-/**
- * All classes, implementing this interface are valid Strategies for Hook calls
- */
-interface IAmAStrategy
-{
-}
diff --git a/src/Core/Hooks/Capabilities/ICanCreateInstances.php b/src/Core/Hooks/Capabilities/ICanCreateInstances.php
new file mode 100644 (file)
index 0000000..6e5d8be
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2023, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Hooks\Capabilities;
+
+use Friendica\Core\Hooks\Exceptions\HookInstanceException;
+
+/**
+ * creates special instance and decorator treatments for given classes
+ */
+interface ICanCreateInstances
+{
+       /**
+        * Returns a new instance of a given class for the corresponding name
+        *
+        * The instance will be build based on the registered strategy and the (unique) name
+        *
+        * In case, there are registered decorators for this class as well, all decorators of the list will be wrapped
+        * around the instance before returning it
+        *
+        * @param string $class     The fully-qualified name of the given class or interface which will get returned
+        * @param string $name      An arbitrary identifier to find a concrete instance strategy.
+        * @param array  $arguments Additional arguments, which can be passed to the constructor of "$class" at runtime
+        *
+        * @return object The concrete instance of the type "$class"
+        */
+       public function createWithName(string $class, string $name, array $arguments = []): object;
+
+       /**
+        * Returns a new instance of a given class
+        *
+        * In case, there are registered decorators for this class as well, all decorators of the list will be wrapped
+        * around the instance before returning it
+        *
+        * @param string $class     The fully-qualified name of the given class or interface which will get returned
+        * @param array  $arguments Additional arguments, which can be passed to the constructor of "$class" at runtime
+        *
+        * @return object The concrete instance of the type "$class"
+        */
+       public function create(string $class, array $arguments = []): object;
+}
diff --git a/src/Core/Hooks/Capabilities/ICanManageInstances.php b/src/Core/Hooks/Capabilities/ICanManageInstances.php
deleted file mode 100644 (file)
index bdad1b9..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2023, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Core\Hooks\Capabilities;
-
-use Friendica\Core\Hooks\Exceptions\HookInstanceException;
-use Friendica\Core\Hooks\Exceptions\HookRegisterArgumentException;
-
-/**
- * Managing special instance and decorator treatments for classes
- */
-interface ICanManageInstances
-{
-       /**
-        * Register a class(strategy) for a given interface with a unique name.
-        *
-        * @see https://refactoring.guru/design-patterns/strategy
-        *
-        * @param string $interface  The interface, which the given class implements
-        * @param string $name       An arbitrary identifier for the given class, which will be used for factories, dependency injections etc.
-        * @param string $class      The fully-qualified given class name
-        * @param ?array  $arguments Additional arguments, which can be passed to the constructor
-        *
-        * @return $this This interface for chain-calls
-        *
-        * @throws HookRegisterArgumentException in case the given class for the interface isn't valid or already set
-        */
-       public function registerStrategy(string $interface, string $name, string $class, array $arguments = null): self;
-
-       /**
-        * Register a new decorator for a given class or interface
-        * @see https://refactoring.guru/design-patterns/decorator
-        *
-        * @note Decorator attach new behaviors to classes without changing them or without letting them know about it.
-        *
-        * @param string $class          The fully-qualified class or interface name, which gets decorated by a class
-        * @param string $decoratorClass The fully-qualified name of the class which mimics the given class or interface and adds new functionality
-        * @param array  $arguments      Additional arguments, which can be passed to the constructor of "decoratorClass"
-        *
-        * @return $this This interface for chain-calls
-        *
-        * @throws HookRegisterArgumentException in case the given class for the class or interface isn't valid
-        */
-       public function registerDecorator(string $class, string $decoratorClass, array $arguments = []): self;
-
-       /**
-        * Returns a new instance of a given class for the corresponding name
-        *
-        * The instance will be build based on the registered strategy and the (unique) name
-        *
-        * In case, there are registered decorators for this class as well, all decorators of the list will be wrapped
-        * around the instance before returning it
-        *
-        * @param string $class     The fully-qualified name of the given class or interface which will get returned
-        * @param string $name      An arbitrary identifier to find a concrete instance strategy.
-        * @param array  $arguments Additional arguments, which can be passed to the constructor of "$class" at runtime
-        *
-        * @return object The concrete instance of the type "$class"
-        *
-        * @throws HookInstanceException In case the class cannot get created
-        */
-       public function getInstance(string $class, string $name, array $arguments = []): object;
-}
diff --git a/src/Core/Hooks/Capabilities/ICanRegisterInstances.php b/src/Core/Hooks/Capabilities/ICanRegisterInstances.php
new file mode 100644 (file)
index 0000000..23a77ab
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2023, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Hooks\Capabilities;
+
+use Friendica\Core\Hooks\Exceptions\HookRegisterArgumentException;
+
+/**
+ * Register strategies and decorator/treatment handling for given classes
+ */
+interface ICanRegisterInstances
+{
+       /**
+        * Register a class(strategy) for a given interface with a unique name.
+        *
+        * @see https://refactoring.guru/design-patterns/strategy
+        *
+        * @param string  $interface The interface, which the given class implements
+        * @param string  $class     The fully-qualified given class name
+        *                           A placeholder for dependencies is possible as well
+        * @param ?string $name      An arbitrary identifier for the given class, which will be used for factories, dependency injections etc.
+        *
+        * @return $this This interface for chain-calls
+        *
+        * @throws HookRegisterArgumentException in case the given class for the interface isn't valid or already set
+        */
+       public function registerStrategy(string $interface, string $class, ?string $name = null): self;
+
+       /**
+        * Register a new decorator for a given class or interface
+        *
+        * @see  https://refactoring.guru/design-patterns/decorator
+        *
+        * @note Decorator attach new behaviors to classes without changing them or without letting them know about it.
+        *
+        * @param string $class          The fully-qualified class or interface name, which gets decorated by a class
+        * @param string $decoratorClass The fully-qualified name of the class which mimics the given class or interface and adds new functionality
+        *                               A placeholder for dependencies is possible as well
+        *
+        * @return $this This interface for chain-calls
+        *
+        * @throws HookRegisterArgumentException in case the given class for the class or interface isn't valid
+        */
+       public function registerDecorator(string $class, string $decoratorClass): self;
+}
diff --git a/src/Core/Hooks/Exceptions/HookConfigException.php b/src/Core/Hooks/Exceptions/HookConfigException.php
new file mode 100644 (file)
index 0000000..ceca721
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2023, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Hooks\Exceptions;
+
+class HookConfigException extends \RuntimeException
+{
+       public function __construct($message = "", \Throwable $previous = null)
+       {
+               parent::__construct($message, 500, $previous);
+       }
+}
diff --git a/src/Core/Hooks/Model/DiceInstanceManager.php b/src/Core/Hooks/Model/DiceInstanceManager.php
new file mode 100644 (file)
index 0000000..381e0a7
--- /dev/null
@@ -0,0 +1,111 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2023, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Hooks\Model;
+
+use Dice\Dice;
+use Friendica\Core\Hooks\Capabilities\ICanCreateInstances;
+use Friendica\Core\Hooks\Capabilities\ICanRegisterInstances;
+use Friendica\Core\Hooks\Exceptions\HookInstanceException;
+use Friendica\Core\Hooks\Exceptions\HookRegisterArgumentException;
+use Friendica\Core\Hooks\Util\HookFileManager;
+
+/**
+ * This class represents an instance register, which uses Dice for creation
+ *
+ * @see Dice
+ */
+class DiceInstanceManager implements ICanCreateInstances, ICanRegisterInstances
+{
+       protected $instance = [];
+       protected $decorator = [];
+
+       /** @var Dice */
+       protected $dice;
+
+       public function __construct(Dice $dice, HookFileManager $hookFileManager)
+       {
+               $this->dice = $dice;
+               $hookFileManager->setupHooks($this);
+       }
+
+       /** {@inheritDoc} */
+       public function registerStrategy(string $interface, string $class, ?string $name = null): ICanRegisterInstances
+       {
+               if (!empty($this->instance[$interface][$name])) {
+                       throw new HookRegisterArgumentException(sprintf('A class with the name %s is already set for the interface %s', $name, $interface));
+               }
+
+               $this->instance[$interface][$name] = $class;
+
+               return $this;
+       }
+
+       /** {@inheritDoc} */
+       public function registerDecorator(string $class, string $decoratorClass): ICanRegisterInstances
+       {
+               $this->decorator[$class][] = $decoratorClass;
+
+               return $this;
+       }
+
+       /** {@inheritDoc} */
+       public function create(string $class, array $arguments = []): object
+       {
+               $instanceClassName = $class;
+               $instanceRule      = $this->dice->getRule($instanceClassName) ?? [];
+
+               $instanceRule = array_replace_recursive($instanceRule, [
+                       'constructParams' => $arguments,
+               ]);
+
+               $this->dice = $this->dice->addRule($instanceClassName, $instanceRule);
+
+               foreach ($this->decorator[$class] ?? [] as $decorator) {
+                       $dependencyRule = $this->dice->getRule($decorator);
+                       for ($i = 0; $i < count($dependencyRule['call'] ?? []); $i++) {
+                               $dependencyRule['call'][$i][1] = [[Dice::INSTANCE => $instanceClassName]];
+                       }
+                       $dependencyRule['constructParams'] = $arguments;
+                       $dependencyRule['substitutions']   = [
+                               $class => $instanceClassName,
+                       ];
+
+                       $this->dice = $this->dice->addRule($decorator, $dependencyRule);
+
+                       $instanceClassName = $decorator;
+               }
+
+               return $this->dice->create($instanceClassName);
+       }
+
+       /** {@inheritDoc} */
+       public function createWithName(string $class, string $name, array $arguments = []): object
+       {
+               if (empty($this->instance[$class][$name])) {
+                       throw new HookInstanceException(sprintf('The class with the name %s isn\'t registered for the class or interface %s', $name, $class));
+               }
+
+               $instanceClassName = $this->instance[$class][$name];
+
+               return $this->create($instanceClassName, $arguments);
+       }
+}
diff --git a/src/Core/Hooks/Model/InstanceManager.php b/src/Core/Hooks/Model/InstanceManager.php
deleted file mode 100644 (file)
index 7bfcfa4..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2023, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Core\Hooks\Model;
-
-use Dice\Dice;
-use Friendica\Core\Hooks\Capabilities\IAmAStrategy;
-use Friendica\Core\Hooks\Capabilities\ICanManageInstances;
-use Friendica\Core\Hooks\Exceptions\HookInstanceException;
-use Friendica\Core\Hooks\Exceptions\HookRegisterArgumentException;
-
-/** {@inheritDoc} */
-class InstanceManager implements ICanManageInstances
-{
-       protected $instance          = [];
-       protected $instanceArguments = [];
-       protected $decorator         = [];
-
-       /** @var Dice */
-       protected $dice;
-
-       public function __construct(Dice $dice)
-       {
-               $this->dice = $dice;
-       }
-
-       /** {@inheritDoc} */
-       public function registerStrategy(string $interface, string $name, string $class, array $arguments = null): ICanManageInstances
-       {
-               if (!is_a($class, $interface, true)) {
-                       throw new HookRegisterArgumentException(sprintf('%s is not a valid class for the interface %s', $class, $interface));
-               }
-
-               if (!is_a($class, IAmAStrategy::class, true)) {
-                       throw new HookRegisterArgumentException(sprintf('%s does not inherit from the marker interface %s', $class, IAmAStrategy::class));
-               }
-
-               if (!empty($this->instance[$interface][$name])) {
-                       throw new HookRegisterArgumentException(sprintf('A class with the name %s is already set for the interface %s', $name, $interface));
-               }
-
-               $this->instance[$interface][$name]          = $class;
-               $this->instanceArguments[$interface][$name] = $arguments;
-
-               return $this;
-       }
-
-       /** {@inheritDoc} */
-       public function registerDecorator(string $class, string $decoratorClass, array $arguments = []): ICanManageInstances
-       {
-               if (!is_a($decoratorClass, $class, true)) {
-                       throw new HookRegisterArgumentException(sprintf('%s is not a valid substitution for the given class or interface %s', $decoratorClass, $class));
-               }
-
-               $this->decorator[$class][] = [
-                       'class'     => $decoratorClass,
-                       'arguments' => $arguments,
-               ];
-
-               return $this;
-       }
-
-       /** {@inheritDoc} */
-       public function getInstance(string $class, string $name, array $arguments = []): object
-       {
-               if (empty($this->instance[$class][$name])) {
-                       throw new HookInstanceException(sprintf('The class with the name %s isn\'t registered for the class or interface %s', $name, $class));
-               }
-
-               $instance = $this->dice->create($this->instance[$class][$name], array_merge($this->instanceArguments[$class][$name] ?? [], $arguments));
-
-               foreach ($this->decorator[$class] ?? [] as $decorator) {
-                       $this->dice = $this->dice->addRule($class, [
-                               'instanceOf'      => $decorator['class'],
-                               'constructParams' => empty($decorator['arguments']) ? null : $decorator['arguments'],
-                               /// @todo maybe support call structures for hooks as well in a later stage - could make factory calls easier
-                               'call'          => null,
-                               'substitutions' => [$class => $instance],
-                       ]);
-
-                       $instance = $this->dice->create($class);
-               }
-
-               return $instance;
-       }
-}
diff --git a/src/Core/Hooks/Util/HookFileManager.php b/src/Core/Hooks/Util/HookFileManager.php
new file mode 100644 (file)
index 0000000..3575678
--- /dev/null
@@ -0,0 +1,118 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2023, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Hooks\Util;
+
+use Friendica\Core\Addon\Capabilities\ICanLoadAddons;
+use Friendica\Core\Hooks\Capabilities\HookType;
+use Friendica\Core\Hooks\Capabilities\ICanRegisterInstances;
+use Friendica\Core\Hooks\Exceptions\HookConfigException;
+
+/**
+ * Manage all hooks.config.php files
+ */
+class HookFileManager
+{
+       const STATIC_DIR = 'static';
+       const CONFIG_NAME = 'hooks';
+
+       /** @var ICanLoadAddons */
+       protected $addonLoader;
+       /** @var array */
+       protected $hookConfig = [];
+       /** @var string */
+       protected $basePath;
+
+       public function __construct(string $basePath, ICanLoadAddons $addonLoader)
+       {
+               $this->basePath    = $basePath;
+               $this->addonLoader = $addonLoader;
+       }
+
+       /**
+        * Loads all kinds of hooks and registers the corresponding instances
+        *
+        * @param ICanRegisterInstances $instanceRegister The instance register
+        *
+        * @return void
+        */
+       public function setupHooks(ICanRegisterInstances $instanceRegister)
+       {
+               // In case it wasn't used before, reload the whole hook config
+               if (empty($this->hookConfig)) {
+                       $this->reloadHookConfig();
+               }
+
+               foreach ($this->hookConfig as $hookType => $classList) {
+                       switch ($hookType) {
+                               case HookType::STRATEGY:
+                                       foreach ($classList as $interface => $strategy) {
+                                               foreach ($strategy as $dependencyName => $names) {
+                                                       if (is_array($names)) {
+                                                               foreach ($names as $name) {
+                                                                       $instanceRegister->registerStrategy($interface, $dependencyName, $name);
+                                                               }
+                                                       } else {
+                                                               $instanceRegister->registerStrategy($interface, $dependencyName, $names);
+                                                       }
+                                               }
+                                       }
+                                       break;
+                               case HookType::DECORATOR:
+                                       foreach ($classList as $interface => $decorators) {
+                                               if (is_array($decorators)) {
+                                                       foreach ($decorators as $decorator) {
+                                                               $instanceRegister->registerDecorator($interface, $decorator);
+                                                       }
+                                               } else {
+                                                       $instanceRegister->registerDecorator($interface, $decorators);
+                                               }
+                                       }
+                                       break;
+                       }
+               }
+       }
+
+       /**
+        * Reloads all hook config files into the config cache for later usage
+        *
+        * Merges all hook configs from every addon - if present - as well
+        *
+        * @return void
+        */
+       protected function reloadHookConfig()
+       {
+               // load core hook config
+               $configFile = $this->basePath . '/' . static::STATIC_DIR . '/' . static::CONFIG_NAME . '.config.php';
+
+               if (!file_exists($configFile)) {
+                       throw new HookConfigException(sprintf('config file %s does not exit.', $configFile));
+               }
+
+               $config = include $configFile;
+
+               if (!is_array($config)) {
+                       throw new HookConfigException('Error loading config file ' . $configFile);
+               }
+
+               $this->hookConfig = array_merge_recursive($config, $this->addonLoader->getActiveAddonConfig(static::CONFIG_NAME));
+       }
+}
diff --git a/src/Core/Logger/Capabilities/ICheckLoggerSettings.php b/src/Core/Logger/Capabilities/ICheckLoggerSettings.php
new file mode 100644 (file)
index 0000000..532425e
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2023, the Friendica project
+ *
+ * @license   GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Logger\Capabilities;
+
+/**
+ * Whenever a logging specific check is necessary, use this interface to encapsulate and centralize this logic
+ */
+interface ICheckLoggerSettings
+{
+       /**
+        * Checks if the logfile is set and usable
+        *
+        * @return string|null null in case everything is ok, otherwise returns the error
+        */
+       public function checkLogfile(): ?string;
+
+       /**
+        * Checks if the debugging logfile is usable in case it is set!
+        *
+        * @return string|null null in case everything is ok, otherwise returns the error
+        */
+       public function checkDebugLogfile(): ?string;
+}
index 83d75f976f82fcefec69476aab9dea4c2707ad5c..7f884bf64765f5219146852914ab4c18a997cb86 100644 (file)
@@ -2,7 +2,7 @@
 /**
  * @copyright Copyright (C) 2010-2023, the Friendica project
  *
- * @license GNU AGPL version 3 or any later version
+ * @license   GNU AGPL version 3 or any later version
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
diff --git a/src/Core/Logger/Capabilities/LogChannel.php b/src/Core/Logger/Capabilities/LogChannel.php
new file mode 100644 (file)
index 0000000..54ae032
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2023, the Friendica project
+ *
+ * @license   GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Logger\Capabilities;
+
+/**
+ * An enum class for the Log channels
+ */
+interface LogChannel
+{
+       /** @var string channel for the auth_ejabbered script */
+       public const AUTH_JABBERED = 'auth_ejabberd';
+       /** @var string Default channel in case it isn't set explicit */
+       public const DEFAULT       = self::APP;
+       /** @var string channel for console execution */
+       public const CONSOLE = 'console';
+       /** @var string channel for developer focused logging */
+       public const DEV = 'dev';
+       /** @var string channel for daemon executions */
+       public const DAEMON = 'daemon';
+       /** @var string channel for worker execution */
+       public const WORKER = 'worker';
+       /** @var string channel for frontend app executions */
+       public const APP = 'app';
+}
index 36b2c31cf3631391e1fe19d72c48e5cc710ef26d..39b2d17a94aeec96b81ad9f8f439468c35940bc8 100644 (file)
@@ -2,7 +2,7 @@
 /**
  * @copyright Copyright (C) 2010-2023, the Friendica project
  *
- * @license GNU AGPL version 3 or any later version
+ * @license   GNU AGPL version 3 or any later version
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -23,6 +23,9 @@ namespace Friendica\Core\Logger\Exception;
 
 use Throwable;
 
+/**
+ * Exception in case the loglevel isn't set or isn't valid
+ */
 class LogLevelException extends \InvalidArgumentException
 {
        public function __construct($message = "", Throwable $previous = null)
index a0b9949b086e6e493fc1e63352f4f7f9c39731a9..08eabe84a7787c62613d51cfa1584d1cd81ecb08 100644 (file)
@@ -2,7 +2,7 @@
 /**
  * @copyright Copyright (C) 2010-2023, the Friendica project
  *
- * @license GNU AGPL version 3 or any later version
+ * @license   GNU AGPL version 3 or any later version
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -23,6 +23,9 @@ namespace Friendica\Core\Logger\Exception;
 
 use Throwable;
 
+/**
+ * Exception in case an argument of a logger class isn't valid
+ */
 class LoggerArgumentException extends \InvalidArgumentException
 {
        public function __construct($message = "", Throwable $previous = null)
index 7e3637327ab5d43c78220fa4d3dd5321baaa73e1..13bcff8f3ce369b9958cf0870217eb810aefdb4d 100644 (file)
@@ -2,7 +2,7 @@
 /**
  * @copyright Copyright (C) 2010-2023, the Friendica project
  *
- * @license GNU AGPL version 3 or any later version
+ * @license   GNU AGPL version 3 or any later version
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -23,6 +23,9 @@ namespace Friendica\Core\Logger\Exception;
 
 use Throwable;
 
+/**
+ * A generic exception of the logging namespace
+ */
 class LoggerException extends \Exception
 {
        public function __construct($message = "", Throwable $previous = null)
diff --git a/src/Core/Logger/Exception/LoggerInvalidException.php b/src/Core/Logger/Exception/LoggerInvalidException.php
deleted file mode 100644 (file)
index db6ecb7..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2023, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Core\Logger\Exception;
-
-use Throwable;
-
-class LoggerInvalidException extends \RuntimeException
-{
-       public function __construct($message = "", Throwable $previous = null)
-       {
-               parent::__construct($message, 500, $previous);
-       }
-}
diff --git a/src/Core/Logger/Exception/LoggerUnusableException.php b/src/Core/Logger/Exception/LoggerUnusableException.php
new file mode 100644 (file)
index 0000000..29336e0
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2023, the Friendica project
+ *
+ * @license   GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Logger\Exception;
+
+use Throwable;
+
+/**
+ * Exception in case the used logging instance is unusable because of some circumstances
+ */
+class LoggerUnusableException extends \RuntimeException
+{
+       public function __construct($message = "", Throwable $previous = null)
+       {
+               parent::__construct($message, 500, $previous);
+       }
+}
diff --git a/src/Core/Logger/Factory/AbstractLoggerTypeFactory.php b/src/Core/Logger/Factory/AbstractLoggerTypeFactory.php
new file mode 100644 (file)
index 0000000..a6ff5ee
--- /dev/null
@@ -0,0 +1,80 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2023, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Logger\Factory;
+
+use Friendica\Core\Logger\Capabilities\IHaveCallIntrospections;
+use Psr\Log\LogLevel;
+
+/**
+ * Abstract class for creating logger types, which includes common necessary logic/content
+ */
+abstract class AbstractLoggerTypeFactory
+{
+       /** @var string */
+       protected $channel;
+       /** @var IHaveCallIntrospections */
+       protected $introspection;
+
+       /**
+        * @param string $channel The channel for the logger
+        */
+       public function __construct(IHaveCallIntrospections $introspection, string $channel)
+       {
+               $this->channel       = $channel;
+               $this->introspection = $introspection;
+       }
+
+       /**
+        * Mapping a legacy level to the PSR-3 compliant levels
+        *
+        * @see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md#5-psrlogloglevel
+        *
+        * @param string $level the level to be mapped
+        *
+        * @return string the PSR-3 compliant level
+        */
+       protected static function mapLegacyConfigDebugLevel(string $level): string
+       {
+               switch ($level) {
+                       // legacy WARNING
+                       case "0":
+                               return LogLevel::ERROR;
+                       // legacy INFO
+                       case "1":
+                               return LogLevel::WARNING;
+                       // legacy TRACE
+                       case "2":
+                               return LogLevel::NOTICE;
+                       // legacy DEBUG
+                       case "3":
+                               return LogLevel::INFO;
+                       // legacy DATA
+                       case "4":
+                               // legacy ALL
+                       case "5":
+                               return LogLevel::DEBUG;
+                       // default if nothing set
+                       default:
+                               return $level;
+               }
+       }
+}
index 2821a813c2681c9a786fe3695e3041603182f1dc..3fde878a34d086202995adc5984506e2714635c8 100644 (file)
 namespace Friendica\Core\Logger\Factory;
 
 use Friendica\Core\Config\Capability\IManageConfigValues;
-use Friendica\Core\Hooks\Capabilities\ICanManageInstances;
-use Friendica\Core\Logger\Exception\LogLevelException;
-use Friendica\Core\Logger\Type\ProfilerLogger;
-use Friendica\Core\Logger\Type\StreamLogger;
-use Friendica\Core\Logger\Type\SyslogLogger;
+use Friendica\Core\Hooks\Capabilities\ICanCreateInstances;
+use Friendica\Core\Logger\Capabilities\LogChannel;
 use Psr\Log\LoggerInterface;
-use Psr\Log\LogLevel;
 use Psr\Log\NullLogger;
+use Throwable;
 
 /**
- * A logger factory
+ * The logger factory for the core logging instances
  */
 class Logger
 {
-       const DEV_CHANNEL = 'dev';
-
-       /** @var string The log-channel (app, worker, ...) */
+       /** @var string The channel */
        protected $channel;
-       /** @var ICanManageInstances */
-       protected $instanceManager;
-       /** @var IManageConfigValues */
-       protected $config;
 
-       public function __construct(string $channel, ICanManageInstances $instanceManager, IManageConfigValues $config, string $logfile = null)
+       public function __construct(string $channel = LogChannel::DEFAULT)
        {
-               $this->channel         = $channel;
-               $this->instanceManager = $instanceManager;
-               $this->config          = $config;
-
-               $this->instanceManager
-                       ->registerStrategy(LoggerInterface::class, 'syslog', SyslogLogger::class)
-                       ->registerStrategy(LoggerInterface::class, 'stream', StreamLogger::class, isset($logfile) ? [$logfile] : null);
-
-               if ($this->config->get('system', 'profiling') ?? false) {
-                       $this->instanceManager->registerDecorator(LoggerInterface::class, ProfilerLogger::class);
-               }
+               $this->channel = $channel;
        }
 
-       /**
-        * Creates a new PSR-3 compliant logger instances
-        *
-        * @param string|null $loglevel (optional) A given loglevel in case the loglevel in the config isn't applicable
-        *
-        * @return LoggerInterface The PSR-3 compliant logger instance
-        */
-       public function create(string $loglevel = null): LoggerInterface
+       public function create(ICanCreateInstances $createInstances, IManageConfigValues $config): LoggerInterface
        {
-               if (empty($this->config->get('system', 'debugging') ?? false)) {
+               if (empty($config->get('system', 'debugging') ?? false)) {
                        return new NullLogger();
                }
 
-               $loglevel = $loglevel ?? static::mapLegacyConfigDebugLevel($this->config->get('system', 'loglevel'));
-               $name     = $this->config->get('system', 'logger_config') ?? 'stream';
+               $name = $config->get('system', 'logger_config') ?? '';
 
                try {
-                       /** @var LoggerInterface */
-                       return $this->instanceManager->getInstance(LoggerInterface::class, $name, [$this->channel, $loglevel]);
-               } catch (LogLevelException $exception) {
-                       // If there's a wrong config value for loglevel, try again with standard
-                       $logger = $this->create(LogLevel::NOTICE);
-                       $logger->warning('Invalid loglevel set in config.', ['loglevel' => $loglevel]);
-                       return $logger;
-               } catch (\Throwable $e) {
+                       return $createInstances->createWithName(LoggerInterface::class, $name, [$this->channel]);
+               } catch (Throwable $e) {
                        // No logger ...
                        return new NullLogger();
                }
        }
-
-       /**
-        * Creates a new PSR-3 compliant develop logger
-        *
-        * If you want to debug only interactions from your IP or the IP of a remote server for federation debug,
-        * you'll use this logger instance for the duration of your work.
-        *
-        * It should never get filled during normal usage of Friendica
-        *
-        * @return LoggerInterface The PSR-3 compliant logger instance
-        * @throws \Exception
-        */
-       public function createDev()
-       {
-               $debugging   = $this->config->get('system', 'debugging');
-               $stream      = $this->config->get('system', 'dlogfile');
-               $developerIp = $this->config->get('system', 'dlogip');
-
-               if ((!isset($developerIp) || !$debugging) &&
-                       (!is_file($stream) || is_writable($stream))) {
-                       return new NullLogger();
-               }
-
-               $name = $this->config->get('system', 'logger_config') ?? 'stream';
-
-               /** @var LoggerInterface */
-               return $this->instanceManager->getInstance(LoggerInterface::class, $name, [self::DEV_CHANNEL, LogLevel::DEBUG, $stream]);
-       }
-
-       /**
-        * Mapping a legacy level to the PSR-3 compliant levels
-        *
-        * @see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md#5-psrlogloglevel
-        *
-        * @param string $level the level to be mapped
-        *
-        * @return string the PSR-3 compliant level
-        */
-       private static function mapLegacyConfigDebugLevel(string $level): string
-       {
-               switch ($level) {
-                       // legacy WARNING
-                       case "0":
-                               return LogLevel::ERROR;
-                       // legacy INFO
-                       case "1":
-                               return LogLevel::WARNING;
-                       // legacy TRACE
-                       case "2":
-                               return LogLevel::NOTICE;
-                       // legacy DEBUG
-                       case "3":
-                               return LogLevel::INFO;
-                       // legacy DATA
-                       case "4":
-                       // legacy ALL
-                       case "5":
-                               return LogLevel::DEBUG;
-                       // default if nothing set
-                       default:
-                               return $level;
-               }
-       }
 }
diff --git a/src/Core/Logger/Factory/ProfilerLogger.php b/src/Core/Logger/Factory/ProfilerLogger.php
new file mode 100644 (file)
index 0000000..3d12692
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2023, the Friendica project
+ *
+ * @license   GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Logger\Factory;
+
+use Friendica\Core\Config\Capability\IManageConfigValues;
+use Friendica\Core\Logger\Type\ProfilerLogger as ProfilerLoggerClass;
+use Friendica\Util\Profiler;
+use Psr\Log\LoggerInterface;
+
+/**
+ * The logger factory for the ProfilerLogger
+ *
+ * @see ProfilerLoggerClass
+ */
+class ProfilerLogger extends AbstractLoggerTypeFactory
+{
+       /**
+        * Wraps a given Logger with profiling information in case profiling is enabled
+        *
+        * @param IManageConfigValues $config   The system configuration
+        * @param LoggerInterface     $logger   The given logger class, which should get wrapped
+        * @param Profiler            $profiler The profiler utility
+        *
+        * @return LoggerInterface The PSR-3 compliant logger instance
+        */
+       public function create(IManageConfigValues $config, LoggerInterface $logger, Profiler $profiler): LoggerInterface
+       {
+               if ($config->get('system', 'profiling') ?? false) {
+                       return $logger;
+               } else {
+                       return new ProfilerLoggerClass($logger, $profiler);
+               }
+       }
+}
diff --git a/src/Core/Logger/Factory/StreamLogger.php b/src/Core/Logger/Factory/StreamLogger.php
new file mode 100644 (file)
index 0000000..85475b3
--- /dev/null
@@ -0,0 +1,100 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2023, the Friendica project
+ *
+ * @license   GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Logger\Factory;
+
+use Friendica\Core\Config\Capability\IManageConfigValues;
+use Friendica\Core\Logger\Capabilities\LogChannel;
+use Friendica\Core\Logger\Exception\LoggerArgumentException;
+use Friendica\Core\Logger\Exception\LoggerException;
+use Friendica\Core\Logger\Type\StreamLogger as StreamLoggerClass;
+use Friendica\Core\Logger\Util\FileSystem;
+use Psr\Log\LoggerInterface;
+use Psr\Log\LogLevel;
+use Psr\Log\NullLogger;
+
+/**
+ * The logger factory for the StreamLogger instance
+ *
+ * @see StreamLoggerClass
+ */
+class StreamLogger extends AbstractLoggerTypeFactory
+{
+       /**
+        * Creates a new PSR-3 compliant stream logger instance
+        *
+        * @param IManageConfigValues $config   The system configuration
+        * @param string|null         $logfile  (optional) A given logfile which should be used as stream (e.g. in case of
+        *                                      developer logging)
+        * @param string|null         $channel  (optional) A given channel in case it is different from the default
+        *
+        * @return LoggerInterface The PSR-3 compliant logger instance
+        *
+        * @throws LoggerException in case the logger cannot get created
+        */
+       public function create(IManageConfigValues $config, string $logfile = null, string $channel = null): LoggerInterface
+       {
+               $fileSystem = new FileSystem();
+
+               $logfile = $logfile ?? $config->get('system', 'logfile');
+               if ((@file_exists($logfile) && !@is_writable($logfile)) && !@is_writable(basename($logfile))) {
+                       throw new LoggerArgumentException(sprintf('%s is not a valid logfile', $logfile));
+               }
+
+               $loglevel = static::mapLegacyConfigDebugLevel($config->get('system', 'loglevel'));
+
+               if (array_key_exists($loglevel, StreamLoggerClass::levelToInt)) {
+                       $loglevel = StreamLoggerClass::levelToInt[$loglevel];
+               } else {
+                       $loglevel = StreamLoggerClass::levelToInt[LogLevel::NOTICE];
+               }
+
+               $stream = $fileSystem->createStream($logfile);
+
+               return new StreamLoggerClass($channel ?? $this->channel, $this->introspection, $stream, $loglevel, getmypid());
+       }
+
+       /**
+        * Creates a new PSR-3 compliant develop logger
+        *
+        * If you want to debug only interactions from your IP or the IP of a remote server for federation debug,
+        * you'll use this logger instance for the duration of your work.
+        *
+        * It should never get filled during normal usage of Friendica
+        *
+        * @return LoggerInterface The PSR-3 compliant logger instance
+        *
+        * @throws LoggerException
+        */
+       public function createDev(IManageConfigValues $config)
+       {
+               $debugging   = $config->get('system', 'debugging');
+               $logfile     = $config->get('system', 'dlogfile');
+               $developerIp = $config->get('system', 'dlogip');
+
+               if ((!isset($developerIp) || !$debugging) &&
+                       (!is_file($logfile) || is_writable($logfile))) {
+                       return new NullLogger();
+               }
+
+               return $this->create($config, $logfile, LogChannel::DEV);
+       }
+}
diff --git a/src/Core/Logger/Factory/SyslogLogger.php b/src/Core/Logger/Factory/SyslogLogger.php
new file mode 100644 (file)
index 0000000..5a87895
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2023, the Friendica project
+ *
+ * @license   GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Logger\Factory;
+
+use Friendica\Core\Config\Capability\IManageConfigValues;
+use Friendica\Core\Logger\Exception\LoggerException;
+use Friendica\Core\Logger\Type\SyslogLogger as SyslogLoggerClass;
+use Psr\Log\LoggerInterface;
+use Psr\Log\LogLevel;
+
+/**
+ * The logger factory for the SyslogLogger instance
+ *
+ * @see SyslogLoggerClass
+ */
+class SyslogLogger extends AbstractLoggerTypeFactory
+{
+       /**
+        * Creates a new PSR-3 compliant syslog logger instance
+        *
+        * @param IManageConfigValues $config   The system configuration
+        *
+        * @return LoggerInterface The PSR-3 compliant logger instance
+        *
+        * @throws LoggerException in case the logger cannot get created
+        */
+       public function create(IManageConfigValues $config): LoggerInterface
+       {
+               $logOpts     = $config->get('system', 'syslog_flags') ?? SyslogLoggerClass::DEFAULT_FLAGS;
+               $logFacility = $config->get('system', 'syslog_facility') ?? SyslogLoggerClass::DEFAULT_FACILITY;
+               $loglevel    = SyslogLogger::mapLegacyConfigDebugLevel($config->get('system', 'loglevel'));
+
+               if (!array_key_exists($loglevel, SyslogLoggerClass::logLevels)) {
+                       $loglevel = SyslogLoggerClass::logLevels[$loglevel];
+               } else {
+                       $loglevel = SyslogLoggerClass::logLevels[LogLevel::NOTICE];
+               }
+
+               return new SyslogLoggerClass($this->channel, $this->introspection, $loglevel, $logOpts, $logFacility);
+       }
+}
diff --git a/src/Core/Logger/Type/README.md b/src/Core/Logger/Type/README.md
deleted file mode 100644 (file)
index b204353..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-## Friendica\Util\Logger
-
-This namespace contains the different implementations of a Logger.
-
-### Configuration guideline
-
-The following settings are possible for `logger_config`:
--      [`stream`](StreamLogger.php): A small logger for files or streams
--      [`syslog`](SyslogLogger.php): Prints the logging output into the syslog
-
-[`VoidLogger`](VoidLogger.php) is a fallback logger without any function if no debugging is enabled.
-
-[`ProfilerLogger`](ProfilerLogger.php) is a wrapper around an existing logger in case profiling is enabled for Friendica.
-Every log call will be saved to the `Profiler` with a timestamp.
-
-### Implementation guideline
-
-Each logging implementation should pe capable of printing at least the following information:
--      An unique ID for each Request/Call
--      The process ID (PID)
--      A timestamp of the logging entry
--      The critically of the log entry
--      A log message
--      A context of the log message (f.e which user)
-
-If possible, a Logger should extend [`AbstractLogger`](AbstractLogger.php), because it contains additional, Friendica specific business logic for each logging call.
index d56f5b20ef6fd2b8fa001f20d9ab811597f1efea..87f1a3937f36d10263b25d5fa568adbd13c9ba2f 100644 (file)
 
 namespace Friendica\Core\Logger\Type;
 
-use Friendica\Core\Config\Capability\IManageConfigValues;
-use Friendica\Core\Hooks\Capabilities\IAmAStrategy;
 use Friendica\Core\Logger\Capabilities\IHaveCallIntrospections;
-use Friendica\Core\Logger\Exception\LoggerArgumentException;
 use Friendica\Core\Logger\Exception\LoggerException;
 use Friendica\Core\Logger\Exception\LogLevelException;
 use Friendica\Util\DateTimeFormat;
-use Friendica\Util\FileSystem;
 use Psr\Log\LogLevel;
 
 /**
  * A Logger instance for logging into a stream (file, stdout, stderr)
  */
-class StreamLogger extends AbstractLogger implements IAmAStrategy
+class StreamLogger extends AbstractLogger
 {
        /**
         * The minimum loglevel at which this logger will be triggered
@@ -42,12 +38,6 @@ class StreamLogger extends AbstractLogger implements IAmAStrategy
         */
        private $logLevel;
 
-       /**
-        * The file URL of the stream (if needed)
-        * @var string
-        */
-       private $url;
-
        /**
         * The stream, where the current logger is writing into
         * @var resource
@@ -60,16 +50,11 @@ class StreamLogger extends AbstractLogger implements IAmAStrategy
         */
        private $pid;
 
-       /**
-        * @var FileSystem
-        */
-       private $fileSystem;
-
        /**
         * Translates LogLevel log levels to integer values
         * @var array
         */
-       private $levelToInt = [
+       public const levelToInt = [
                LogLevel::EMERGENCY => 0,
                LogLevel::ALERT     => 1,
                LogLevel::CRITICAL  => 2,
@@ -84,41 +69,20 @@ class StreamLogger extends AbstractLogger implements IAmAStrategy
         * {@inheritdoc}
         * @param string          $level  The minimum loglevel at which this logger will be triggered
         *
-        * @throws LoggerArgumentException
-        * @throws LogLevelException
+        * @throws LoggerException
         */
-       public function __construct(string $channel, IManageConfigValues $config, IHaveCallIntrospections $introspection, FileSystem $fileSystem, string $level = LogLevel::DEBUG)
+       public function __construct(string $channel, IHaveCallIntrospections $introspection, $stream, int $logLevel, int $pid)
        {
-               $this->fileSystem = $fileSystem;
-
-               $stream = $this->logfile ?? $config->get('system', 'logfile');
-               if ((@file_exists($stream) && !@is_writable($stream)) && !@is_writable(basename($stream))) {
-                       throw new LoggerArgumentException(sprintf('%s is not a valid logfile', $stream));
-               }
-
                parent::__construct($channel, $introspection);
 
-               if (is_resource($stream)) {
-                       $this->stream = $stream;
-               } elseif (is_string($stream)) {
-                       $this->url = $stream;
-               } else {
-                       throw new LoggerArgumentException('A stream must either be a resource or a string.');
-               }
-
-               $this->pid = getmypid();
-               if (array_key_exists($level, $this->levelToInt)) {
-                       $this->logLevel = $this->levelToInt[$level];
-               } else {
-                       throw new LogLevelException(sprintf('The level "%s" is not valid.', $level));
-               }
-
-               $this->checkStream();
+               $this->stream   = $stream;
+               $this->pid      = $pid;
+               $this->logLevel = $logLevel;
        }
 
        public function close()
        {
-               if ($this->url && is_resource($this->stream)) {
+               if (is_resource($this->stream)) {
                        fclose($this->stream);
                }
 
@@ -139,18 +103,16 @@ class StreamLogger extends AbstractLogger implements IAmAStrategy
         */
        protected function addEntry($level, string $message, array $context = [])
        {
-               if (!array_key_exists($level, $this->levelToInt)) {
+               if (!array_key_exists($level, static::levelToInt)) {
                        throw new LogLevelException(sprintf('The level "%s" is not valid.', $level));
                }
 
-               $logLevel = $this->levelToInt[$level];
+               $logLevel = static::levelToInt[$level];
 
                if ($logLevel > $this->logLevel) {
                        return;
                }
 
-               $this->checkStream();
-
                $formattedLog = $this->formatLog($level, $message, $context);
                fwrite($this->stream, $formattedLog);
        }
@@ -185,27 +147,4 @@ class StreamLogger extends AbstractLogger implements IAmAStrategy
 
                return $logMessage;
        }
-
-       /**
-        * Checks the current stream
-        *
-        * @throws LoggerException
-        * @throws LoggerArgumentException
-        */
-       private function checkStream()
-       {
-               if (is_resource($this->stream)) {
-                       return;
-               }
-
-               if (empty($this->url)) {
-                       throw new LoggerArgumentException('Missing stream URL.');
-               }
-
-               try {
-                       $this->stream = $this->fileSystem->createStream($this->url);
-               } catch (\UnexpectedValueException $exception) {
-                       throw new LoggerException('Cannot create stream.', $exception);
-               }
-       }
 }
index 3c9ab581a0f9dfb026ac0ed67b8cfa3e8fc5ccd2..88dc1964ddb729f5d9c4a52a252df2d65b51d3e9 100644 (file)
@@ -21,8 +21,6 @@
 
 namespace Friendica\Core\Logger\Type;
 
-use Friendica\Core\Config\Capability\IManageConfigValues;
-use Friendica\Core\Hooks\Capabilities\IAmAStrategy;
 use Friendica\Core\Logger\Capabilities\IHaveCallIntrospections;
 use Friendica\Core\Logger\Exception\LoggerException;
 use Friendica\Core\Logger\Exception\LogLevelException;
@@ -32,7 +30,7 @@ use Psr\Log\LogLevel;
  * A Logger instance for syslogging (fast, but simple)
  * @see http://php.net/manual/en/function.syslog.php
  */
-class SyslogLogger extends AbstractLogger implements IAmAStrategy
+class SyslogLogger extends AbstractLogger
 {
        const IDENT = 'Friendica';
 
@@ -45,7 +43,7 @@ class SyslogLogger extends AbstractLogger implements IAmAStrategy
         * Translates LogLevel log levels to syslog log priorities.
         * @var array
         */
-       private $logLevels = [
+       public const logLevels = [
                LogLevel::DEBUG     => LOG_DEBUG,
                LogLevel::INFO      => LOG_INFO,
                LogLevel::NOTICE    => LOG_NOTICE,
@@ -60,7 +58,7 @@ class SyslogLogger extends AbstractLogger implements IAmAStrategy
         * Translates log priorities to string outputs
         * @var array
         */
-       private $logToString = [
+       protected const logToString = [
                LOG_DEBUG   => 'DEBUG',
                LOG_INFO    => 'INFO',
                LOG_NOTICE  => 'NOTICE',
@@ -101,19 +99,18 @@ class SyslogLogger extends AbstractLogger implements IAmAStrategy
 
        /**
         * {@inheritdoc}
-        * @param string $level       The minimum loglevel at which this logger will be triggered
         *
-        * @throws LogLevelException
-        * @throws LoggerException
+        * @param string $logLevel    The minimum loglevel at which this logger will be triggered
+        * @param string $logOptions
+        * @param string $logFacility
         */
-       public function __construct(string $channel, IManageConfigValues $config, IHaveCallIntrospections $introspection, string $level = LogLevel::NOTICE)
+       public function __construct(string $channel, IHaveCallIntrospections $introspection, string $logLevel, string $logOptions, string $logFacility)
        {
                parent::__construct($channel, $introspection);
 
-               $this->logOpts     = $config->get('system', 'syslog_flags') ?? static::DEFAULT_FLAGS;
-               $this->logFacility = $config->get('system', 'syslog_facility') ?? static::DEFAULT_FACILITY;
-               $this->logLevel    = $this->mapLevelToPriority($level);
-               $this->introspection->addClasses([self::class]);
+               $this->logOpts     = $logOptions;
+               $this->logFacility = $logFacility;
+               $this->logLevel    = $logLevel;
        }
 
        /**
@@ -149,11 +146,11 @@ class SyslogLogger extends AbstractLogger implements IAmAStrategy
         */
        public function mapLevelToPriority(string $level): int
        {
-               if (!array_key_exists($level, $this->logLevels)) {
+               if (!array_key_exists($level, static::logLevels)) {
                        throw new LogLevelException(sprintf('The level "%s" is not valid.', $level));
                }
 
-               return $this->logLevels[$level];
+               return static::logLevels[$level];
        }
 
        /**
@@ -202,7 +199,7 @@ class SyslogLogger extends AbstractLogger implements IAmAStrategy
                $record = array_merge($record, ['uid' => $this->logUid]);
 
                $logMessage = $this->channel . ' ';
-               $logMessage .= '[' . $this->logToString[$level] . ']: ';
+               $logMessage .= '[' . static::logToString[$level] . ']: ';
                $logMessage .= $this->psrInterpolate($message, $context) . ' ';
                $logMessage .= $this->jsonEncodeArray($context) . ' - ';
                $logMessage .= $this->jsonEncodeArray($record);
diff --git a/src/Core/Logger/Util/FileSystem.php b/src/Core/Logger/Util/FileSystem.php
new file mode 100644 (file)
index 0000000..3793ac4
--- /dev/null
@@ -0,0 +1,102 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2023, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Logger\Util;
+
+/**
+ * Util class for filesystem manipulation for Logger classes
+ */
+class FileSystem
+{
+       /**
+        * @var string a error message
+        */
+       private $errorMessage;
+
+       /**
+        * Creates a directory based on a file, which gets accessed
+        *
+        * @param string $file The file
+        *
+        * @return string The directory name (empty if no directory is found, like urls)
+        */
+       public function createDir(string $file): string
+       {
+               $dirname = null;
+               $pos = strpos($file, '://');
+
+               if (!$pos) {
+                       $dirname = realpath(dirname($file));
+               }
+
+               if (substr($file, 0, 7) === 'file://') {
+                       $dirname = realpath(dirname(substr($file, 7)));
+               }
+
+               if (isset($dirname) && !is_dir($dirname)) {
+                       set_error_handler([$this, 'customErrorHandler']);
+                       $status = mkdir($dirname, 0777, true);
+                       restore_error_handler();
+
+                       if (!$status && !is_dir($dirname)) {
+                               throw new \UnexpectedValueException(sprintf('Directory "%s" cannot get created: ' . $this->errorMessage, $dirname));
+                       }
+
+                       return $dirname;
+               } elseif (isset($dirname) && is_dir($dirname)) {
+                       return $dirname;
+               } else {
+                       return '';
+               }
+       }
+
+       /**
+        * Creates a stream based on a URL (could be a local file or a real URL)
+        *
+        * @param string $url The file/url
+        *
+        * @return resource the open stream resource
+        *
+        * @throws \UnexpectedValueException
+        */
+       public function createStream(string $url)
+       {
+               $directory = $this->createDir($url);
+               set_error_handler([$this, 'customErrorHandler']);
+               if (!empty($directory)) {
+                       $url = $directory . DIRECTORY_SEPARATOR . pathinfo($url, PATHINFO_BASENAME);
+               }
+
+               $stream = fopen($url, 'ab');
+               restore_error_handler();
+
+               if (!is_resource($stream)) {
+                       throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened: ' . $this->errorMessage, $url));
+               }
+
+               return $stream;
+       }
+
+       private function customErrorHandler($code, $msg)
+       {
+               $this->errorMessage = preg_replace('{^(fopen|mkdir)\(.*?\): }', '', $msg);
+       }
+}
diff --git a/src/Core/Logger/Util/LoggerSettingsCheck.php b/src/Core/Logger/Util/LoggerSettingsCheck.php
new file mode 100644 (file)
index 0000000..7782216
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2023, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Logger\Util;
+
+use Friendica\Core\Config\Capability\IManageConfigValues;
+use Friendica\Core\L10n;
+use Friendica\Core\Logger\Capabilities\ICheckLoggerSettings;
+use Friendica\Core\Logger\Exception\LoggerUnusableException;
+
+/** {@inheritDoc} */
+class LoggerSettingsCheck implements ICheckLoggerSettings
+{
+       /** @var IManageConfigValues */
+       protected $config;
+       /** @var $fileSystem */
+       protected $fileSystem;
+       /** @var L10n */
+       protected $l10n;
+
+       public function __construct(IManageConfigValues $config, FileSystem $fileSystem, L10n $l10n)
+       {
+               $this->config     = $config;
+               $this->fileSystem = $fileSystem;
+               $this->l10n       = $l10n;
+       }
+
+       /** {@inheritDoc} */
+       public function checkLogfile(): ?string
+       {
+               // Check logfile permission
+               if ($this->config->get('system', 'debugging')) {
+                       $file = $this->config->get('system', 'logfile');
+
+                       try {
+                               $stream = $this->fileSystem->createStream($file);
+
+                               if (!isset($stream)) {
+                                       throw new LoggerUnusableException('Stream is null.');
+                               }
+                       } catch (\Throwable $exception) {
+                               return $this->l10n->t('The logfile \'%s\' is not usable. No logging possible (error: \'%s\')', $file, $exception->getMessage());
+                       }
+               }
+
+               return null;
+       }
+
+       /** {@inheritDoc} */
+       public function checkDebugLogfile(): ?string
+       {
+               // Check logfile permission
+               if ($this->config->get('system', 'debugging')) {
+                       $file = $this->config->get('system', 'dlogfile');
+
+                       if (empty($file)) {
+                               return null;
+                       }
+
+                       try {
+                               $stream = $this->fileSystem->createStream($file);
+
+                               if (!isset($stream)) {
+                                       throw new LoggerUnusableException('Stream is null.');
+                               }
+                       } catch (\Throwable $exception) {
+                               return $this->l10n->t('The debug logfile \'%s\' is not usable. No logging possible (error: \'%s\')', $file, $exception->getMessage());
+                       }
+               }
+
+               return null;
+       }
+}
index 8d706ed374a1ab3eb80b34280b983dcf0805dfa5..ad8745622fd07ec07eab552a20a4a18b3224084a 100644 (file)
 namespace Friendica;
 
 use Dice\Dice;
-use Friendica\Core\Session\Capability\IHandleSessions;
-use Friendica\Core\Session\Capability\IHandleUserSessions;
-use Friendica\Navigation\SystemMessages;
-use Psr\Log\LoggerInterface;
+use \Friendica\Core\Logger\Capabilities\ICheckLoggerSettings;
+use \Friendica\Core\Logger\Util\LoggerSettingsCheck;
+use \Friendica\Core\Session\Capability\IHandleSessions;
+use \Friendica\Core\Session\Capability\IHandleUserSessions;
+use \Friendica\Navigation\SystemMessages;
+use \Psr\Log\LoggerInterface;
 
 /**
  * This class is capable of getting all dynamic created classes
@@ -295,6 +297,11 @@ abstract class DI
                static::init($flushDice);
        }
 
+       public static function loggCheck(): ICheckLoggerSettings
+       {
+               return self::$dice->create(LoggerSettingsCheck::class);
+       }
+
        /**
         * @return LoggerInterface
         */
@@ -692,14 +699,6 @@ abstract class DI
                return self::$dice->create(Util\DateTimeFormat::class);
        }
 
-       /**
-        * @return Util\FileSystem
-        */
-       public static function fs()
-       {
-               return self::$dice->create(Util\FileSystem::class);
-       }
-
        /**
         * @return Util\Profiler
         */
index d872f4825957e81d4d7e9bf1a5946d1a9945d158..80437305dccd2e1124193d09ee9ec65b75d55b47 100644 (file)
@@ -79,7 +79,7 @@ class Summary extends BaseAdmin
                // Check if github.com/friendica/stable/VERSION is higher then
                // the local version of Friendica. Check is opt-in, source may be stable or develop branch
                if (DI::config()->get('system', 'check_new_version_url', 'none') != 'none') {
-                       $gitversion = DI::keyValue()->get('git_friendica_version') ?? ''; 
+                       $gitversion = DI::keyValue()->get('git_friendica_version') ?? '';
 
                        if (version_compare(App::VERSION, $gitversion) < 0) {
                                $warningtext[] = DI::l10n()->t('There is a new version of Friendica available for download. Your current version is %1$s, upstream version is %2$s', App::VERSION, $gitversion);
@@ -126,35 +126,11 @@ class Summary extends BaseAdmin
                }
 
                // Check logfile permission
-               if (DI::config()->get('system', 'debugging')) {
-                       $file = DI::config()->get('system', 'logfile');
-
-                       $fileSystem = DI::fs();
-
-                       try {
-                               $stream = $fileSystem->createStream($file);
-
-                               if (!isset($stream)) {
-                                       throw new ServiceUnavailableException('Stream is null.');
-                               }
-
-                       } catch (\Throwable $exception) {
-                               $warningtext[] = DI::l10n()->t('The logfile \'%s\' is not usable. No logging possible (error: \'%s\')', $file, $exception->getMessage());
-                       }
-
-                       $file = DI::config()->get('system', 'dlogfile');
-
-                       try {
-                               if (!empty($file)) {
-                                       $stream = $fileSystem->createStream($file);
-
-                                       if (!isset($stream)) {
-                                               throw new ServiceUnavailableException('Stream is null.');
-                                       }
-                               }
-                       } catch (\Throwable $exception) {
-                               $warningtext[] = DI::l10n()->t('The debug logfile \'%s\' is not usable. No logging possible (error: \'%s\')', $file, $exception->getMessage());
-                       }
+               if (($return = DI::loggCheck()->checkLogfile()) !== null) {
+                       $warningtext[] = $return;
+               }
+               if (($return = DI::loggCheck()->checkDebugLogfile()) !== null) {
+                       $warningtext[] = $return;
                }
 
                // check legacy basepath settings
diff --git a/src/Util/FileSystem.php b/src/Util/FileSystem.php
deleted file mode 100644 (file)
index a21e7fb..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2023, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Util;
-
-/**
- * Util class for filesystem manipulation
- */
-class FileSystem
-{
-       /**
-        * @var string a error message
-        */
-       private $errorMessage;
-
-       /**
-        * Creates a directory based on a file, which gets accessed
-        *
-        * @param string $file The file
-        *
-        * @return string The directory name (empty if no directory is found, like urls)
-        */
-       public function createDir(string $file)
-       {
-               $dirname = null;
-               $pos = strpos($file, '://');
-
-               if (!$pos) {
-                       $dirname = realpath(dirname($file));
-               }
-
-               if (substr($file, 0, 7) === 'file://') {
-                       $dirname = realpath(dirname(substr($file, 7)));
-               }
-
-               if (isset($dirname) && !is_dir($dirname)) {
-                       set_error_handler([$this, 'customErrorHandler']);
-                       $status = mkdir($dirname, 0777, true);
-                       restore_error_handler();
-
-                       if (!$status && !is_dir($dirname)) {
-                               throw new \UnexpectedValueException(sprintf('Directory "%s" cannot get created: ' . $this->errorMessage, $dirname));
-                       }
-
-                       return $dirname;
-               } elseif (isset($dirname) && is_dir($dirname)) {
-                       return $dirname;
-               } else {
-                       return '';
-               }
-       }
-
-       /**
-        * Creates a stream based on a URL (could be a local file or a real URL)
-        *
-        * @param string $url The file/url
-        *
-        * @return resource the open stream resource
-        *
-        * @throws \UnexpectedValueException
-        */
-       public function createStream(string $url)
-       {
-               $directory = $this->createDir($url);
-               set_error_handler([$this, 'customErrorHandler']);
-               if (!empty($directory)) {
-                       $url = $directory . DIRECTORY_SEPARATOR . pathinfo($url, PATHINFO_BASENAME);
-               }
-
-               $stream = fopen($url, 'ab');
-               restore_error_handler();
-
-               if (!is_resource($stream)) {
-                       throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened: ' . $this->errorMessage, $url));
-               }
-
-               return $stream;
-       }
-
-       private function customErrorHandler($code, $msg)
-       {
-               $this->errorMessage = preg_replace('{^(fopen|mkdir)\(.*?\): }', '', $msg);
-       }
-}
index 0891166424f8bd884a4cdb5f6192a0ab00b1b8c2..2b246f84529a7cc028bf61fec51bcfb8fc86b37c 100644 (file)
@@ -37,8 +37,9 @@ use Dice\Dice;
 use Friendica\App;
 use Friendica\Core\Cache;
 use Friendica\Core\Config;
-use Friendica\Core\Hooks\Capabilities\ICanManageInstances;
-use Friendica\Core\Hooks\Model\InstanceManager;
+use Friendica\Core\Hooks\Capabilities\ICanCreateInstances;
+use Friendica\Core\Hooks\Capabilities\ICanRegisterInstances;
+use Friendica\Core\Hooks\Model\DiceInstanceManager;
 use Friendica\Core\PConfig;
 use Friendica\Core\L10n;
 use Friendica\Core\Lock;
@@ -62,6 +63,13 @@ return [
                // one instance for the whole execution
                'shared' => true,
        ],
+       \Friendica\Core\Addon\Capabilities\ICanLoadAddons::class => [
+               'instanceOf' => \Friendica\Core\Addon\Model\AddonLoader::class,
+               'constructParams' => [
+                       [Dice::INSTANCE => '$basepath'],
+                       [Dice::INSTANCE => Dice::SELF],
+               ],
+       ],
        '$basepath'                     => [
                'instanceOf'      => Util\BasePath::class,
                'call'            => [
@@ -78,8 +86,24 @@ return [
                        $_SERVER
                ]
        ],
-       ICanManageInstances::class => [
-               'instanceOf' => InstanceManager::class,
+       DiceInstanceManager::class   => [
+               'constructParams' => [
+                       [Dice::INSTANCE => Dice::SELF],
+               ]
+       ],
+       \Friendica\Core\Hooks\Util\HookFileManager::class => [
+               'constructParams' => [
+                       [Dice::INSTANCE => '$basepath'],
+               ],
+       ],
+       ICanRegisterInstances::class => [
+               'instanceOf' => DiceInstanceManager::class,
+               'constructParams' => [
+                       [Dice::INSTANCE => Dice::SELF],
+               ],
+       ],
+       ICanCreateInstances::class   => [
+               'instanceOf' => DiceInstanceManager::class,
                'constructParams' => [
                        [Dice::INSTANCE => Dice::SELF],
                ],
@@ -156,40 +180,40 @@ return [
                        [Dice::INSTANCE => '$basepath'],
                ],
        ],
-       /**
-        * Create a Logger, which implements the LoggerInterface
-        *
-        * Same as:
-        *   $loggerFactory = new Factory\LoggerFactory();
-        *   $logger = $loggerFactory->create($channel, $configuration, $profiler);
-        *
-        * Attention1: We can use DICE for detecting dependencies inside "chained" calls too
-        * Attention2: The variable "$channel" is passed inside the creation of the dependencies per:
-        *    $app = $dice->create(App::class, [], ['$channel' => 'index']);
-        *    and is automatically passed as an argument with the same name
-        */
-       LoggerInterface::class          => [
+       \Psr\Log\LoggerInterface::class                                    => [
                'instanceOf' => \Friendica\Core\Logger\Factory\Logger::class,
-               'constructParams' => [
-                       'index',
+               'call'       => [
+                       ['create', [], Dice::CHAIN_CALL],
                ],
+       ],
+       \Friendica\Core\Logger\Type\SyslogLogger::class                    => [
+               'instanceOf' => \Friendica\Core\Logger\Factory\SyslogLogger::class,
                'call'       => [
                        ['create', [], Dice::CHAIN_CALL],
                ],
        ],
-       '$devLogger'                    => [
-               'instanceOf' => \Friendica\Core\Logger\Factory\Logger::class,
-               'constructParams' => [
-                       'dev',
+       \Friendica\Core\Logger\Type\StreamLogger::class                    => [
+               'instanceOf' => \Friendica\Core\Logger\Factory\StreamLogger::class,
+               'call'       => [
+                       ['create', [], Dice::CHAIN_CALL],
                ],
+       ],
+       \Friendica\Core\Logger\Type\ProfilerLogger::class                  => [
+               'instanceOf' => \Friendica\Core\Logger\Factory\ProfilerLogger::class,
                'call'       => [
-                       ['createDev', [], Dice::CHAIN_CALL],
-               ]
+                       ['create', [], Dice::CHAIN_CALL],
+               ],
        ],
        \Friendica\Core\Logger\Capabilities\IHaveCallIntrospections::class => [
-               'instanceOf' => \Friendica\Core\Logger\Util\Introspection::class,
+               'instanceOf'      => \Friendica\Core\Logger\Util\Introspection::class,
                'constructParams' => [
-                       \Friendica\Core\Logger\Util\Introspection::IGNORE_CLASS_LIST,
+                       \Friendica\Core\Logger\Capabilities\IHaveCallIntrospections::IGNORE_CLASS_LIST,
+               ],
+       ],
+       '$devLogger'                                                       => [
+               'instanceOf' => \Friendica\Core\Logger\Factory\StreamLogger::class,
+               'call'       => [
+                       ['createDev', [], Dice::CHAIN_CALL],
                ],
        ],
        Cache\Capability\ICanCache::class => [
diff --git a/static/hooks.config.php b/static/hooks.config.php
new file mode 100644 (file)
index 0000000..ca8863e
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2023, the Friendica project
+ *
+ * @license   GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+use Friendica\Core\Hooks\Capabilities\HookType as H;
+
+return [
+       H::STRATEGY  => [
+               \Psr\Log\LoggerInterface::class => [
+                       \Psr\Log\NullLogger::class                      => [''],
+                       \Friendica\Core\Logger\Type\SyslogLogger::class => ['syslog'],
+                       \Friendica\Core\Logger\Type\StreamLogger::class => ['stream'],
+               ],
+       ],
+       H::DECORATOR => [
+               \Psr\Log\LoggerInterface::class => [
+                       \Friendica\Core\Logger\Type\ProfilerLogger::class,
+               ],
+       ],
+];
index ff99002f7c77514ee2aeacf7c39ad6dcddb7ff38..9a0e9dd6faa35c07dcb500b6222e8790affc7151 100644 (file)
@@ -21,9 +21,7 @@
 
 namespace Friendica\Test\Util\Hooks\InstanceMocks;
 
-use Friendica\Core\Hooks\Capabilities\IAmAStrategy;
-
-class FakeInstance implements IAmADecoratedInterface, IAmAStrategy
+class FakeInstance
 {
        protected $aText = null;
        protected $cBool = null;
index 4e4c0135cbf3f26071f7c46568dca30ffc0ee109..200500d63e8b49b037ff09b7e09ab804a1f866a8 100644 (file)
@@ -22,7 +22,7 @@
 namespace Friendica\Test\src\Core\Hooks\Model;
 
 use Dice\Dice;
-use Friendica\Core\Hooks\Model\InstanceManager;
+use Friendica\Core\Hooks\Model\DiceInstanceManager;
 use Friendica\Test\MockedTest;
 use Friendica\Test\Util\Hooks\InstanceMocks\FakeInstance;
 use Friendica\Test\Util\Hooks\InstanceMocks\FakeInstanceDecorator;
@@ -32,12 +32,12 @@ class InstanceManagerTest extends MockedTest
 {
        public function testEqualButNotSameInstance()
        {
-               $instance = new InstanceManager(new Dice());
+               $instance = new DiceInstanceManager(new Dice());
 
                $instance->registerStrategy(IAmADecoratedInterface::class, 'fake', FakeInstance::class);
 
-               $getInstanceA = $instance->getInstance(IAmADecoratedInterface::class, 'fake');
-               $getInstanceB = $instance->getInstance(IAmADecoratedInterface::class, 'fake');
+               $getInstanceA = $instance->createWithName(IAmADecoratedInterface::class, 'fake');
+               $getInstanceB = $instance->createWithName(IAmADecoratedInterface::class, 'fake');
 
                self::assertEquals($getInstanceA, $getInstanceB);
                self::assertNotSame($getInstanceA, $getInstanceB);
@@ -81,7 +81,7 @@ class InstanceManagerTest extends MockedTest
         */
        public function testInstanceWithConstructorAnonymArgs(string $aString = null, bool $cBool = null, string $bString = null)
        {
-               $instance = new InstanceManager(new Dice());
+               $instance = new DiceInstanceManager(new Dice());
 
                $args = [];
 
@@ -98,9 +98,9 @@ class InstanceManagerTest extends MockedTest
                $instance->registerStrategy(IAmADecoratedInterface::class, 'fake', FakeInstance::class, $args);
 
                /** @var IAmADecoratedInterface $getInstanceA */
-               $getInstanceA = $instance->getInstance(IAmADecoratedInterface::class, 'fake');
+               $getInstanceA = $instance->createWithName(IAmADecoratedInterface::class, 'fake');
                /** @var IAmADecoratedInterface $getInstanceB */
-               $getInstanceB = $instance->getInstance(IAmADecoratedInterface::class, 'fake');
+               $getInstanceB = $instance->createWithName(IAmADecoratedInterface::class, 'fake');
 
                self::assertEquals($getInstanceA, $getInstanceB);
                self::assertNotSame($getInstanceA, $getInstanceB);
@@ -117,7 +117,7 @@ class InstanceManagerTest extends MockedTest
         */
        public function testInstanceConstructorAndGetInstanceWithNamedArgs(string $aString = null, bool $cBool = null, string $bString = null)
        {
-               $instance = new InstanceManager(new Dice());
+               $instance = new DiceInstanceManager(new Dice());
 
                $args = [];
 
@@ -131,9 +131,9 @@ class InstanceManagerTest extends MockedTest
                $instance->registerStrategy(IAmADecoratedInterface::class, 'fake', FakeInstance::class, $args);
 
                /** @var IAmADecoratedInterface $getInstanceA */
-               $getInstanceA = $instance->getInstance(IAmADecoratedInterface::class, 'fake', [$bString]);
+               $getInstanceA = $instance->createWithName(IAmADecoratedInterface::class, 'fake', [$bString]);
                /** @var IAmADecoratedInterface $getInstanceB */
-               $getInstanceB = $instance->getInstance(IAmADecoratedInterface::class, 'fake', [$bString]);
+               $getInstanceB = $instance->createWithName(IAmADecoratedInterface::class, 'fake', [$bString]);
 
                self::assertEquals($getInstanceA, $getInstanceB);
                self::assertNotSame($getInstanceA, $getInstanceB);
@@ -150,7 +150,7 @@ class InstanceManagerTest extends MockedTest
         */
        public function testInstanceWithTwoStrategies(string $aString = null, bool $cBool = null, string $bString = null)
        {
-               $instance = new InstanceManager(new Dice());
+               $instance = new DiceInstanceManager(new Dice());
 
                $args = [];
 
@@ -165,9 +165,9 @@ class InstanceManagerTest extends MockedTest
                $instance->registerStrategy(IAmADecoratedInterface::class, 'fake23', FakeInstance::class, $args);
 
                /** @var IAmADecoratedInterface $getInstanceA */
-               $getInstanceA = $instance->getInstance(IAmADecoratedInterface::class, 'fake', [$bString]);
+               $getInstanceA = $instance->createWithName(IAmADecoratedInterface::class, 'fake', [$bString]);
                /** @var IAmADecoratedInterface $getInstanceB */
-               $getInstanceB = $instance->getInstance(IAmADecoratedInterface::class, 'fake23', [$bString]);
+               $getInstanceB = $instance->createWithName(IAmADecoratedInterface::class, 'fake23', [$bString]);
 
                self::assertEquals($getInstanceA, $getInstanceB);
                self::assertNotSame($getInstanceA, $getInstanceB);
@@ -184,7 +184,7 @@ class InstanceManagerTest extends MockedTest
         */
        public function testDecorator(string $aString = null, bool $cBool = null, string $bString = null)
        {
-               $instance = new InstanceManager(new Dice());
+               $instance = new DiceInstanceManager(new Dice());
 
                $args = [];
 
@@ -202,9 +202,9 @@ class InstanceManagerTest extends MockedTest
                $instance->registerDecorator(IAmADecoratedInterface::class, FakeInstanceDecorator::class, [$prefix]);
 
                /** @var IAmADecoratedInterface $getInstanceA */
-               $getInstanceA = $instance->getInstance(IAmADecoratedInterface::class, 'fake', [$bString]);
+               $getInstanceA = $instance->createWithName(IAmADecoratedInterface::class, 'fake', [$bString]);
                /** @var IAmADecoratedInterface $getInstanceB */
-               $getInstanceB = $instance->getInstance(IAmADecoratedInterface::class, 'fake23', [$bString]);
+               $getInstanceB = $instance->createWithName(IAmADecoratedInterface::class, 'fake23', [$bString]);
 
                self::assertEquals(2, FakeInstanceDecorator::$countInstance);
                self::assertEquals($getInstanceA, $getInstanceB);
@@ -222,7 +222,7 @@ class InstanceManagerTest extends MockedTest
         */
        public function testTwoDecoratorWithPrefix(string $aString = null, bool $cBool = null, string $bString = null)
        {
-               $instance = new InstanceManager(new Dice());
+               $instance = new DiceInstanceManager(new Dice());
 
                $args = [];
 
@@ -241,9 +241,9 @@ class InstanceManagerTest extends MockedTest
                $instance->registerDecorator(IAmADecoratedInterface::class, FakeInstanceDecorator::class);
 
                /** @var IAmADecoratedInterface $getInstanceA */
-               $getInstanceA = $instance->getInstance(IAmADecoratedInterface::class, 'fake', [$bString]);
+               $getInstanceA = $instance->createWithName(IAmADecoratedInterface::class, 'fake', [$bString]);
                /** @var IAmADecoratedInterface $getInstanceB */
-               $getInstanceB = $instance->getInstance(IAmADecoratedInterface::class, 'fake23', [$bString]);
+               $getInstanceB = $instance->createWithName(IAmADecoratedInterface::class, 'fake23', [$bString]);
 
                self::assertEquals(4, FakeInstanceDecorator::$countInstance);
                self::assertEquals($getInstanceA, $getInstanceB);
index 1ddddf4c1b63d015f109c36503d8d56836978ba8..c8fac4939d13b7c93b3396006f4f5a7ababdb3c4 100644 (file)
@@ -24,7 +24,7 @@ namespace Friendica\Test\src\Core\Logger;
 use Friendica\Core\Logger\Exception\LoggerArgumentException;
 use Friendica\Core\Logger\Exception\LoggerException;
 use Friendica\Core\Logger\Exception\LogLevelException;
-use Friendica\Util\FileSystem;
+use Friendica\Core\Logger\Util\FileSystem;
 use Friendica\Test\Util\VFSTrait;
 use Friendica\Core\Logger\Type\StreamLogger;
 use org\bovigo\vfs\vfsStream;
@@ -41,7 +41,7 @@ class StreamLoggerTest extends AbstractLoggerTest
        private $logfile;
 
        /**
-        * @var Filesystem
+        * @var \Friendica\Core\Logger\Util\Filesystem
         */
        private $fileSystem;