Merge pull request #13298 from nupplaphil/feat/strategies

[Hook] Introduce some more strategies
This commit is contained in:
Hypolite Petovan 2023-07-28 19:50:37 +02:00 committed by GitHub
commit 4073400bfb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
66 changed files with 261 additions and 254 deletions

View File

@ -1,4 +1,4 @@
pipeline:
steps:
restore_cache:
image: meltwater/drone-cache:dev
settings:

View File

@ -11,7 +11,7 @@ labels:
skip_clone: true
pipeline:
steps:
clone:
image: alpine/git
commands:

View File

@ -6,7 +6,11 @@ matrix:
branches:
exclude: [ stable ]
pipeline:
# This forces CI executions at the "opensocial" labeled location (because of much more power...)
labels:
location: opensocial
steps:
db_version_match:
image: friendicaci/transifex
commands:

View File

@ -1,4 +1,4 @@
pipeline:
steps:
check:
image: friendicaci/php-cs
commands:

View File

@ -1,4 +1,4 @@
pipeline:
steps:
build_xgettext:
image: friendicaci/transifex
commands:
@ -9,4 +9,4 @@ pipeline:
- /check-messages.sh
branches:
exclude: [ stable ]
exclude: [ stable ]

View File

@ -15,12 +15,12 @@ matrix:
labels:
location: opensocial
pipeline:
steps:
php-lint:
image: php:${PHP_MAJOR_VERSION}
group: lint
commands:
- ./bin/composer.phar run lint
- find . -name \*.php -not -path './vendor/*' -not -path './view/asset/*' -print0 | xargs -0 -n1 php -l
restore_cache:
image: meltwater/drone-cache:dev
settings:

View File

@ -9,7 +9,7 @@ labels:
skip_clone: true
pipeline:
steps:
clone:
image: alpine/git
commands:

View File

@ -58,7 +58,7 @@ if (php_sapi_name() !== 'cli') {
use Dice\Dice;
use Friendica\App\Mode;
use Friendica\Core\Logger\Capabilities\LogChannel;
use Friendica\Core\Logger\Capability\LogChannel;
use Friendica\Security\ExAuth;
use Psr\Log\LoggerInterface;
@ -79,8 +79,8 @@ chdir($directory);
require dirname(__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);
/** @var \Friendica\Core\Addon\Capability\ICanLoadAddons $addonLoader */
$addonLoader = $dice->create(\Friendica\Core\Addon\Capability\ICanLoadAddons::class);
$dice = $dice->addRules($addonLoader->getActiveAddonConfig('dependencies'));
$dice = $dice->addRule(LoggerInterface::class,['constructParams' => [LogChannel::AUTH_JABBERED]]);

View File

@ -26,15 +26,15 @@ if (php_sapi_name() !== 'cli') {
}
use Dice\Dice;
use Friendica\Core\Logger\Capabilities\LogChannel;
use Friendica\Core\Logger\Capability\LogChannel;
use Friendica\DI;
use Psr\Log\LoggerInterface;
require dirname(__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);
/** @var \Friendica\Core\Addon\Capability\ICanLoadAddons $addonLoader */
$addonLoader = $dice->create(\Friendica\Core\Addon\Capability\ICanLoadAddons::class);
$dice = $dice->addRules($addonLoader->getActiveAddonConfig('dependencies'));
$dice = $dice->addRule(LoggerInterface::class, ['constructParams' => [LogChannel::CONSOLE]]);

View File

@ -60,10 +60,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');
/** @var \Friendica\Core\Addon\Capabilities\ICanLoadAddons $addonLoader */
$addonLoader = $dice->create(\Friendica\Core\Addon\Capabilities\ICanLoadAddons::class);
/** @var \Friendica\Core\Addon\Capability\ICanLoadAddons $addonLoader */
$addonLoader = $dice->create(\Friendica\Core\Addon\Capability\ICanLoadAddons::class);
$dice = $dice->addRules($addonLoader->getActiveAddonConfig('dependencies'));
$dice = $dice->addRule(LoggerInterface::class, ['constructParams' => [Logger\Capabilities\LogChannel::DAEMON]]);
$dice = $dice->addRule(LoggerInterface::class, ['constructParams' => [Logger\Capability\LogChannel::DAEMON]]);
DI::init($dice);
\Friendica\Core\Logger\Handler\ErrorHandler::register($dice->create(\Psr\Log\LoggerInterface::class));

View File

@ -29,7 +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\Logger\Capability\LogChannel;
use Friendica\Core\Update;
use Friendica\Core\Worker;
use Friendica\DI;
@ -55,8 +55,8 @@ 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');
/** @var \Friendica\Core\Addon\Capabilities\ICanLoadAddons $addonLoader */
$addonLoader = $dice->create(\Friendica\Core\Addon\Capabilities\ICanLoadAddons::class);
/** @var \Friendica\Core\Addon\Capability\ICanLoadAddons $addonLoader */
$addonLoader = $dice->create(\Friendica\Core\Addon\Capability\ICanLoadAddons::class);
$dice = $dice->addRules($addonLoader->getActiveAddonConfig('dependencies'));
$dice = $dice->addRule(LoggerInterface::class, ['constructParams' => [LogChannel::WORKER]]);

View File

@ -10,9 +10,9 @@ This type of hook is based on the [Strategy Design Pattern](https://refactoring.
A strategy class defines a possible implementation of a given interface based on a unique name.
Every name is possible as long as it's unique and not `null`.
Using an empty name (`''`) is possible as well and should be used as the "default" implementation.
To register a strategy, use the [`ICanRegisterInstance`](../src/Core/Hooks/Capabilities/ICanRegisterInstances.php) interface.
To register a strategy, use the [`ICanRegisterInstance`](../src/Core/Hooks/Capability/ICanRegisterInstances.php) interface.
After registration, a caller can automatically create this instance with the [`ICanCreateInstances`](../src/Core/Hooks/Capabilities/ICanCreateInstances.php) interface and the chosen name.
After registration, a caller can automatically create this instance with the [`ICanCreateInstances`](../src/Core/Hooks/Capability/ICanCreateInstances.php) interface and the chosen name.
This is useful in case there are different, possible implementations for the same purpose, like for logging, locking, caching, ...
@ -43,11 +43,11 @@ public class ConcreteClassB implements ExampleInterface
}
}
/** @var \Friendica\Core\Hooks\Capabilities\ICanRegisterStrategies $instanceRegister */
/** @var \Friendica\Core\Hooks\Capability\ICanRegisterStrategies $instanceRegister */
$instanceRegister->registerStrategy(ExampleInterface::class, ConcreteClassA::class, 'A');
$instanceRegister->registerStrategy(ExampleInterface::class, ConcreteClassB::class, 'B');
/** @var \Friendica\Core\Hooks\Capabilities\ICanCreateInstances $instanceManager */
/** @var \Friendica\Core\Hooks\Capability\ICanCreateInstances $instanceManager */
/** @var ConcreteClassA $concreteClass */
$concreteClass = $instanceManager->create(ExampleInterface::class, 'A');
@ -62,14 +62,14 @@ To avoid registering all strategies manually inside the code, Friendica introduc
There, you can register all kind of strategies in one file.
### [`HookType::STRATEGY`](../src/Core/Hooks/Capabilities/HookType.php)
### [`HookType::STRATEGY`](../src/Core/Hooks/Capability/HookType.php)
For each given interface, a list of key-value pairs can be set, where the key is the concrete implementation class and the value is an array of unique names.
### Example
```php
use Friendica\Core\Hooks\Capabilities\BehavioralHookType as H;
use Friendica\Core\Hooks\Capability\BehavioralHookType as H;
return [
H::STRATEGY => [

View File

@ -30,8 +30,8 @@ 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);
/** @var \Friendica\Core\Addon\Capability\ICanLoadAddons $addonLoader */
$addonLoader = $dice->create(\Friendica\Core\Addon\Capability\ICanLoadAddons::class);
$dice = $dice->addRules($addonLoader->getActiveAddonConfig('dependencies'));
$dice = $dice->addRule(Friendica\App\Mode::class, ['call' => [['determineRunMode', [false, $_SERVER], Dice::CHAIN_CALL]]]);

View File

@ -22,7 +22,7 @@
namespace Friendica\Console;
use Friendica\App;
use Friendica\Core\KeyValueStorage\Capabilities\IManageKeyValuePairs;
use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
use Friendica\Core\L10n;
use Friendica\Core\Update;

View File

@ -544,7 +544,7 @@ class Item
unset($item['owner-name']);
unset($item['owner-avatar']);
}
$item['postopts'] = '';
}

View File

@ -19,7 +19,7 @@
*
*/
namespace Friendica\Core\Addon\Capabilities;
namespace Friendica\Core\Addon\Capability;
/**
* Interface for loading Addons specific content

View File

@ -21,7 +21,7 @@
namespace Friendica\Core\Addon\Model;
use Friendica\Core\Addon\Capabilities\ICanLoadAddons;
use Friendica\Core\Addon\Capability\ICanLoadAddons;
use Friendica\Core\Addon\Exception\AddonInvalidConfigFileException;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Util\Strings;

View File

@ -21,16 +21,13 @@
namespace Friendica\Core\Cache\Factory;
use Friendica\App\BaseURL;
use Friendica\Core\Cache\Enum;
use Friendica\Core\Cache\Capability\ICanCache;
use Friendica\Core\Cache\Exception\CachePersistenceException;
use Friendica\Core\Cache\Exception\InvalidCacheDriverException;
use Friendica\Core\Cache\Type;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Database\Database;
use Friendica\Core\Hooks\Capability\ICanCreateInstances;
use Friendica\Util\Profiler;
use Psr\Log\LoggerInterface;
/**
* Class CacheFactory
@ -44,59 +41,32 @@ class Cache
/**
* @var string The default cache if nothing set
*/
const DEFAULT_TYPE = Enum\Type::DATABASE;
const DEFAULT_TYPE = Type\DatabaseCache::NAME;
/** @var ICanCreateInstances */
protected $instanceCreator;
/** @var IManageConfigValues */
protected $config;
/** @var Profiler */
protected $profiler;
/**
* @var IManageConfigValues The IConfiguration to read parameters out of the config
*/
private $config;
/**
* @var Database The database connection in case that the cache is used the dba connection
*/
private $dba;
/**
* @var string The hostname, used as Prefix for Caching
*/
private $hostname;
/**
* @var Profiler The optional profiler if the cached should be profiled
*/
private $profiler;
/**
* @var LoggerInterface The Friendica Logger
*/
private $logger;
public function __construct(BaseURL $baseURL, IManageConfigValues $config, Database $dba, Profiler $profiler, LoggerInterface $logger)
public function __construct(ICanCreateInstances $instanceCreator, IManageConfigValues $config, Profiler $profiler)
{
$this->hostname = $baseURL->getHost();
$this->config = $config;
$this->dba = $dba;
$this->profiler = $profiler;
$this->logger = $logger;
$this->config = $config;
$this->instanceCreator = $instanceCreator;
$this->profiler = $profiler;
}
/**
* This method creates a CacheDriver for distributed caching with the given cache driver name
*
* @param string|null $type The cache type to create (default is per config)
* This method creates a CacheDriver for distributed caching
*
* @return ICanCache The instance of the CacheDriver
*
* @throws InvalidCacheDriverException In case the underlying cache driver isn't valid or not configured properly
* @throws CachePersistenceException In case the underlying cache has errors during persistence
*/
public function createDistributed(string $type = null): ICanCache
public function createDistributed(): ICanCache
{
if ($type === Enum\Type::APCU) {
throw new InvalidCacheDriverException('apcu doesn\'t support distributed caching.');
}
return $this->create($type ?? $this->config->get('system', 'distributed_cache_driver', self::DEFAULT_TYPE));
return $this->create($this->config->get('system', 'distributed_cache_driver', self::DEFAULT_TYPE));
}
/**
@ -117,31 +87,17 @@ class Cache
/**
* Creates a new Cache instance
*
* @param string $type The type of cache
* @param string $strategy The strategy, which cache instance should be used
*
* @return ICanCache
*
* @throws InvalidCacheDriverException In case the underlying cache driver isn't valid or not configured properly
* @throws CachePersistenceException In case the underlying cache has errors during persistence
*/
protected function create(string $type): ICanCache
protected function create(string $strategy): ICanCache
{
switch ($type) {
case Enum\Type::MEMCACHE:
$cache = new Type\MemcacheCache($this->hostname, $this->config);
break;
case Enum\Type::MEMCACHED:
$cache = new Type\MemcachedCache($this->hostname, $this->config, $this->logger);
break;
case Enum\Type::REDIS:
$cache = new Type\RedisCache($this->hostname, $this->config);
break;
case Enum\Type::APCU:
$cache = new Type\APCuCache($this->hostname);
break;
default:
$cache = new Type\DatabaseCache($this->hostname, $this->dba);
}
/** @var ICanCache $cache */
$cache = $this->instanceCreator->create(ICanCache::class, $strategy);
$profiling = $this->config->get('system', 'profiling', false);

View File

@ -23,7 +23,6 @@ namespace Friendica\Core\Cache\Type;
use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Enum\Type;
use Friendica\Core\Cache\Exception\InvalidCacheDriverException;
/**
@ -31,12 +30,12 @@ use Friendica\Core\Cache\Exception\InvalidCacheDriverException;
*/
class APCuCache extends AbstractCache implements ICanCacheInMemory
{
const NAME = 'apcu';
use CompareSetTrait;
use CompareDeleteTrait;
/**
* @param string $hostname
*
* @throws InvalidCacheDriverException
*/
public function __construct(string $hostname)
@ -173,12 +172,4 @@ class APCuCache extends AbstractCache implements ICanCacheInMemory
return true;
}
/**
* {@inheritDoc}
*/
public function getName(): string
{
return Type::APCU;
}
}

View File

@ -28,6 +28,8 @@ use Friendica\Core\Cache\Capability\ICanCache;
*/
abstract class AbstractCache implements ICanCache
{
const NAME = '';
/**
* @var string The hostname
*/
@ -105,4 +107,10 @@ abstract class AbstractCache implements ICanCache
return $result;
}
}
/** {@inheritDoc} */
public function getName(): string
{
return static::NAME;
}
}

View File

@ -29,6 +29,8 @@ use Friendica\Core\Cache\Enum;
*/
class ArrayCache extends AbstractCache implements ICanCacheInMemory
{
const NAME = 'array';
use CompareDeleteTrait;
/** @var array Array with the cached data */
@ -108,12 +110,4 @@ class ArrayCache extends AbstractCache implements ICanCacheInMemory
return false;
}
}
/**
* {@inheritDoc}
*/
public function getName(): string
{
return Enum\Type::ARRAY;
}
}

View File

@ -32,6 +32,8 @@ use Friendica\Util\DateTimeFormat;
*/
class DatabaseCache extends AbstractCache implements ICanCache
{
const NAME = 'database';
/**
* @var Database
*/
@ -154,12 +156,4 @@ class DatabaseCache extends AbstractCache implements ICanCache
throw new CachePersistenceException('Cannot clear cache', $exception);
}
}
/**
* {@inheritDoc}
*/
public function getName(): string
{
return Enum\Type::DATABASE;
}
}

View File

@ -23,7 +23,6 @@ namespace Friendica\Core\Cache\Type;
use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Enum\Type;
use Friendica\Core\Cache\Exception\CachePersistenceException;
use Friendica\Core\Cache\Exception\InvalidCacheDriverException;
use Friendica\Core\Config\Capability\IManageConfigValues;
@ -34,6 +33,8 @@ use Memcache;
*/
class MemcacheCache extends AbstractCache implements ICanCacheInMemory
{
const NAME = 'memcache';
use CompareSetTrait;
use CompareDeleteTrait;
use MemcacheCommandTrait;
@ -169,12 +170,4 @@ class MemcacheCache extends AbstractCache implements ICanCacheInMemory
$cacheKey = $this->getCacheKey($key);
return $this->memcache->add($cacheKey, serialize($value), MEMCACHE_COMPRESSED, $ttl);
}
/**
* {@inheritDoc}
*/
public function getName(): string
{
return Type::MEMCACHE;
}
}

View File

@ -23,7 +23,6 @@ namespace Friendica\Core\Cache\Type;
use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Enum\Type;
use Friendica\Core\Cache\Exception\CachePersistenceException;
use Friendica\Core\Cache\Exception\InvalidCacheDriverException;
use Friendica\Core\Config\Capability\IManageConfigValues;
@ -35,6 +34,8 @@ use Psr\Log\LoggerInterface;
*/
class MemcachedCache extends AbstractCache implements ICanCacheInMemory
{
const NAME = 'memcached';
use CompareSetTrait;
use CompareDeleteTrait;
use MemcacheCommandTrait;
@ -185,12 +186,4 @@ class MemcachedCache extends AbstractCache implements ICanCacheInMemory
$cacheKey = $this->getCacheKey($key);
return $this->memcached->add($cacheKey, $value, $ttl);
}
/**
* {@inheritDoc}
*/
public function getName(): string
{
return Type::MEMCACHED;
}
}

View File

@ -21,10 +21,8 @@
namespace Friendica\Core\Cache\Type;
use Exception;
use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Enum\Type;
use Friendica\Core\Cache\Exception\CachePersistenceException;
use Friendica\Core\Cache\Exception\InvalidCacheDriverException;
use Friendica\Core\Config\Capability\IManageConfigValues;
@ -35,6 +33,8 @@ use Redis;
*/
class RedisCache extends AbstractCache implements ICanCacheInMemory
{
const NAME = 'redis';
/**
* @var Redis
*/
@ -59,18 +59,23 @@ class RedisCache extends AbstractCache implements ICanCacheInMemory
$redis_pw = $config->get('system', 'redis_password');
$redis_db = $config->get('system', 'redis_db', 0);
if (!empty($redis_port) && !@$this->redis->connect($redis_host, $redis_port)) {
throw new CachePersistenceException('Expected Redis server at ' . $redis_host . ':' . $redis_port . ' isn\'t available');
} elseif (!@$this->redis->connect($redis_host)) {
throw new CachePersistenceException('Expected Redis server at ' . $redis_host . ' isn\'t available');
}
try {
if (!empty($redis_pw) && !$this->redis->auth($redis_pw)) {
throw new CachePersistenceException('Cannot authenticate redis server at ' . $redis_host . ':' . $redis_port);
}
if (!empty($redis_port) && !@$this->redis->connect($redis_host, $redis_port)) {
throw new CachePersistenceException('Expected Redis server at ' . $redis_host . ':' . $redis_port . ' isn\'t available');
} else if (!@$this->redis->connect($redis_host)) {
throw new CachePersistenceException('Expected Redis server at ' . $redis_host . ' isn\'t available');
}
if ($redis_db !== 0 && !$this->redis->select($redis_db)) {
throw new CachePersistenceException('Cannot switch to redis db ' . $redis_db . ' at ' . $redis_host . ':' . $redis_port);
if (!empty($redis_pw) && !$this->redis->auth($redis_pw)) {
throw new CachePersistenceException('Cannot authenticate redis server at ' . $redis_host . ':' . $redis_port);
}
if ($redis_db !== 0 && !$this->redis->select($redis_db)) {
throw new CachePersistenceException('Cannot switch to redis db ' . $redis_db . ' at ' . $redis_host . ':' . $redis_port);
}
} catch (\RedisException $exception) {
throw new CachePersistenceException('Redis connection fails unexpectedly', $exception);
}
}
@ -211,12 +216,4 @@ class RedisCache extends AbstractCache implements ICanCacheInMemory
$this->redis->unwatch();
return false;
}
/**
* {@inheritDoc}
*/
public function getName(): string
{
return Type::REDIS;
}
}

View File

@ -19,7 +19,7 @@
*
*/
namespace Friendica\Core\Hooks\Capabilities;
namespace Friendica\Core\Hooks\Capability;
/**
* An enum of hook types, based on behavioral design patterns

View File

@ -19,7 +19,7 @@
*
*/
namespace Friendica\Core\Hooks\Capabilities;
namespace Friendica\Core\Hooks\Capability;
/**
* creates special instances for given classes

View File

@ -19,7 +19,7 @@
*
*/
namespace Friendica\Core\Hooks\Capabilities;
namespace Friendica\Core\Hooks\Capability;
use Friendica\Core\Hooks\Exceptions\HookRegisterArgumentException;

View File

@ -22,8 +22,8 @@
namespace Friendica\Core\Hooks\Model;
use Dice\Dice;
use Friendica\Core\Hooks\Capabilities\ICanCreateInstances;
use Friendica\Core\Hooks\Capabilities\ICanRegisterStrategies;
use Friendica\Core\Hooks\Capability\ICanCreateInstances;
use Friendica\Core\Hooks\Capability\ICanRegisterStrategies;
use Friendica\Core\Hooks\Exceptions\HookInstanceException;
use Friendica\Core\Hooks\Exceptions\HookRegisterArgumentException;
use Friendica\Core\Hooks\Util\StrategiesFileManager;

View File

@ -21,8 +21,8 @@
namespace Friendica\Core\Hooks\Util;
use Friendica\Core\Addon\Capabilities\ICanLoadAddons;
use Friendica\Core\Hooks\Capabilities\ICanRegisterStrategies;
use Friendica\Core\Addon\Capability\ICanLoadAddons;
use Friendica\Core\Hooks\Capability\ICanRegisterStrategies;
use Friendica\Core\Hooks\Exceptions\HookConfigException;
/**
@ -30,6 +30,11 @@ use Friendica\Core\Hooks\Exceptions\HookConfigException;
*/
class StrategiesFileManager
{
/**
* The default hook-file-key of strategies
* -> it's an empty string to cover empty/missing config values
*/
const STRATEGY_DEFAULT_KEY = '';
const STATIC_DIR = 'static';
const CONFIG_NAME = 'strategies';

View File

@ -19,7 +19,7 @@
*
*/
namespace Friendica\Core\KeyValueStorage\Capabilities;
namespace Friendica\Core\KeyValueStorage\Capability;
use Friendica\Core\KeyValueStorage\Exceptions\KeyValueStoragePersistenceException;

View File

@ -19,17 +19,17 @@
*
*/
namespace Friendica\Core\Cache\Enum;
namespace Friendica\Core\KeyValueStorage\Factory;
/**
* Enumeration for cache types
*/
abstract class Type
use Friendica\Core\Hooks\Capability\ICanCreateInstances;
use Friendica\Core\Hooks\Util\StrategiesFileManager;
use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
class KeyValueStorage
{
const APCU = 'apcu';
const REDIS = 'redis';
const ARRAY = 'array';
const MEMCACHE = 'memcache';
const DATABASE = 'database';
const MEMCACHED = 'memcached';
public function create(ICanCreateInstances $instanceCreator): IManageKeyValuePairs
{
/** @var IManageKeyValuePairs */
return $instanceCreator->create(IManageKeyValuePairs::class, StrategiesFileManager::STRATEGY_DEFAULT_KEY);
}
}

View File

@ -21,13 +21,15 @@
namespace Friendica\Core\KeyValueStorage\Type;
use Friendica\Core\KeyValueStorage\Capabilities\IManageKeyValuePairs;
use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
/**
* An abstract helper class for Key-Value storage classes
*/
abstract class AbstractKeyValueStorage implements IManageKeyValuePairs
{
const NAME = '';
/** {@inheritDoc} */
public function get(string $key)
{

View File

@ -30,6 +30,7 @@ use Friendica\Database\Database;
*/
class DBKeyValueStorage extends AbstractKeyValueStorage
{
const NAME = 'database';
const DB_KEY_VALUE_TABLE = 'key-value';
/** @var Database */

View File

@ -21,7 +21,7 @@
namespace Friendica\Core\Lock\Enum;
use Friendica\Core\Cache\Enum\Type as CacheType;
use Friendica\Core\Cache\Type\DatabaseCache;
/**
* Enumeration for lock types
@ -30,6 +30,6 @@ use Friendica\Core\Cache\Enum\Type as CacheType;
*/
abstract class Type
{
const DATABASE = CacheType::DATABASE;
const DATABASE = DatabaseCache::NAME;
const SEMAPHORE = 'semaphore';
}

View File

@ -23,10 +23,10 @@ namespace Friendica\Core\Lock\Factory;
use Friendica\Core\Cache\Factory\Cache;
use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Enum;
use Friendica\Core\Cache\Type as CacheType;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Lock\Capability\ICanLock;
use Friendica\Core\Lock\Type;
use Friendica\Core\Lock\Type as LockType;
use Friendica\Database\Database;
use Psr\Log\LoggerInterface;
@ -78,20 +78,20 @@ class Lock
try {
switch ($lock_type) {
case Enum\Type::MEMCACHE:
case Enum\Type::MEMCACHED:
case Enum\Type::REDIS:
case Enum\Type::APCU:
case CacheType\MemcacheCache::NAME:
case CacheType\MemcachedCache::NAME:
case CacheType\RedisCache::NAME:
case CacheType\APCuCache::NAME:
$cache = $this->cacheFactory->createLocal($lock_type);
if ($cache instanceof ICanCacheInMemory) {
return new Type\CacheLock($cache);
return new LockType\CacheLock($cache);
} else {
throw new \Exception(sprintf('Incompatible cache driver \'%s\' for lock used', $lock_type));
}
case 'database':
return new Type\DatabaseLock($this->dba);
return new LockType\DatabaseLock($this->dba);
case 'semaphore':
return new Type\SemaphoreLock();
return new LockType\SemaphoreLock();
default:
return self::useAutoDriver();
}
@ -116,7 +116,7 @@ class Lock
// 1. Try to use Semaphores for - local - locking
if (function_exists('sem_get')) {
try {
return new Type\SemaphoreLock();
return new LockType\SemaphoreLock();
} catch (\Exception $exception) {
$this->logger->warning('Using Semaphore driver for locking failed.', ['exception' => $exception]);
}
@ -124,11 +124,11 @@ class Lock
// 2. Try to use Cache Locking (don't use the DB-Cache Locking because it works different!)
$cache_type = $this->config->get('system', 'cache_driver', 'database');
if ($cache_type != Enum\Type::DATABASE) {
if ($cache_type != CacheType\DatabaseCache::NAME) {
try {
$cache = $this->cacheFactory->createLocal($cache_type);
if ($cache instanceof ICanCacheInMemory) {
return new Type\CacheLock($cache);
return new LockType\CacheLock($cache);
}
} catch (\Exception $exception) {
$this->logger->warning('Using Cache driver for locking failed.', ['exception' => $exception]);
@ -136,6 +136,6 @@ class Lock
}
// 3. Use Database Locking as a Fallback
return new Type\DatabaseLock($this->dba);
return new LockType\DatabaseLock($this->dba);
}
}

View File

@ -36,7 +36,7 @@ abstract class AbstractLock implements ICanLock
/**
* Check if we've locally acquired a lock
*
* @param string key The Name of the lock
* @param string $key The Name of the lock
*
* @return bool Returns true if the lock is set
*/

View File

@ -19,7 +19,7 @@
*
*/
namespace Friendica\Core\Logger\Capabilities;
namespace Friendica\Core\Logger\Capability;
/**
* Whenever a logging specific check is necessary, use this interface to encapsulate and centralize this logic

View File

@ -19,7 +19,7 @@
*
*/
namespace Friendica\Core\Logger\Capabilities;
namespace Friendica\Core\Logger\Capability;
interface IHaveCallIntrospections
{

View File

@ -19,7 +19,7 @@
*
*/
namespace Friendica\Core\Logger\Capabilities;
namespace Friendica\Core\Logger\Capability;
/**
* An enum class for the Log channels

View File

@ -21,7 +21,7 @@
namespace Friendica\Core\Logger\Factory;
use Friendica\Core\Logger\Capabilities\IHaveCallIntrospections;
use Friendica\Core\Logger\Capability\IHaveCallIntrospections;
use Psr\Log\LogLevel;
/**

View File

@ -22,8 +22,8 @@
namespace Friendica\Core\Logger\Factory;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Hooks\Capabilities\ICanCreateInstances;
use Friendica\Core\Logger\Capabilities\LogChannel;
use Friendica\Core\Hooks\Capability\ICanCreateInstances;
use Friendica\Core\Logger\Capability\LogChannel;
use Friendica\Core\Logger\Type\ProfilerLogger as ProfilerLoggerClass;
use Friendica\Util\Profiler;
use Psr\Log\LoggerInterface;

View File

@ -22,7 +22,7 @@
namespace Friendica\Core\Logger\Factory;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Logger\Capabilities\LogChannel;
use Friendica\Core\Logger\Capability\LogChannel;
use Friendica\Core\Logger\Exception\LoggerArgumentException;
use Friendica\Core\Logger\Exception\LoggerException;
use Friendica\Core\Logger\Exception\LogLevelException;

View File

@ -21,7 +21,7 @@
namespace Friendica\Core\Logger\Type;
use Friendica\Core\Logger\Capabilities\IHaveCallIntrospections;
use Friendica\Core\Logger\Capability\IHaveCallIntrospections;
use Friendica\Core\Logger\Exception\LoggerException;
use Friendica\Util\Strings;
use Psr\Log\LoggerInterface;
@ -38,6 +38,8 @@ use Psr\Log\LogLevel;
*/
abstract class AbstractLogger implements LoggerInterface
{
const NAME = '';
/**
* The output channel of this logger
* @var string

View File

@ -21,7 +21,7 @@
namespace Friendica\Core\Logger\Type;
use Friendica\Core\Logger\Capabilities\IHaveCallIntrospections;
use Friendica\Core\Logger\Capability\IHaveCallIntrospections;
use Friendica\Core\Logger\Exception\LoggerException;
use Friendica\Core\Logger\Exception\LogLevelException;
use Friendica\Util\DateTimeFormat;
@ -32,6 +32,8 @@ use Psr\Log\LogLevel;
*/
class StreamLogger extends AbstractLogger
{
const NAME = 'stream';
/**
* The minimum loglevel at which this logger will be triggered
* @var string

View File

@ -21,7 +21,7 @@
namespace Friendica\Core\Logger\Type;
use Friendica\Core\Logger\Capabilities\IHaveCallIntrospections;
use Friendica\Core\Logger\Capability\IHaveCallIntrospections;
use Friendica\Core\Logger\Exception\LoggerException;
use Friendica\Core\Logger\Exception\LogLevelException;
use Psr\Log\LogLevel;
@ -32,6 +32,8 @@ use Psr\Log\LogLevel;
*/
class SyslogLogger extends AbstractLogger
{
const NAME = 'syslog';
const IDENT = 'Friendica';
/** @var int The default syslog flags */

View File

@ -22,7 +22,7 @@
namespace Friendica\Core\Logger\Util;
use Friendica\App\Request;
use Friendica\Core\Logger\Capabilities\IHaveCallIntrospections;
use Friendica\Core\Logger\Capability\IHaveCallIntrospections;
/**
* Get Introspection information about the current call

View File

@ -23,7 +23,7 @@ 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\Capability\ICheckLoggerSettings;
use Friendica\Core\Logger\Exception\LoggerUnusableException;
/** {@inheritDoc} */

View File

@ -22,28 +22,16 @@
namespace Friendica\Core\PConfig\Factory;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Hooks\Capability\ICanCreateInstances;
use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues;
use Friendica\Core\PConfig\Repository;
use Friendica\Core\PConfig\Type;
use Friendica\Core\PConfig\ValueObject;
class PConfig
{
/**
* @param IManageConfigValues $config The config
* @param ValueObject\Cache $pConfigCache The personal config cache
* @param Repository\PConfig $configRepo The configuration model
*
* @return IManagePersonalConfigValues
*/
public function create(IManageConfigValues $config, ValueObject\Cache $pConfigCache, Repository\PConfig $configRepo): IManagePersonalConfigValues
public function create(ICanCreateInstances $instanceCreator, IManageConfigValues $config): IManagePersonalConfigValues
{
if ($config->get('system', 'config_adapter') === 'preload') {
$configuration = new Type\PreloadPConfig($pConfigCache, $configRepo);
} else {
$configuration = new Type\JitPConfig($pConfigCache, $configRepo);
}
$strategy = $config->get('system', 'config_adapter');
return $configuration;
/** @var IManagePersonalConfigValues */
return $instanceCreator->create(IManagePersonalConfigValues::class, $strategy);
}
}

View File

@ -34,6 +34,8 @@ use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues;
*/
abstract class AbstractPConfigValues implements IManagePersonalConfigValues
{
const NAME = '';
/**
* @var Cache
*/

View File

@ -33,6 +33,8 @@ use Friendica\Core\PConfig\ValueObject;
*/
class JitPConfig extends AbstractPConfigValues
{
const NAME = 'jit';
/**
* @var array Array of already loaded db values (even if there was no value)
*/

View File

@ -32,6 +32,8 @@ use Friendica\Core\PConfig\ValueObject;
*/
class PreloadPConfig extends AbstractPConfigValues
{
const NAME = 'preload';
/** @var array */
private $config_loaded;

View File

@ -22,8 +22,8 @@
namespace Friendica\Core\Session\Factory;
use Friendica\App;
use Friendica\Core\Cache\Enum;
use Friendica\Core\Cache\Factory\Cache;
use Friendica\Core\Cache\Type\DatabaseCache;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Session\Capability\IHandleSessions;
use Friendica\Core\Session\Type;
@ -74,7 +74,7 @@ class Session
$cache = $cacheFactory->createDistributed();
// In case we're using the db as cache driver, use the native db session, not the cache
if ($config->get('system', 'cache_driver') === Enum\Type::DATABASE) {
if ($config->get('system', 'cache_driver') === DatabaseCache::NAME) {
$handler = new Handler\Database($dba, $logger, $server);
} else {
$handler = new Handler\Cache($cache, $logger);

View File

@ -22,7 +22,7 @@
namespace Friendica;
use Dice\Dice;
use Friendica\Core\Logger\Capabilities\ICheckLoggerSettings;
use Friendica\Core\Logger\Capability\ICheckLoggerSettings;
use Friendica\Core\Logger\Util\LoggerSettingsCheck;
use Friendica\Core\Session\Capability\IHandleSessions;
use Friendica\Core\Session\Capability\IHandleUserSessions;
@ -210,9 +210,9 @@ abstract class DI
return self::$dice->create(Core\Config\Util\ConfigFileManager::class);
}
public static function keyValue(): Core\KeyValueStorage\Capabilities\IManageKeyValuePairs
public static function keyValue(): Core\KeyValueStorage\Capability\IManageKeyValuePairs
{
return self::$dice->create(Core\KeyValueStorage\Capabilities\IManageKeyValuePairs::class);
return self::$dice->create(Core\KeyValueStorage\Capability\IManageKeyValuePairs::class);
}
/**

View File

@ -26,7 +26,7 @@ use Friendica\BaseModule;
use Friendica\Core\Addon;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Hook;
use Friendica\Core\KeyValueStorage\Capabilities\IManageKeyValuePairs;
use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
use Friendica\Core\L10n;
use Friendica\Core\Renderer;
use Friendica\Core\Session\Capability\IHandleUserSessions;

View File

@ -25,7 +25,7 @@ use Friendica\App;
use Friendica\BaseModule;
use Friendica\Core\Addon;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\KeyValueStorage\Capabilities\IManageKeyValuePairs;
use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
use Friendica\Core\L10n;
use Friendica\Core\System;
use Friendica\Network\HTTPException\NotFoundException;
@ -38,7 +38,7 @@ class Statistics extends BaseModule
protected $config;
/** @var IManageKeyValuePairs */
protected $keyValue;
public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, IManageConfigValues $config, IManageKeyValuePairs $keyValue, Response $response, array $server, array $parameters = [])
{
parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);

View File

@ -37,8 +37,8 @@ use Dice\Dice;
use Friendica\App;
use Friendica\Core\Cache;
use Friendica\Core\Config;
use Friendica\Core\Hooks\Capabilities\ICanCreateInstances;
use Friendica\Core\Hooks\Capabilities\ICanRegisterStrategies;
use Friendica\Core\Hooks\Capability\ICanCreateInstances;
use Friendica\Core\Hooks\Capability\ICanRegisterStrategies;
use Friendica\Core\Hooks\Model\DiceInstanceManager;
use Friendica\Core\PConfig;
use Friendica\Core\L10n;
@ -63,7 +63,7 @@ return [
// one instance for the whole execution
'shared' => true,
],
\Friendica\Core\Addon\Capabilities\ICanLoadAddons::class => [
\Friendica\Core\Addon\Capability\ICanLoadAddons::class => [
'instanceOf' => \Friendica\Core\Addon\Model\AddonLoader::class,
'constructParams' => [
[Dice::INSTANCE => '$basepath'],
@ -178,6 +178,20 @@ return [
$_SERVER,
],
],
'$hostname' => [
'instanceOf' => App\BaseURL::class,
'constructParams' => [
$_SERVER,
],
'call' => [
['getHost', [], Dice::CHAIN_CALL],
],
],
Cache\Type\AbstractCache::class => [
'constructParams' => [
[Dice::INSTANCE => '$hostname'],
],
],
App\Page::class => [
'constructParams' => [
[Dice::INSTANCE => '$basepath'],
@ -201,10 +215,10 @@ return [
['create', [], Dice::CHAIN_CALL],
],
],
\Friendica\Core\Logger\Capabilities\IHaveCallIntrospections::class => [
\Friendica\Core\Logger\Capability\IHaveCallIntrospections::class => [
'instanceOf' => \Friendica\Core\Logger\Util\Introspection::class,
'constructParams' => [
\Friendica\Core\Logger\Capabilities\IHaveCallIntrospections::IGNORE_CLASS_LIST,
\Friendica\Core\Logger\Capability\IHaveCallIntrospections::IGNORE_CLASS_LIST,
],
],
'$devLogger' => [
@ -276,8 +290,11 @@ return [
['getBackend', [], Dice::CHAIN_CALL],
],
],
\Friendica\Core\KeyValueStorage\Capabilities\IManageKeyValuePairs::class => [
'instanceOf' => \Friendica\Core\KeyValueStorage\Type\DBKeyValueStorage::class,
\Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs::class => [
'instanceOf' => \Friendica\Core\KeyValueStorage\Factory\KeyValueStorage::class,
'call' => [
['create', [], Dice::CHAIN_CALL],
],
],
Network\HTTPClient\Capability\ICanSendHttpRequests::class => [
'instanceOf' => Network\HTTPClient\Factory\HttpClient::class,

View File

@ -19,14 +19,31 @@
*
*/
use Friendica\Core\Hooks\Capabilities\BehavioralHookType as H;
use Friendica\Core\Cache;
use Friendica\Core\Hooks\Util\StrategiesFileManager;
use Friendica\Core\Logger\Type;
use Friendica\Core\KeyValueStorage;
use Friendica\Core\PConfig;
use Psr\Log;
return [
Log\LoggerInterface::class => [
Log\NullLogger::class => [''],
Type\SyslogLogger::class => ['syslog'],
Type\StreamLogger::class => ['stream'],
Log\NullLogger::class => [StrategiesFileManager::STRATEGY_DEFAULT_KEY],
Type\SyslogLogger::class => [Type\SyslogLogger::NAME],
Type\StreamLogger::class => [Type\StreamLogger::NAME],
],
Cache\Capability\ICanCache::class => [
Cache\Type\DatabaseCache::class => [Cache\Type\DatabaseCache::NAME, StrategiesFileManager::STRATEGY_DEFAULT_KEY],
Cache\Type\APCuCache::class => [Cache\Type\APCuCache::NAME],
Cache\Type\MemcacheCache::class => [Cache\Type\MemcacheCache::NAME],
Cache\Type\MemcachedCache::class => [Cache\Type\MemcachedCache::NAME],
Cache\Type\RedisCache::class => [Cache\Type\RedisCache::NAME],
],
KeyValueStorage\Capability\IManageKeyValuePairs::class => [
KeyValueStorage\Type\DBKeyValueStorage::class => [KeyValueStorage\Type\DBKeyValueStorage::NAME, StrategiesFileManager::STRATEGY_DEFAULT_KEY],
],
PConfig\Capability\IManagePersonalConfigValues::class => [
PConfig\Type\JitPConfig::class => [PConfig\Type\JitPConfig::NAME],
PConfig\Type\PreloadPConfig::class => [PConfig\Type\PreloadPConfig::NAME, StrategiesFileManager::STRATEGY_DEFAULT_KEY],
],
];

24
tests/phpunit-addons.xml Normal file
View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
bootstrap="bootstrap.php"
verbose="true"
timeoutForSmallTests="900"
timeoutForMediumTests="900"
timeoutForLargeTests="900"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
<testsuite name="friendica-addons">
<directory suffix=".php">../addon/*/tests/</directory>
</testsuite>
<!-- Filters for Code Coverage -->
<coverage>
<include>
<directory suffix=".php">../addon/</directory>
</include>
<exclude>
<directory suffix=".php">../addon/*/tests/</directory>
<directory suffix=".php">../addon/*/view/</directory>
<directory suffix=".php">../addon/*/vendor/</directory>
</exclude>
</coverage>
</phpunit>

View File

@ -54,7 +54,7 @@ class AddonLoaderTest extends MockedTest
<?php
return [
\Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
\Friendica\Core\Hooks\Capability\BehavioralHookType::STRATEGY => [
\Psr\Log\LoggerInterface::class => [
\Psr\Log\NullLogger::class => [''],
],
@ -79,7 +79,7 @@ EOF;
'addon/testaddon1/static/hooks.config.php' => $this->content,
],
'assertion' => [
\Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
\Friendica\Core\Hooks\Capability\BehavioralHookType::STRATEGY => [
\Psr\Log\LoggerInterface::class => [
\Psr\Log\NullLogger::class => [''],
],
@ -94,7 +94,7 @@ EOF;
'addon/testaddon2/static/hooks.config.php' => $this->content,
],
'assertion' => [
\Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
\Friendica\Core\Hooks\Capability\BehavioralHookType::STRATEGY => [
\Psr\Log\LoggerInterface::class => [
\Psr\Log\NullLogger::class => ['', ''],
],
@ -118,7 +118,7 @@ EOF;
'addon/testaddon2/static/hooks.config.php' => $this->content,
],
'assertion' => [
\Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
\Friendica\Core\Hooks\Capability\BehavioralHookType::STRATEGY => [
\Psr\Log\LoggerInterface::class => [
\Psr\Log\NullLogger::class => [''],
],

View File

@ -23,6 +23,7 @@ namespace Friendica\Test\src\Core\Cache;
use Friendica\Core\Cache\Capability\ICanCache;
use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Type\AbstractCache;
use Friendica\Test\MockedTest;
use Friendica\Util\PidFile;
@ -246,4 +247,13 @@ abstract class CacheTest extends MockedTest
self::assertTrue($this->instance->set('key space', 'value'));
self::assertEquals('value', $this->instance->get('key space'));
}
public function testGetName()
{
if (defined(get_class($this->instance) . '::NAME')) {
self::assertEquals($this->instance::NAME, $this->instance->getName());
} else {
self::expectNotToPerformAssertions();
}
}
}

View File

@ -21,6 +21,7 @@
namespace Friendica\Test\src\Core\Cache;
use Friendica\App\BaseURL;
use Friendica\Core\Cache;
use Friendica\Test\DatabaseTestTrait;
use Friendica\Test\Util\CreateDatabaseTrait;

View File

@ -21,8 +21,8 @@
namespace Friendica\Test\src\Core\Hooks\Util;
use Friendica\Core\Addon\Capabilities\ICanLoadAddons;
use Friendica\Core\Hooks\Capabilities\ICanRegisterStrategies;
use Friendica\Core\Addon\Capability\ICanLoadAddons;
use Friendica\Core\Hooks\Capability\ICanRegisterStrategies;
use Friendica\Core\Hooks\Exceptions\HookConfigException;
use Friendica\Core\Hooks\Util\StrategiesFileManager;
use Friendica\Test\MockedTest;

View File

@ -21,7 +21,7 @@
namespace Friendica\Test\src\Core\KeyValueStorage;
use Friendica\Core\KeyValueStorage\Capabilities\IManageKeyValuePairs;
use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
use Friendica\Core\KeyValueStorage\Type\DBKeyValueStorage;
use Friendica\Database\Database;
use Friendica\Test\Util\CreateDatabaseTrait;

View File

@ -21,7 +21,7 @@
namespace Friendica\Test\src\Core\KeyValueStorage;
use Friendica\Core\KeyValueStorage\Capabilities\IManageKeyValuePairs;
use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
use Friendica\Test\MockedTest;
abstract class KeyValueStorageTest extends MockedTest

View File

@ -21,7 +21,7 @@
namespace Friendica\Test\src\Core\Logger;
use Friendica\Core\Logger\Capabilities\IHaveCallIntrospections;
use Friendica\Core\Logger\Capability\IHaveCallIntrospections;
use Friendica\Core\Logger\Type\SyslogLogger;
/**