diff --git a/bin/worker.php b/bin/worker.php index de207ae98f..a742132480 100755 --- a/bin/worker.php +++ b/bin/worker.php @@ -69,8 +69,6 @@ if (!DI::mode()->has(App\Mode::MAINTENANCEDISABLED)) { return; } -DI::baseUrl()->saveByURL(DI::config()->get('system', 'url')); - $spawn = array_key_exists('s', $options) || array_key_exists('spawn', $options); if ($spawn) { diff --git a/composer.lock b/composer.lock index 63f8a0d5b0..0034780263 100644 --- a/composer.lock +++ b/composer.lock @@ -666,6 +666,7 @@ "x509", "x690" ], + "abandoned": true, "time": "2021-12-11T12:41:06+00:00" }, { @@ -1244,16 +1245,16 @@ }, { "name": "level-2/dice", - "version": "4.0.3", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/Level-2/Dice.git", - "reference": "3e9a8548398c01e2527110c916a93f6efa17ac9c" + "reference": "e04c98d96bcc932a917b2b7e7944887e4839056a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Level-2/Dice/zipball/3e9a8548398c01e2527110c916a93f6efa17ac9c", - "reference": "3e9a8548398c01e2527110c916a93f6efa17ac9c", + "url": "https://api.github.com/repos/Level-2/Dice/zipball/e04c98d96bcc932a917b2b7e7944887e4839056a", + "reference": "e04c98d96bcc932a917b2b7e7944887e4839056a", "shasum": "" }, "require": { @@ -1263,6 +1264,9 @@ "phpunit/phpunit": "^6.5" }, "type": "library", + "extra": { + "patches_applied": [] + }, "autoload": { "psr-4": { "Dice\\": "./" @@ -1286,7 +1290,7 @@ "di", "ioc" ], - "time": "2021-04-20T14:06:06+00:00" + "time": "2022-03-28T21:20:23+00:00" }, { "name": "lightopenid/lightopenid", diff --git a/config/local-sample.config.php b/config/local-sample.config.php index 9bf073df1d..2e9c02b421 100644 --- a/config/local-sample.config.php +++ b/config/local-sample.config.php @@ -36,9 +36,11 @@ return [ 'sitename' => 'Friendica Social Network', 'register_policy' => \Friendica\Module\Register::OPEN, 'register_text' => '', + 'hostname' => 'friendica.local', ], 'system' => [ 'default_timezone' => 'UTC', 'language' => 'en', + 'url' => 'https://friendica.local', ], ]; diff --git a/database.sql b/database.sql index 48e0930e67..0b91aedc06 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2023.03-dev (Giant Rhubarb) --- DB_UPDATE_VERSION 1511 +-- DB_UPDATE_VERSION 1512 -- ------------------------------------------ diff --git a/mods/local.config.vagrant.php b/mods/local.config.vagrant.php index da873116d8..379ddf185d 100644 --- a/mods/local.config.vagrant.php +++ b/mods/local.config.vagrant.php @@ -40,5 +40,7 @@ return [ 'language' => 'en', 'basepath' => '/vagrant', 'ssl_policy' => \Friendica\App\BaseURL::SSL_POLICY_SELFSIGN, + 'url' => 'https://192.168.56.10', + 'urlpath' => '', ], ]; diff --git a/src/App.php b/src/App.php index a5ef7970d5..9df62a4e77 100644 --- a/src/App.php +++ b/src/App.php @@ -540,25 +540,6 @@ class App return Core\Theme::getStylesheetPath($this->getCurrentTheme()); } - /** - * Sets the base url for use in cmdline programs which don't have - * $_SERVER variables - */ - public function checkURL() - { - $url = $this->config->get('system', 'url'); - - // if the url isn't set or the stored url is radically different - // than the currently visited url, store the current value accordingly. - // "Radically different" ignores common variations such as http vs https - // and www.example.com vs example.com. - // We will only change the url to an ip address if there is no existing setting - - if (empty($url) || (!Util\Strings::compareLink($url, $this->baseURL->get())) && (!preg_match("/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/", $this->baseURL->getHostname()))) { - $this->config->set('system', 'url', $this->baseURL->get()); - } - } - /** * Frontend App script * @@ -657,7 +638,6 @@ class App if ($this->mode->isInstall() && $moduleName !== 'install') { $this->baseURL->redirect('install'); } else { - $this->checkURL(); Core\Update::check($this->getBasePath(), false); Core\Addon::loadAddons(); Core\Hook::loadHooks(); diff --git a/src/App/BaseURL.php b/src/App/BaseURL.php index ab3d03a5be..f02cb9ef99 100644 --- a/src/App/BaseURL.php +++ b/src/App/BaseURL.php @@ -257,109 +257,18 @@ class BaseURL */ public function __construct(IManageConfigValues $config, array $server) { - $this->config = $config; - $this->server = $server; - - $this->determineSchema(); - $this->checkConfig(); - } - - /** - * Check the current config during loading - */ - public function checkConfig() - { + $this->config = $config; + $this->server = $server; $this->hostname = $this->config->get('config', 'hostname'); - $this->urlPath = $this->config->get('system', 'urlpath'); - $this->sslPolicy = $this->config->get('system', 'ssl_policy'); + $this->urlPath = $this->config->get('system', 'urlpath') ?? ''; + $this->sslPolicy = $this->config->get('system', 'ssl_policy') ?? static::DEFAULT_SSL_SCHEME; $this->url = $this->config->get('system', 'url'); - if (empty($this->hostname)) { - $this->determineHostname(); - - if (!empty($this->hostname)) { - $this->config->set('config', 'hostname', $this->hostname); - } + if (empty($this->hostname) || empty($this->url)) { + throw new \Exception('Invalid config - Missing system.url or config.hostname'); } - if (!isset($this->urlPath)) { - $this->determineURLPath(); - $this->config->set('system', 'urlpath', $this->urlPath); - } - - if (!isset($this->sslPolicy)) { - if ($this->scheme == 'https') { - $this->sslPolicy = self::SSL_POLICY_FULL; - } else { - $this->sslPolicy = self::DEFAULT_SSL_SCHEME; - } - $this->config->set('system', 'ssl_policy', $this->sslPolicy); - } - - if (empty($this->url)) { - $this->determineBaseUrl(); - - if (!empty($this->url)) { - $this->config->set('system', 'url', $this->url); - } - } - } - - /** - * Determines the hostname of this node if not set already - */ - private function determineHostname() - { - $this->hostname = ''; - - if (!empty($this->server['SERVER_NAME'])) { - $this->hostname = $this->server['SERVER_NAME']; - - if (!empty($this->server['SERVER_PORT']) && $this->server['SERVER_PORT'] != 80 && $this->server['SERVER_PORT'] != 443) { - $this->hostname .= ':' . $this->server['SERVER_PORT']; - } - } - } - - /** - * Figure out if we are running at the top of a domain or in a sub-directory - */ - private function determineURLPath() - { - $this->urlPath = ''; - - /* - * The automatic path detection in this function is currently deactivated, - * see issue https://github.com/friendica/friendica/issues/6679 - * - * The problem is that the function seems to be confused with some url. - * These then confuses the detection which changes the url path. - */ - - /* Relative script path to the web server root - * Not all of those $_SERVER properties can be present, so we do by inverse priority order - */ - $relative_script_path = - ($this->server['REDIRECT_URL'] ?? '') ?: - ($this->server['REDIRECT_URI'] ?? '') ?: - ($this->server['REDIRECT_SCRIPT_URL'] ?? '') ?: - ($this->server['SCRIPT_URL'] ?? '') ?: - $this->server['REQUEST_URI'] ?? ''; - - /* $relative_script_path gives /relative/path/to/friendica/module/parameter - * QUERY_STRING gives pagename=module/parameter - * - * To get /relative/path/to/friendica we perform dirname() for as many levels as there are slashes in the QUERY_STRING - */ - if (!empty($relative_script_path)) { - // Module - if (!empty($this->server['QUERY_STRING'])) { - $this->urlPath = trim(dirname($relative_script_path, substr_count(trim($this->server['QUERY_STRING'], '/'), '/') + 1), '/'); - } else { - // Root page - $this->urlPath = trim($relative_script_path, '/'); - } - } + $this->determineSchema(); } /** diff --git a/src/App/Request.php b/src/App/Request.php index 675841ae76..d61303d5d7 100644 --- a/src/App/Request.php +++ b/src/App/Request.php @@ -74,7 +74,7 @@ class Request public function __construct(IManageConfigValues $config, array $server = []) { $this->remoteAddress = $this->determineRemoteAddress($config, $server); - $this->requestId = $server[static::DEFAULT_REQUEST_ID_HEADER] ?? System::createGUID(8); + $this->requestId = $server[static::DEFAULT_REQUEST_ID_HEADER] ?? System::createGUID(8, false); } /** diff --git a/src/Content/OEmbed.php b/src/Content/OEmbed.php index 7553cd9f81..562febdaf9 100644 --- a/src/Content/OEmbed.php +++ b/src/Content/OEmbed.php @@ -316,7 +316,7 @@ class OEmbed if ($stopoembed == true) { return preg_replace("/\[embed\](.+?)\[\/embed\]/is", "" . DI::l10n()->t('Embedding disabled') . " : $1", $text); } - return preg_replace_callback("/\[embed\](.+?)\[\/embed\]/is", ['self', 'replaceCallback'], $text); + return preg_replace_callback("/\[embed\](.+?)\[\/embed\]/is", [self::class, 'replaceCallback'], $text); } /** diff --git a/src/Content/Smilies.php b/src/Content/Smilies.php index 5ebb5b64e8..c51d9b3305 100644 --- a/src/Content/Smilies.php +++ b/src/Content/Smilies.php @@ -218,8 +218,8 @@ class Smilies return $text; } - $text = preg_replace_callback('/<(pre)>(.*?)<\/pre>/ism', 'self::encode', $text); - $text = preg_replace_callback('/<(code)>(.*?)<\/code>/ism', 'self::encode', $text); + $text = preg_replace_callback('/<(pre)>(.*?)<\/pre>/ism', [self::class, 'encode'], $text); + $text = preg_replace_callback('/<(code)>(.*?)<\/code>/ism', [self::class, 'encode'], $text); if ($no_images) { $cleaned = ['texts' => [], 'icons' => []]; @@ -233,11 +233,11 @@ class Smilies $smilies = $cleaned; } - $text = preg_replace_callback('/<(3+)/', 'self::heartReplaceCallback', $text); + $text = preg_replace_callback('/<(3+)/', [self::class, 'heartReplaceCallback'], $text); $text = self::strOrigReplace($smilies['texts'], $smilies['icons'], $text); - $text = preg_replace_callback('/<(code)>(.*?)<\/code>/ism', 'self::decode', $text); - $text = preg_replace_callback('/<(pre)>(.*?)<\/pre>/ism', 'self::decode', $text); + $text = preg_replace_callback('/<(code)>(.*?)<\/code>/ism', [self::class, 'decode'], $text); + $text = preg_replace_callback('/<(pre)>(.*?)<\/pre>/ism', [self::class, 'decode'], $text); return $text; } diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index f65eeeee2c..e95ed06759 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -1415,8 +1415,8 @@ class BBCode public static function cleanPictureLinks(string $text): string { DI::profiler()->startRecording('rendering'); - $return = preg_replace_callback("&\[url=([^\[\]]*)\]\[img=(.*)\](.*)\[\/img\]\[\/url\]&Usi", 'self::cleanPictureLinksCallback', $text); - $return = preg_replace_callback("&\[url=([^\[\]]*)\]\[img\](.*)\[\/img\]\[\/url\]&Usi", 'self::cleanPictureLinksCallback', $return); + $return = preg_replace_callback("&\[url=([^\[\]]*)\]\[img=(.*)\](.*)\[\/img\]\[\/url\]&Usi", [self::class, 'cleanPictureLinksCallback'], $text); + $return = preg_replace_callback("&\[url=([^\[\]]*)\]\[img\](.*)\[\/img\]\[\/url\]&Usi", [self::class, 'cleanPictureLinksCallback'], $return); DI::profiler()->stopRecording(); return $return; } @@ -1450,7 +1450,7 @@ class BBCode { DI::profiler()->startRecording('rendering'); $regexp = "/([@!])\[url\=([^\[\]]*)\].*?\[\/url\]/ism"; - $body = preg_replace_callback($regexp, ['self', 'mentionCallback'], $body); + $body = preg_replace_callback($regexp, [self::class, 'mentionCallback'], $body); DI::profiler()->stopRecording(); return $body; } @@ -2002,12 +2002,12 @@ class BBCode if (!$for_plaintext) { if (in_array($simple_html, [self::OSTATUS, self::MASTODON_API, self::TWITTER_API, self::ACTIVITYPUB])) { - $text = preg_replace_callback("/\[url\](.*?)\[\/url\]/ism", 'self::convertUrlForActivityPubCallback', $text); - $text = preg_replace_callback("/\[url\=(.*?)\](.*?)\[\/url\]/ism", 'self::convertUrlForActivityPubCallback', $text); + $text = preg_replace_callback("/\[url\](.*?)\[\/url\]/ism", [self::class, 'convertUrlForActivityPubCallback'], $text); + $text = preg_replace_callback("/\[url\=(.*?)\](.*?)\[\/url\]/ism", [self::class, 'convertUrlForActivityPubCallback'], $text); } } else { $text = preg_replace("(\[url\](.*?)\[\/url\])ism", " $1 ", $text); - $text = preg_replace_callback("&\[url=([^\[\]]*)\]\[img\](.*)\[\/img\]\[\/url\]&Usi", 'self::removePictureLinksCallback', $text); + $text = preg_replace_callback("&\[url=([^\[\]]*)\]\[img\](.*)\[\/img\]\[\/url\]&Usi", [self::class, 'removePictureLinksCallback'], $text); } // Bookmarks in red - will be converted to bookmarks in friendica @@ -2017,7 +2017,7 @@ class BBCode "[bookmark=$1]$2[/bookmark]", $text); if (in_array($simple_html, [self::OSTATUS, self::TWITTER])) { - $text = preg_replace_callback("/([^#@!])\[url\=([^\]]*)\](.*?)\[\/url\]/ism", "self::expandLinksCallback", $text); + $text = preg_replace_callback("/([^#@!])\[url\=([^\]]*)\](.*?)\[\/url\]/ism", [self::class, 'expandLinksCallback'], $text); //$text = preg_replace("/[^#@!]\[url\=([^\]]*)\](.*?)\[\/url\]/ism", ' $2 [url]$1[/url]', $text); $text = preg_replace("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism", ' $2 [url]$1[/url]', $text); } @@ -2327,7 +2327,7 @@ class BBCode $url_search_string = "^\[\]"; $text = preg_replace_callback( "/([@!])\[(.*?)\]\(([$url_search_string]*?)\)/ism", - ['self', 'bbCodeMention2DiasporaCallback'], + [self::class, 'bbCodeMention2DiasporaCallback'], $text ); } diff --git a/src/Content/Text/HTML.php b/src/Content/Text/HTML.php index c65e1d9820..f9f340135c 100644 --- a/src/Content/Text/HTML.php +++ b/src/Content/Text/HTML.php @@ -1032,7 +1032,7 @@ class HTML // the quotes, e.g.: // // concat("'foo'", '"', "bar") - return 'concat(' . implode(', \'"\', ', array_map(['self', 'xpathQuote'], explode('"', $value))) . ')'; + return 'concat(' . implode(', \'"\', ', array_map([self::class, 'xpathQuote'], explode('"', $value))) . ')'; } /** diff --git a/src/Content/Widget/TagCloud.php b/src/Content/Widget/TagCloud.php index 6f146f4ac1..53d332f0a8 100644 --- a/src/Content/Widget/TagCloud.php +++ b/src/Content/Widget/TagCloud.php @@ -144,7 +144,7 @@ class TagCloud $x ++; } - usort($tags, 'self::tagsSort'); + usort($tags, [self::class, 'tagsSort']); $range = max(0.01, $max - $min) * 1.0001; for ($x = 0; $x < count($tags); $x ++) { diff --git a/src/Core/Config/Util/ConfigFileTransformer.php b/src/Core/Config/Util/ConfigFileTransformer.php index 45e7a5522b..f159721644 100644 --- a/src/Core/Config/Util/ConfigFileTransformer.php +++ b/src/Core/Config/Util/ConfigFileTransformer.php @@ -214,6 +214,17 @@ class ConfigFileTransformer case "NULL": return "null"; case "object": + if (method_exists($value, '__toString')) { + return sprintf('\'%s\'', $value); + } elseif ($value instanceof \Serializable) { + try { + return $value->serialize(); + } catch (\Exception $e) { + throw new \InvalidArgumentException(sprintf('Cannot serialize %s.', gettype($value)), $e); + } + } else { + throw new \InvalidArgumentException(sprintf('%s is an object without stringify.', gettype($value))); + } case "resource": case "resource (closed)": throw new \InvalidArgumentException(sprintf('%s in configs are not supported yet.', gettype($value))); diff --git a/src/Core/Hooks/Capabilities/IAmAStrategy.php b/src/Core/Hooks/Capabilities/IAmAStrategy.php new file mode 100644 index 0000000000..017cb56c4e --- /dev/null +++ b/src/Core/Hooks/Capabilities/IAmAStrategy.php @@ -0,0 +1,29 @@ +. + * + */ + +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/ICanManageInstances.php b/src/Core/Hooks/Capabilities/ICanManageInstances.php new file mode 100644 index 0000000000..bdad1b9235 --- /dev/null +++ b/src/Core/Hooks/Capabilities/ICanManageInstances.php @@ -0,0 +1,81 @@ +. + * + */ + +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/Exceptions/HookInstanceException.php b/src/Core/Hooks/Exceptions/HookInstanceException.php new file mode 100644 index 0000000000..bda8e7c8fb --- /dev/null +++ b/src/Core/Hooks/Exceptions/HookInstanceException.php @@ -0,0 +1,30 @@ +. + * + */ + +namespace Friendica\Core\Hooks\Exceptions; + +class HookInstanceException extends \RuntimeException +{ + public function __construct($message = "", \Throwable $previous = null) + { + parent::__construct($message, 500, $previous); + } +} diff --git a/src/Core/Hooks/Exceptions/HookRegisterArgumentException.php b/src/Core/Hooks/Exceptions/HookRegisterArgumentException.php new file mode 100644 index 0000000000..799c4294be --- /dev/null +++ b/src/Core/Hooks/Exceptions/HookRegisterArgumentException.php @@ -0,0 +1,30 @@ +. + * + */ + +namespace Friendica\Core\Hooks\Exceptions; + +class HookRegisterArgumentException extends \RuntimeException +{ + public function __construct($message = "", \Throwable $previous = null) + { + parent::__construct($message, 500, $previous); + } +} diff --git a/src/Core/Hooks/Model/InstanceManager.php b/src/Core/Hooks/Model/InstanceManager.php new file mode 100644 index 0000000000..7bfcfa420d --- /dev/null +++ b/src/Core/Hooks/Model/InstanceManager.php @@ -0,0 +1,104 @@ +. + * + */ + +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/Logger/Exception/LoggerInvalidException.php b/src/Core/Logger/Exception/LoggerInvalidException.php new file mode 100644 index 0000000000..db6ecb78c5 --- /dev/null +++ b/src/Core/Logger/Exception/LoggerInvalidException.php @@ -0,0 +1,32 @@ +. + * + */ + +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/Factory/Logger.php b/src/Core/Logger/Factory/Logger.php index 3dd2a81dc2..2821a813c2 100644 --- a/src/Core/Logger/Factory/Logger.php +++ b/src/Core/Logger/Factory/Logger.php @@ -22,16 +22,11 @@ namespace Friendica\Core\Logger\Factory; use Friendica\Core\Config\Capability\IManageConfigValues; -use Friendica\Core; -use Friendica\Core\Logger\Capabilities\IHaveCallIntrospections; +use Friendica\Core\Hooks\Capabilities\ICanManageInstances; use Friendica\Core\Logger\Exception\LogLevelException; -use Friendica\Database\Database; -use Friendica\Network\HTTPException\InternalServerErrorException; -use Friendica\Util\FileSystem; use Friendica\Core\Logger\Type\ProfilerLogger; use Friendica\Core\Logger\Type\StreamLogger; use Friendica\Core\Logger\Type\SyslogLogger; -use Friendica\Util\Profiler; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; use Psr\Log\NullLogger; @@ -44,115 +39,55 @@ class Logger const DEV_CHANNEL = 'dev'; /** @var string The log-channel (app, worker, ...) */ - private $channel; + protected $channel; + /** @var ICanManageInstances */ + protected $instanceManager; + /** @var IManageConfigValues */ + protected $config; - public function __construct(string $channel, bool $includeAddon = true) + public function __construct(string $channel, ICanManageInstances $instanceManager, IManageConfigValues $config, string $logfile = null) { - $this->channel = $channel; + $this->channel = $channel; + $this->instanceManager = $instanceManager; + $this->config = $config; - /// @fixme clean solution = Making Addon & Hook dynamic and load them inside the constructor, so there's no custom load logic necessary anymore - if ($includeAddon) { - Core\Addon::loadAddons(); - Core\Hook::loadHooks(); + $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); } } /** * Creates a new PSR-3 compliant logger instances * - * @param Database $database The Friendica Database instance - * @param IManageConfigValues $config The config - * @param Profiler $profiler The profiler of the app - * @param FileSystem $fileSystem FileSystem utils - * @param string|null $minLevel (optional) Override minimum Loglevel to log + * @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(Database $database, IManageConfigValues $config, Profiler $profiler, FileSystem $fileSystem, IHaveCallIntrospections $introspection, ?string $minLevel = null): LoggerInterface + public function create(string $loglevel = null): LoggerInterface { - if (empty($config->get('system', 'debugging', false))) { - $logger = new NullLogger(); - $database->setLogger($logger); + if (empty($this->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'; + + 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) { + // No logger ... + return new NullLogger(); } - - $minLevel = $minLevel ?? $config->get('system', 'loglevel'); - $loglevel = self::mapLegacyConfigDebugLevel((string)$minLevel); - - $name = $config->get('system', 'logger_config', 'stream'); - - switch ($name) { - case 'syslog': - try { - $logger = new SyslogLogger($this->channel, $introspection, $loglevel, $config->get('system', 'syslog_flags', SyslogLogger::DEFAULT_FLAGS), $config->get('system', 'syslog_facility', SyslogLogger::DEFAULT_FACILITY)); - } catch (LogLevelException $exception) { - // If there's a wrong config value for loglevel, try again with standard - $logger = $this->create($database, $config, $profiler, $fileSystem, $introspection, LogLevel::NOTICE); - $logger->warning('Invalid loglevel set in config.', ['loglevel' => $loglevel]); - } catch (\Throwable $e) { - // No logger ... - $logger = new NullLogger(); - } - break; - - case 'stream': - default: - $data = [ - 'name' => $name, - 'channel' => $this->channel, - 'introspection' => $introspection, - 'loglevel' => $loglevel, - 'logger' => null, - ]; - try { - Core\Hook::callAll('logger_instance', $data); - } catch (InternalServerErrorException $exception) { - $data['logger'] = null; - } - - if (($data['logger'] ?? null) instanceof LoggerInterface) { - $logger = $data['logger']; - } - - if (empty($logger)) { - $stream = $config->get('system', 'logfile'); - // just add a stream in case it's either writable or not file - if (!is_file($stream) || is_writable($stream)) { - try { - $logger = new StreamLogger($this->channel, $stream, $introspection, $fileSystem, $loglevel); - } catch (LogLevelException $exception) { - // If there's a wrong config value for loglevel, try again with standard - $logger = $this->create($database, $config, $profiler, $fileSystem, $introspection, LogLevel::NOTICE); - $logger->warning('Invalid loglevel set in config.', ['loglevel' => $loglevel]); - } catch (\Throwable $t) { - // No logger ... - $logger = new NullLogger(); - } - } else { - try { - $logger = new SyslogLogger($this->channel, $introspection, $loglevel); - } catch (LogLevelException $exception) { - // If there's a wrong config value for loglevel, try again with standard - $logger = $this->create($database, $config, $profiler, $fileSystem, $introspection, LogLevel::NOTICE); - $logger->warning('Invalid loglevel set in config.', ['loglevel' => $loglevel]); - } catch (\Throwable $e) { - // No logger ... - $logger = new NullLogger(); - } - } - } - break; - } - - $profiling = $config->get('system', 'profiling', false); - - // In case profiling is enabled, wrap the ProfilerLogger around the current logger - if (isset($profiling) && $profiling !== false) { - $logger = new ProfilerLogger($logger, $profiler); - } - - $database->setLogger($logger); - return $logger; } /** @@ -163,63 +98,24 @@ class Logger * * It should never get filled during normal usage of Friendica * - * @param IManageConfigValues $config The config - * @param Profiler $profiler The profiler of the app - * @param FileSystem $fileSystem FileSystem utils - * * @return LoggerInterface The PSR-3 compliant logger instance * @throws \Exception */ - public static function createDev(IManageConfigValues $config, Profiler $profiler, FileSystem $fileSystem, IHaveCallIntrospections $introspection) + public function createDev() { - $debugging = $config->get('system', 'debugging'); - $stream = $config->get('system', 'dlogfile'); - $developerIp = $config->get('system', 'dlogip'); + $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 = $config->get('system', 'logger_config', 'stream'); + $name = $this->config->get('system', 'logger_config') ?? 'stream'; - switch ($name) { - - case 'syslog': - $logger = new SyslogLogger(self::DEV_CHANNEL, $introspection, LogLevel::DEBUG); - break; - - case 'stream': - default: - $data = [ - 'name' => $name, - 'channel' => self::DEV_CHANNEL, - 'introspection' => $introspection, - 'loglevel' => LogLevel::DEBUG, - 'logger' => null, - ]; - try { - Core\Hook::callAll('logger_instance', $data); - } catch (InternalServerErrorException $exception) { - $data['logger'] = null; - } - - if (($data['logger'] ?? null) instanceof LoggerInterface) { - return $data['logger']; - } - - $logger = new StreamLogger(self::DEV_CHANNEL, $stream, $introspection, $fileSystem, LogLevel::DEBUG); - break; - } - - $profiling = $config->get('system', 'profiling', false); - - // In case profiling is enabled, wrap the ProfilerLogger around the current logger - if (isset($profiling) && $profiling !== false) { - $logger = new ProfilerLogger($logger, $profiler); - } - - return $logger; + /** @var LoggerInterface */ + return $this->instanceManager->getInstance(LoggerInterface::class, $name, [self::DEV_CHANNEL, LogLevel::DEBUG, $stream]); } /** diff --git a/src/Core/Logger/Type/AbstractLogger.php b/src/Core/Logger/Type/AbstractLogger.php index bc4b00ecea..77a61e9206 100644 --- a/src/Core/Logger/Type/AbstractLogger.php +++ b/src/Core/Logger/Type/AbstractLogger.php @@ -21,8 +21,8 @@ namespace Friendica\Core\Logger\Type; +use Friendica\Core\Logger\Capabilities\IHaveCallIntrospections; use Friendica\Core\Logger\Exception\LoggerException; -use Friendica\Core\Logger\Util\Introspection; use Friendica\Util\Strings; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; @@ -46,7 +46,7 @@ abstract class AbstractLogger implements LoggerInterface /** * The Introspection for the current call - * @var Introspection + * @var IHaveCallIntrospections */ protected $introspection; @@ -69,11 +69,11 @@ abstract class AbstractLogger implements LoggerInterface /** * @param string $channel The output channel - * @param Introspection $introspection The introspection of the current call + * @param IHaveCallIntrospections $introspection The introspection of the current call * * @throws LoggerException */ - public function __construct(string $channel, Introspection $introspection) + public function __construct(string $channel, IHaveCallIntrospections $introspection) { $this->channel = $channel; $this->introspection = $introspection; diff --git a/src/Core/Logger/Type/StreamLogger.php b/src/Core/Logger/Type/StreamLogger.php index a444faaaba..6e0f657978 100644 --- a/src/Core/Logger/Type/StreamLogger.php +++ b/src/Core/Logger/Type/StreamLogger.php @@ -21,18 +21,20 @@ 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 Friendica\Core\Logger\Util\Introspection; use Psr\Log\LogLevel; /** * A Logger instance for logging into a stream (file, stdout, stderr) */ -class StreamLogger extends AbstractLogger +class StreamLogger extends AbstractLogger implements IAmAStrategy { /** * The minimum loglevel at which this logger will be triggered @@ -80,16 +82,20 @@ class StreamLogger extends AbstractLogger /** * {@inheritdoc} - * @param string|resource $stream The stream to write with this logger (either a file or a stream, i.e. stdout) * @param string $level The minimum loglevel at which this logger will be triggered * * @throws LoggerArgumentException * @throws LogLevelException */ - public function __construct($channel, $stream, Introspection $introspection, FileSystem $fileSystem, string $level = LogLevel::DEBUG) + public function __construct(string $channel, IManageConfigValues $config, IHaveCallIntrospections $introspection, FileSystem $fileSystem, string $level = LogLevel::DEBUG) { $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)) { diff --git a/src/Core/Logger/Type/SyslogLogger.php b/src/Core/Logger/Type/SyslogLogger.php index b38cb01855..3c9ab581a0 100644 --- a/src/Core/Logger/Type/SyslogLogger.php +++ b/src/Core/Logger/Type/SyslogLogger.php @@ -21,16 +21,18 @@ 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; -use Friendica\Core\Logger\Util\Introspection; 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 +class SyslogLogger extends AbstractLogger implements IAmAStrategy { const IDENT = 'Friendica'; @@ -100,17 +102,16 @@ class SyslogLogger extends AbstractLogger /** * {@inheritdoc} * @param string $level The minimum loglevel at which this logger will be triggered - * @param int $logOpts Indicates what logging options will be used when generating a log message - * @param int $logFacility Used to specify what type of program is logging the message * * @throws LogLevelException * @throws LoggerException */ - public function __construct($channel, Introspection $introspection, string $level = LogLevel::NOTICE, int $logOpts = self::DEFAULT_FLAGS, int $logFacility = self::DEFAULT_FACILITY ) + public function __construct(string $channel, IManageConfigValues $config, IHaveCallIntrospections $introspection, string $level = LogLevel::NOTICE) { parent::__construct($channel, $introspection); - $this->logOpts = $logOpts; - $this->logFacility = $logFacility; + + $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]); } diff --git a/src/Database/DBA.php b/src/Database/DBA.php index ffeecfaa71..e29cd30386 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -527,7 +527,7 @@ class DBA public static function buildTableString(array $tables): string { // Quote each entry - return implode(',', array_map(['self', 'quoteIdentifier'], $tables)); + return implode(',', array_map([self::class, 'quoteIdentifier'], $tables)); } /** @@ -717,7 +717,7 @@ class DBA { $groupby_string = ''; if (!empty($params['group_by'])) { - $groupby_string = " GROUP BY " . implode(', ', array_map(['self', 'quoteIdentifier'], $params['group_by'])); + $groupby_string = " GROUP BY " . implode(', ', array_map([self::class, 'quoteIdentifier'], $params['group_by'])); } $order_string = ''; diff --git a/src/Database/DBStructure.php b/src/Database/DBStructure.php index c0bd005d1e..579b9cdc11 100644 --- a/src/Database/DBStructure.php +++ b/src/Database/DBStructure.php @@ -783,7 +783,7 @@ class DBStructure } if (!DBA::exists('verb', ['id' => 0])) { - DBA::insert('verb', ['name' => '']); + DBA::insert('verb', ['name' => ''], Database::INSERT_IGNORE); $lastid = DBA::lastInsertId(); if ($lastid != 0) { DBA::update('verb', ['id' => 0], ['id' => $lastid]); @@ -819,7 +819,7 @@ class DBStructure } if (self::existsTable('contact') && !DBA::exists('contact', ['id' => 0])) { - DBA::insert('contact', ['nurl' => '']); + DBA::insert('contact', ['nurl' => ''], Database::INSERT_IGNORE); $lastid = DBA::lastInsertId(); if ($lastid != 0) { DBA::update('contact', ['id' => 0], ['id' => $lastid]); @@ -834,7 +834,7 @@ class DBStructure } if (self::existsTable('tag') && !DBA::exists('tag', ['id' => 0])) { - DBA::insert('tag', ['name' => '']); + DBA::insert('tag', ['name' => ''], Database::INSERT_IGNORE); $lastid = DBA::lastInsertId(); if ($lastid != 0) { DBA::update('tag', ['id' => 0], ['id' => $lastid]); @@ -850,7 +850,7 @@ class DBStructure if (self::existsTable('permissionset')) { if (!DBA::exists('permissionset', ['id' => 0])) { - DBA::insert('permissionset', ['allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '']); + DBA::insert('permissionset', ['allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => ''], Database::INSERT_IGNORE); $lastid = DBA::lastInsertId(); if ($lastid != 0) { DBA::update('permissionset', ['id' => 0], ['id' => $lastid]); @@ -878,7 +878,7 @@ class DBStructure } $fields = ['id' => $set['psid'], 'uid' => $set['uid'], 'allow_cid' => $permission, 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '']; - DBA::insert('permissionset', $fields); + DBA::insert('permissionset', $fields, Database::INSERT_IGNORE); } DBA::close($sets); } diff --git a/src/Database/Database.php b/src/Database/Database.php index 032a282030..a5fe7f978a 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -36,7 +36,6 @@ use PDO; use PDOException; use PDOStatement; use Psr\Log\LoggerInterface; -use Psr\Log\NullLogger; /** * This class is for the low level database stuff that does driver specific things. @@ -81,16 +80,14 @@ class Database /** @var ViewDefinition */ protected $viewDefinition; - public function __construct(IManageConfigValues $config, Profiler $profiler, DbaDefinition $dbaDefinition, ViewDefinition $viewDefinition) + public function __construct(IManageConfigValues $config, Profiler $profiler, DbaDefinition $dbaDefinition, ViewDefinition $viewDefinition, LoggerInterface $logger) { // We are storing these values for being able to perform a reconnect - $this->config = $config; - $this->profiler = $profiler; + $this->config = $config; + $this->profiler = $profiler; $this->dbaDefinition = $dbaDefinition; $this->viewDefinition = $viewDefinition; - - // Temporary NullLogger until we can fetch the logger class from the config - $this->logger = new NullLogger(); + $this->logger = $logger; $this->connect(); } @@ -196,21 +193,6 @@ class Database $this->testmode = $test; } - /** - * Sets the logger for DBA - * - * @note this is necessary because if we want to load the logger configuration - * from the DB, but there's an error, we would print out an exception. - * So the logger gets updated after the logger configuration can be retrieved - * from the database - * - * @param LoggerInterface $logger - */ - public function setLogger(LoggerInterface $logger) - { - $this->logger = $logger; - } - /** * Sets the profiler for DBA * diff --git a/src/Database/Definition/DbaDefinition.php b/src/Database/Definition/DbaDefinition.php index b65a7d30ed..1e597bd64b 100644 --- a/src/Database/Definition/DbaDefinition.php +++ b/src/Database/Definition/DbaDefinition.php @@ -87,6 +87,10 @@ class DbaDefinition $data[$field] = mb_substr($data[$field], 0, $result[1]); } elseif (is_string($data[$field]) && preg_match("/binary\((\d*)\)/", $definition[$table]['fields'][$field]['type'], $result)) { $data[$field] = substr($data[$field], 0, $result[1]); + } elseif (is_numeric($data[$field]) && $definition[$table]['fields'][$field]['type'] === 'int') { + $data[$field] = min(max((int)$data[$field], -2147483648), 2147483647); + } elseif (is_numeric($data[$field]) && $definition[$table]['fields'][$field]['type'] === 'int unsigned') { + $data[$field] = min(max((int)$data[$field], 0), 4294967295); } $fields[$field] = $data[$field]; } diff --git a/src/Model/Contact.php b/src/Model/Contact.php index e847ce0346..7b5a1e428a 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -243,15 +243,13 @@ class Contact * @throws \Exception * @todo Let's get rid of boolean type of $old_fields */ - public static function update(array $fields, array $condition, $old_fields = []) + public static function update(array $fields, array $condition, $old_fields = []): bool { - $fields = DI::dbaDefinition()->truncateFieldsForTable('contact', $fields); - $ret = DBA::update('contact', $fields, $condition, $old_fields); - // Apply changes to the "user-contact" table on dedicated fields Contact\User::updateByContactUpdate($fields, $condition); - return $ret; + $fields = DI::dbaDefinition()->truncateFieldsForTable('contact', $fields); + return DBA::update('contact', $fields, $condition, $old_fields); } /** @@ -2970,7 +2968,7 @@ class Contact } // check if we already have a contact - $condition = ['uid' => $uid, 'nurl' => Strings::normaliseLink($ret['url'])]; + $condition = ['uid' => $uid, 'nurl' => Strings::normaliseLink($ret['url']), 'deleted' => false]; $contact = DBA::selectFirst('contact', ['id', 'rel', 'url', 'pending', 'hub-verify'], $condition); $protocol = self::getProtocol($ret['url'], $ret['network']); @@ -3293,7 +3291,7 @@ class Contact if ($contact['rel'] == self::SHARING || in_array($contact['network'], [Protocol::FEED, Protocol::MAIL])) { self::remove($contact['id']); } else { - self::update(['rel' => self::FOLLOWER], ['id' => $contact['id']]); + self::update(['rel' => self::FOLLOWER, 'pending' => false], ['id' => $contact['id']]); } Worker::add(Worker::PRIORITY_LOW, 'ContactDiscoveryForUser', $contact['uid']); diff --git a/src/Model/Event.php b/src/Model/Event.php index ca22c32ac6..e39ee5fd56 100644 --- a/src/Model/Event.php +++ b/src/Model/Event.php @@ -198,7 +198,7 @@ class Event public static function sortByDate(array $event_list): array { - usort($event_list, ['self', 'compareDatesCallback']); + usort($event_list, [self::class, 'compareDatesCallback']); return $event_list; } diff --git a/src/Model/GServer.php b/src/Model/GServer.php index 54e4d7220e..7e3f0f4802 100644 --- a/src/Model/GServer.php +++ b/src/Model/GServer.php @@ -455,22 +455,26 @@ class GServer * Set failed server status * * @param string $url + * @return void */ public static function setFailureByUrl(string $url) { - $gserver = DBA::selectFirst('gserver', [], ['nurl' => Strings::normaliseLink($url)]); + $nurl = Strings::normaliseLink($url); + + $gserver = DBA::selectFirst('gserver', [], ['nurl' => $nurl]); if (DBA::isResult($gserver)) { $next_update = self::getNextUpdateDate(false, $gserver['created'], $gserver['last_contact']); self::update(['url' => $url, 'failed' => true, 'blocked' => Network::isUrlBlocked($url), 'last_failure' => DateTimeFormat::utcNow(), 'next_contact' => $next_update, 'network' => Protocol::PHANTOM, 'detection-method' => null], - ['nurl' => Strings::normaliseLink($url)]); + ['nurl' => $nurl]); Logger::info('Set failed status for existing server', ['url' => $url]); if (self::isDefunct($gserver)) { self::archiveContacts($gserver['id']); } return; } - self::insert(['url' => $url, 'nurl' => Strings::normaliseLink($url), + + self::insert(['url' => $url, 'nurl' => $nurl, 'network' => Protocol::PHANTOM, 'created' => DateTimeFormat::utcNow(), 'failed' => true, 'last_failure' => DateTimeFormat::utcNow()]); Logger::info('Set failed status for new server', ['url' => $url]); @@ -556,7 +560,7 @@ class GServer // If the URL missmatches, then we mark the old entry as failure if (!Strings::compareLink($url, $original_url)) { self::setFailureByUrl($original_url); - if (!self::getID($url, true)) { + if (!self::getID($url, true) && !Network::isUrlBlocked($url)) { self::detect($url, $network, $only_nodeinfo); } return false; @@ -577,7 +581,7 @@ class GServer (((parse_url($url, PHP_URL_HOST) != parse_url($valid_url, PHP_URL_HOST)) || (parse_url($url, PHP_URL_PATH) != parse_url($valid_url, PHP_URL_PATH))) && empty(parse_url($valid_url, PHP_URL_PATH)))) { Logger::debug('Found redirect. Mark old entry as failure', ['old' => $url, 'new' => $valid_url]); self::setFailureByUrl($url); - if (!self::getID($valid_url, true)) { + if (!self::getID($valid_url, true) && !Network::isUrlBlocked($valid_url)) { self::detect($valid_url, $network, $only_nodeinfo); } return false; @@ -591,7 +595,7 @@ class GServer $valid_url = (string)Uri::fromParts($parts); self::setFailureByUrl($url); - if (!self::getID($valid_url, true)) { + if (!self::getID($valid_url, true) && !Network::isUrlBlocked($valid_url)) { self::detect($valid_url, $network, $only_nodeinfo); } return false; diff --git a/src/Model/Nodeinfo.php b/src/Model/Nodeinfo.php index 0fbaf93c7e..07f56dd7bb 100644 --- a/src/Model/Nodeinfo.php +++ b/src/Model/Nodeinfo.php @@ -55,17 +55,17 @@ class Nodeinfo $userStats = User::getStatistics(); - $config->set('nodeinfo', 'total_users', $userStats['total_users']); - $config->set('nodeinfo', 'active_users_halfyear', $userStats['active_users_halfyear']); - $config->set('nodeinfo', 'active_users_monthly', $userStats['active_users_monthly']); - $config->set('nodeinfo', 'active_users_weekly', $userStats['active_users_weekly']); + DI::keyValue()->set('nodeinfo_total_users', $userStats['total_users']); + DI::keyValue()->set('nodeinfo_active_users_halfyear', $userStats['active_users_halfyear']); + DI::keyValue()->set('nodeinfo_active_users_monthly', $userStats['active_users_monthly']); + DI::keyValue()->set('nodeinfo_active_users_weekly', $userStats['active_users_weekly']); $logger->info('user statistics', $userStats); $posts = DBA::count('post-thread', ["`uri-id` IN (SELECT `uri-id` FROM `post-user` WHERE NOT `deleted` AND `origin`)"]); $comments = DBA::count('post', ["NOT `deleted` AND `gravity` = ? AND `uri-id` IN (SELECT `uri-id` FROM `post-user` WHERE `origin`)", Item::GRAVITY_COMMENT]); - $config->set('nodeinfo', 'local_posts', $posts); - $config->set('nodeinfo', 'local_comments', $comments); + DI::keyValue()->set('nodeinfo_local_posts', $posts); + DI::keyValue()->set('nodeinfo_local_comments', $comments); $logger->info('User actitivy', ['posts' => $posts, 'comments' => $comments]); } @@ -83,14 +83,14 @@ class Nodeinfo $usage->users = new \stdClass; if (!empty($config->get('system', 'nodeinfo'))) { - $usage->users->total = intval($config->get('nodeinfo', 'total_users')); - $usage->users->activeHalfyear = intval($config->get('nodeinfo', 'active_users_halfyear')); - $usage->users->activeMonth = intval($config->get('nodeinfo', 'active_users_monthly')); - $usage->localPosts = intval($config->get('nodeinfo', 'local_posts')); - $usage->localComments = intval($config->get('nodeinfo', 'local_comments')); + $usage->users->total = intval(DI::keyValue()->get('nodeinfo_total_users')); + $usage->users->activeHalfyear = intval(DI::keyValue()->get('nodeinfo_active_users_halfyear')); + $usage->users->activeMonth = intval(DI::keyValue()->get('nodeinfo_active_users_monthly')); + $usage->localPosts = intval(DI::keyValue()->get('nodeinfo_local_posts')); + $usage->localComments = intval(DI::keyValue()->get('nodeinfo_local_comments')); if ($version2) { - $usage->users->activeWeek = intval($config->get('nodeinfo', 'active_users_weekly')); + $usage->users->activeWeek = intval(DI::keyValue()->get('nodeinfo_active_users_weekly')); } } diff --git a/src/Model/User.php b/src/Model/User.php index bd7351f072..75b913250c 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -757,7 +757,7 @@ class User } /** - * Allowed characters are a-z, A-Z, 0-9 and special characters except white spaces, accentuated letters and colon (:). + * Allowed characters are a-z, A-Z, 0-9 and special characters except white spaces and accentuated letters. * * Password length is limited to 72 characters if the current default password hashing algorithm is Blowfish. * From the manual: "Using the PASSWORD_BCRYPT as the algorithm, will result in the password parameter being @@ -770,13 +770,13 @@ class User */ public static function getPasswordRegExp(string $delimiter = null): string { - $allowed_characters = '!"#$%&\'()*+,-./;<=>?@[\]^_`{|}~'; + $allowed_characters = ':!"#$%&\'()*+,-./;<=>?@[\]^_`{|}~'; if ($delimiter) { $allowed_characters = preg_quote($allowed_characters, $delimiter); } - return '^[a-zA-Z0-9' . $allowed_characters . ']' . (PASSWORD_DEFAULT !== PASSWORD_BCRYPT ? '{1,72}' : '+') . '$'; + return '^[a-zA-Z0-9' . $allowed_characters . ']' . (PASSWORD_DEFAULT === PASSWORD_BCRYPT ? '{1,72}' : '+') . '$'; } /** @@ -804,7 +804,7 @@ class User } if (!preg_match('/' . self::getPasswordRegExp('/') . '/', $password)) { - throw new Exception(DI::l10n()->t('The password can\'t contain accentuated letters, white spaces or colons (:)')); + throw new Exception(DI::l10n()->t("The password can't contain white spaces nor accentuated letters")); } return self::updatePasswordHashed($uid, self::hashPassword($password)); diff --git a/src/Module/Contact/Profile.php b/src/Module/Contact/Profile.php index 15eebd3603..e13fbd584c 100644 --- a/src/Module/Contact/Profile.php +++ b/src/Module/Contact/Profile.php @@ -197,7 +197,7 @@ class Profile extends BaseModule Contact\User::setIgnored($contact['id'], DI::userSession()->getLocalUserId(), true); $message = $this->t('Contact has been ignored'); } - + // @TODO: add $this->localRelationship->save($localRelationship); DI::sysmsg()->addInfo($message); } @@ -213,7 +213,7 @@ class Profile extends BaseModule Contact\User::setCollapsed($contact['id'], DI::userSession()->getLocalUserId(), true); $message = $this->t('Contact has been collapsed'); } - + // @TODO: add $this->localRelationship->save($localRelationship); DI::sysmsg()->addInfo($message); } @@ -239,9 +239,6 @@ class Profile extends BaseModule '$baseurl' => $this->baseUrl->get(true), ]); - $contact['blocked'] = Contact\User::isBlocked($contact['id'], DI::userSession()->getLocalUserId()); - $contact['readonly'] = Contact\User::isIgnored($contact['id'], DI::userSession()->getLocalUserId()); - switch ($localRelationship->rel) { case Contact::FRIEND: $relation_text = $this->t('You are mutual friends with %s', $contact['name']); break; case Contact::FOLLOWER: $relation_text = $this->t('You are sharing with %s', $contact['name']); break; @@ -361,16 +358,13 @@ class Profile extends BaseModule '$last_update' => $last_update, '$udnow' => $this->t('Update now'), '$contact_id' => $contact['id'], - '$block_text' => ($contact['blocked'] ? $this->t('Unblock') : $this->t('Block')), - '$ignore_text' => ($contact['readonly'] ? $this->t('Unignore') : $this->t('Ignore')), - '$insecure' => (in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::MAIL, Protocol::DIASPORA]) ? '' : $insecure), - '$info' => $localRelationship->info, - '$cinfo' => ['info', '', $localRelationship->info, ''], - '$blocked' => ($contact['blocked'] ? $this->t('Currently blocked') : ''), - '$ignored' => ($contact['readonly'] ? $this->t('Currently ignored') : ''), - '$collapsed' => (Contact\User::isCollapsed($contact['id'], DI::userSession()->getLocalUserId()) ? $this->t('Currently collapsed') : ''), + '$pending' => $localRelationship->pending ? $this->t('Awaiting connection acknowledge') : '', + '$blocked' => $localRelationship->blocked ? $this->t('Currently blocked') : '', + '$ignored' => $localRelationship->ignored ? $this->t('Currently ignored') : '', + '$collapsed' => $localRelationship->collapsed ? $this->t('Currently collapsed') : '', '$archived' => ($contact['archive'] ? $this->t('Currently archived') : ''), - '$pending' => ($contact['pending'] ? $this->t('Awaiting connection acknowledge') : ''), + '$insecure' => (in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::MAIL, Protocol::DIASPORA]) ? '' : $insecure), + '$cinfo' => ['info', '', $localRelationship->info, ''], '$hidden' => ['hidden', $this->t('Hide this contact from others'), $localRelationship->hidden, $this->t('Replies/likes to your public posts may still be visible')], '$notify_new_posts' => ['notify_new_posts', $this->t('Notification for new posts'), ($localRelationship->notifyNewPosts), $this->t('Send a notification of every new post of this contact')], '$fetch_further_information' => $fetch_further_information, diff --git a/src/Module/Maintenance.php b/src/Module/Maintenance.php index 412723db31..67f65b8e39 100644 --- a/src/Module/Maintenance.php +++ b/src/Module/Maintenance.php @@ -36,7 +36,7 @@ class Maintenance extends BaseModule { protected function content(array $request = []): string { - $reason = DI::config()->get('system', 'maintenance_reason'); + $reason = DI::config()->get('system', 'maintenance_reason') ?? ''; if ((substr(Strings::normaliseLink($reason), 0, 7) === 'http://') || (substr(Strings::normaliseLink($reason), 0, 8) === 'https://')) { diff --git a/src/Module/OAuth/Token.php b/src/Module/OAuth/Token.php index 2752c69a6d..21c18d47c6 100644 --- a/src/Module/OAuth/Token.php +++ b/src/Module/OAuth/Token.php @@ -61,7 +61,10 @@ class Token extends BaseApi } if (empty($request['client_id']) && substr($authorization, 0, 6) == 'Basic ') { - $datapair = explode(':', base64_decode(trim(substr($authorization, 6)))); + // Per RFC2617, usernames can't contain a colon but password can, + // so we cut on the first colon to obtain the username and the password + // @see https://www.rfc-editor.org/rfc/rfc2617#section-2 + $datapair = explode(':', base64_decode(trim(substr($authorization, 6))), 2); if (count($datapair) == 2) { $request['client_id'] = $datapair[0]; $request['client_secret'] = $datapair[1]; diff --git a/src/Module/Security/PasswordTooLong.php b/src/Module/Security/PasswordTooLong.php index 1934556b3f..53fafea41e 100644 --- a/src/Module/Security/PasswordTooLong.php +++ b/src/Module/Security/PasswordTooLong.php @@ -98,7 +98,7 @@ class PasswordTooLong extends \Friendica\BaseModule '$return_url' => $request['return_url'] ?? '', '$password_current' => ['password_current', $this->l10n->t('Current Password:'), '', $this->l10n->t('Your current password to confirm the changes'), 'required', 'autocomplete="off"'], - '$password' => ['password', $this->l10n->t('New Password:'), '', $this->l10n->t('Allowed characters are a-z, A-Z, 0-9 and special characters except white spaces, accentuated letters and colon (:).') . ' ' . $this->l10n->t('Password length is limited to 72 characters.'), 'required', 'autocomplete="off"', User::getPasswordRegExp()], + '$password' => ['password', $this->l10n->t('New Password:'), '', $this->l10n->t('Allowed characters are a-z, A-Z, 0-9 and special characters except white spaces and accentuated letters.') . ' ' . $this->l10n->t('Password length is limited to 72 characters.'), 'required', 'autocomplete="off"', User::getPasswordRegExp()], '$password_confirm' => ['password_confirm', $this->l10n->t('Confirm:'), '', '', 'required', 'autocomplete="off"'], ]); diff --git a/src/Module/Settings/Account.php b/src/Module/Settings/Account.php index df8d41519c..f8f65e7206 100644 --- a/src/Module/Settings/Account.php +++ b/src/Module/Settings/Account.php @@ -549,7 +549,7 @@ class Account extends BaseSettings $notify_type = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'notify_type'); - $passwordRules = DI::l10n()->t('Allowed characters are a-z, A-Z, 0-9 and special characters except white spaces, accentuated letters and colon (:).') + $passwordRules = DI::l10n()->t('Allowed characters are a-z, A-Z, 0-9 and special characters except white spaces and accentuated letters.') . (PASSWORD_DEFAULT === PASSWORD_BCRYPT ? ' ' . DI::l10n()->t('Password length is limited to 72 characters.') : ''); $tpl = Renderer::getMarkupTemplate('settings/account.tpl'); diff --git a/src/Module/Statistics.php b/src/Module/Statistics.php index 75d3e6432b..514f10bb73 100644 --- a/src/Module/Statistics.php +++ b/src/Module/Statistics.php @@ -25,6 +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\L10n; use Friendica\Core\System; use Friendica\Network\HTTPException\NotFoundException; @@ -35,13 +36,15 @@ class Statistics extends BaseModule { /** @var IManageConfigValues */ protected $config; - - public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, IManageConfigValues $config, Response $response, array $server, array $parameters = []) + /** @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); - $this->config = $config; - + $this->config = $config; + $this->keyValue = $keyValue; if (!$this->config->get("system", "nodeinfo")) { throw new NotFoundException(); } @@ -72,10 +75,10 @@ class Statistics extends BaseModule 'network' => App::PLATFORM, 'version' => App::VERSION . '-' . DB_UPDATE_VERSION, 'registrations_open' => $registration_open, - 'total_users' => $this->config->get('nodeinfo', 'total_users'), - 'active_users_halfyear' => $this->config->get('nodeinfo', 'active_users_halfyear'), - 'active_users_monthly' => $this->config->get('nodeinfo', 'active_users_monthly'), - 'local_posts' => $this->config->get('nodeinfo', 'local_posts'), + 'total_users' => $this->keyValue->get('nodeinfo_total_users'), + 'active_users_halfyear' => $this->keyValue->get('nodeinfo_active_users_halfyear'), + 'active_users_monthly' => $this->keyValue->get('nodeinfo_active_users_monthly'), + 'local_posts' => $this->keyValue->get('nodeinfo_local_posts'), 'services' => $services, ], $services); diff --git a/src/Navigation/Notifications/Repository/Notify.php b/src/Navigation/Notifications/Repository/Notify.php index 87671f7e6a..2d15dd85c1 100644 --- a/src/Navigation/Notifications/Repository/Notify.php +++ b/src/Navigation/Notifications/Repository/Notify.php @@ -614,7 +614,7 @@ class Notify extends BaseRepository $emailBuilder->setHeader('Message-ID', $message_id); $log_msg = "No previous notification found for this parent:\n" . - " parent: ${params['parent']}\n" . " uid : ${params['uid']}\n"; + " parent: {$params['parent']}\n" . " uid : {$params['uid']}\n"; $this->logger->info($log_msg); } else { // If not, just "follow" the thread. diff --git a/src/Network/HTTPClient/Client/HttpClient.php b/src/Network/HTTPClient/Client/HttpClient.php index 2ef704df1f..4ee0842150 100644 --- a/src/Network/HTTPClient/Client/HttpClient.php +++ b/src/Network/HTTPClient/Client/HttpClient.php @@ -69,6 +69,10 @@ class HttpClient implements ICanSendHttpRequests $this->logger->debug('Request start.', ['url' => $url, 'method' => $method]); $host = parse_url($url, PHP_URL_HOST); + if (empty($host)) { + throw new \InvalidArgumentException('Unable to retrieve the host in URL: ' . $url); + } + if(!filter_var($host, FILTER_VALIDATE_IP) && !@dns_get_record($host . '.', DNS_A + DNS_AAAA) && !gethostbyname($host)) { $this->logger->debug('URL cannot be resolved.', ['url' => $url, 'callstack' => System::callstack(20)]); $this->profiler->stopRecording(); diff --git a/src/Object/Api/Mastodon/Card.php b/src/Object/Api/Mastodon/Card.php index d9b7344561..c4d21f66a3 100644 --- a/src/Object/Api/Mastodon/Card.php +++ b/src/Object/Api/Mastodon/Card.php @@ -54,6 +54,8 @@ class Card extends BaseDataTransferObject protected $image; /** @var string */ protected $blurhash; + /** @var array */ + protected $history; /** * Creates a card record from an attachment array. diff --git a/src/Object/Api/Mastodon/Stats.php b/src/Object/Api/Mastodon/Stats.php index 1f08ab2ed7..335c82d431 100644 --- a/src/Object/Api/Mastodon/Stats.php +++ b/src/Object/Api/Mastodon/Stats.php @@ -25,7 +25,6 @@ use Friendica\BaseDataTransferObject; use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Protocol; use Friendica\Database\Database; -use Friendica\Database\DBA; use Friendica\DI; /** @@ -45,9 +44,9 @@ class Stats extends BaseDataTransferObject public function __construct(IManageConfigValues $config, Database $database) { if (!empty($config->get('system', 'nodeinfo'))) { - $this->user_count = intval($config->get('nodeinfo', 'total_users')); - $this->status_count = $config->get('nodeinfo', 'local_posts') + $config->get('nodeinfo', 'local_comments'); - $this->domain_count = $database->count('gserver', ["`network` in (?, ?) AND NOT `failed`", Protocol::DFRN, Protocol::ACTIVITYPUB]); + $this->user_count = intval(DI::keyValue()->get('nodeinfo_total_users')); + $this->status_count = DI::keyValue()->get('nodeinfo_local_posts') + DI::keyValue()->get('nodeinfo_local_comments'); + $this->domain_count = $database->count('gserver', ["`network` in (?, ?) AND NOT `failed` AND NOT `blocked`", Protocol::DFRN, Protocol::ACTIVITYPUB]); } } } diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 6e1180bca8..bcff0b53b1 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -1661,7 +1661,7 @@ class Transmitter * * } elseif (($type == 'Article') && empty($data['summary'])) { * $regexp = "/[@!]\[url\=([^\[\]]*)\].*?\[\/url\]/ism"; - * $summary = preg_replace_callback($regexp, ['self', 'mentionAddrCallback'], $body); + * $summary = preg_replace_callback($regexp, [self::class, 'mentionAddrCallback'], $body); * $data['summary'] = BBCode::toPlaintext(Plaintext::shorten(self::removePictures($summary), 1000)); * } */ diff --git a/src/Util/ParseUrl.php b/src/Util/ParseUrl.php index 9d19a4ebac..f1e96dedc3 100644 --- a/src/Util/ParseUrl.php +++ b/src/Util/ParseUrl.php @@ -646,7 +646,7 @@ class ParseUrl $arr_tags = str_getcsv($string); if (count($arr_tags)) { // add the # sign to every tag - array_walk($arr_tags, ['self', 'arrAddHashes']); + array_walk($arr_tags, [self::class, 'arrAddHashes']); return $arr_tags; } diff --git a/src/Util/Proxy.php b/src/Util/Proxy.php index 67a0becb04..7f3c946722 100644 --- a/src/Util/Proxy.php +++ b/src/Util/Proxy.php @@ -141,7 +141,7 @@ class Proxy { $html = str_replace(Strings::normaliseLink(DI::baseUrl()) . '/', DI::baseUrl() . '/', $html); - return preg_replace_callback('/(]*src *= *["\'])([^"\']+)(["\'][^>]*>)/siU', 'self::replaceUrl', $html); + return preg_replace_callback('/(]*src *= *["\'])([^"\']+)(["\'][^>]*>)/siU', [self::class, 'replaceUrl'], $html); } /** diff --git a/src/Worker/UpdateServerPeers.php b/src/Worker/UpdateServerPeers.php index 85a1b61bf6..4829b538cf 100644 --- a/src/Worker/UpdateServerPeers.php +++ b/src/Worker/UpdateServerPeers.php @@ -57,7 +57,7 @@ class UpdateServerPeers $total = 0; $added = 0; foreach ($peers as $peer) { - if (Network::isUrlBlocked('http://' . $peer)) { + if (Network::isUrlBlocked('https://' . $peer)) { // Ignore blocked systems as soon as possible in the loop to avoid being slowed down by tar pits continue; } diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index a6459f16ba..4329410b4a 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -55,7 +55,7 @@ use Friendica\Database\DBA; if (!defined('DB_UPDATE_VERSION')) { - define('DB_UPDATE_VERSION', 1511); + define('DB_UPDATE_VERSION', 1512); } return [ diff --git a/static/dependencies.config.php b/static/dependencies.config.php index 1836a44dd5..5b7a345685 100644 --- a/static/dependencies.config.php +++ b/static/dependencies.config.php @@ -37,6 +37,8 @@ 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\PConfig; use Friendica\Core\L10n; use Friendica\Core\Lock; @@ -76,6 +78,12 @@ return [ $_SERVER ] ], + ICanManageInstances::class => [ + 'instanceOf' => InstanceManager::class, + 'constructParams' => [ + [Dice::INSTANCE => Dice::SELF], + ], + ], Config\Util\ConfigFileManager::class => [ 'instanceOf' => Config\Factory\Config::class, 'call' => [ diff --git a/tests/Util/CreateDatabaseTrait.php b/tests/Util/CreateDatabaseTrait.php index 51f74c7a52..127d8da2f1 100644 --- a/tests/Util/CreateDatabaseTrait.php +++ b/tests/Util/CreateDatabaseTrait.php @@ -30,6 +30,7 @@ use Friendica\Database\Definition\ViewDefinition; use Friendica\Test\DatabaseTestTrait; use Friendica\Test\Util\Database\StaticDatabase; use Friendica\Util\Profiler; +use Psr\Log\NullLogger; trait CreateDatabaseTrait { @@ -45,7 +46,7 @@ trait CreateDatabaseTrait ], ])); - $database = new StaticDatabase($config, new Profiler($config), (new DbaDefinition($this->root->url()))->load(), (new ViewDefinition($this->root->url()))->load()); + $database = new StaticDatabase($config, new Profiler($config), (new DbaDefinition($this->root->url()))->load(), (new ViewDefinition($this->root->url()))->load(), new NullLogger()); $database->setTestmode(true); return $database; diff --git a/tests/Util/Hooks/InstanceMocks/FakeInstance.php b/tests/Util/Hooks/InstanceMocks/FakeInstance.php new file mode 100644 index 0000000000..ff99002f7c --- /dev/null +++ b/tests/Util/Hooks/InstanceMocks/FakeInstance.php @@ -0,0 +1,60 @@ +. + * + */ + +namespace Friendica\Test\Util\Hooks\InstanceMocks; + +use Friendica\Core\Hooks\Capabilities\IAmAStrategy; + +class FakeInstance implements IAmADecoratedInterface, IAmAStrategy +{ + protected $aText = null; + protected $cBool = null; + protected $bText = null; + + public function __construct(string $aText = null, bool $cBool = null, string $bText = null) + { + $this->aText = $aText; + $this->cBool = $cBool; + $this->bText = $bText; + } + + public function createSomething(string $aText, bool $cBool, string $bText): string + { + $this->aText = $aText; + $this->cBool = $cBool; + $this->bText = $bText; + } + + public function getAText(): ?string + { + return $this->aText; + } + + public function getBText(): ?string + { + return $this->bText; + } + + public function getCBool(): ?bool + { + return $this->cBool; + } +} diff --git a/tests/Util/Hooks/InstanceMocks/FakeInstanceDecorator.php b/tests/Util/Hooks/InstanceMocks/FakeInstanceDecorator.php new file mode 100644 index 0000000000..af4db96c44 --- /dev/null +++ b/tests/Util/Hooks/InstanceMocks/FakeInstanceDecorator.php @@ -0,0 +1,59 @@ +. + * + */ + +namespace Friendica\Test\Util\Hooks\InstanceMocks; + +class FakeInstanceDecorator implements IAmADecoratedInterface +{ + public static $countInstance = 0; + + /** @var IAmADecoratedInterface */ + protected $orig; + protected $prefix = ''; + + public function __construct(IAmADecoratedInterface $orig, string $prefix = '') + { + $this->orig = $orig; + $this->prefix = $prefix; + + self::$countInstance++; + } + + public function createSomething(string $aText, bool $cBool, string $bText): string + { + return $this->orig->createSomething($aText, $cBool, $bText); + } + + public function getAText(): ?string + { + return $this->prefix . $this->orig->getAText(); + } + + public function getBText(): ?string + { + return $this->prefix . $this->orig->getBText(); + } + + public function getCBool(): ?bool + { + return $this->prefix . $this->orig->getCBool(); + } +} diff --git a/tests/Util/Hooks/InstanceMocks/IAmADecoratedInterface.php b/tests/Util/Hooks/InstanceMocks/IAmADecoratedInterface.php new file mode 100644 index 0000000000..fe93aa998d --- /dev/null +++ b/tests/Util/Hooks/InstanceMocks/IAmADecoratedInterface.php @@ -0,0 +1,33 @@ +. + * + */ + +namespace Friendica\Test\Util\Hooks\InstanceMocks; + +interface IAmADecoratedInterface +{ + public function createSomething(string $aText, bool $cBool, string $bText): string; + + public function getAText(): ?string; + + public function getBText(): ?string; + + public function getCBool(): ?bool; +} diff --git a/tests/Util/SerializableObjectDouble.php b/tests/Util/SerializableObjectDouble.php new file mode 100644 index 0000000000..e159655012 --- /dev/null +++ b/tests/Util/SerializableObjectDouble.php @@ -0,0 +1,35 @@ +. + * + */ + +namespace Friendica\Test\Util; + +class SerializableObjectDouble implements \Serializable +{ + public function serialize() + { + return '\'serialized\''; + } + + public function unserialize($data) + { + return '\'unserialized\''; + } +} diff --git a/tests/datasets/config/transformer/object_valid.node.config.php b/tests/datasets/config/transformer/object_valid.node.config.php new file mode 100644 index 0000000000..bfe61f3c8d --- /dev/null +++ b/tests/datasets/config/transformer/object_valid.node.config.php @@ -0,0 +1,11 @@ + [ + 'toString' => new HiddenString('test'), + 'serializable' => new SerializableObjectDouble(), + ], +]; diff --git a/tests/functional/DependencyCheckTest.php b/tests/functional/DependencyCheckTest.php index 86724bf437..27e693295e 100644 --- a/tests/functional/DependencyCheckTest.php +++ b/tests/functional/DependencyCheckTest.php @@ -25,7 +25,6 @@ use Dice\Dice; use Friendica\App; use Friendica\Core\Cache\Capability\ICanCache; use Friendica\Core\Cache\Capability\ICanCacheInMemory; -use Friendica\Core\Config\Model\Config; use Friendica\Core\Config\ValueObject\Cache; use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Lock\Capability\ICanLock; @@ -33,7 +32,6 @@ use Friendica\Database\Database; use Friendica\Test\Util\VFSTrait; use Friendica\Util\BasePath; use Friendica\Core\Config\Util\ConfigFileManager; -use Friendica\Util\Profiler; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -53,7 +51,18 @@ class DependencyCheckTest extends TestCase $this->setUpVfsDir(); $this->dice = (new Dice()) - ->addRules(include __DIR__ . '/../../static/dependencies.config.php'); + ->addRules(include __DIR__ . '/../../static/dependencies.config.php') + ->addRule(BasePath::class, [ + 'constructParams' => [ + $this->root->url(), + [], + ], + ]) + ->addRule(LoggerInterface::class, ['constructParams' => ['test']]); + + /** @var IManageConfigValues $config */ + $config = $this->dice->create(IManageConfigValues::class); + $config->set('system', 'logfile', $this->root->url() . '/logs/friendica.log'); } /** @@ -142,7 +151,7 @@ class DependencyCheckTest extends TestCase public function testLogger() { /** @var LoggerInterface $logger */ - $logger = $this->dice->create(LoggerInterface::class, ['test']); + $logger = $this->dice->create(LoggerInterface::class, [['$channel' => 'test']]); self::assertInstanceOf(LoggerInterface::class, $logger); } @@ -154,7 +163,7 @@ class DependencyCheckTest extends TestCase $config->set('system', 'dlogfile', $this->root->url() . '/friendica.log'); /** @var LoggerInterface $logger */ - $logger = $this->dice->create('$devLogger', ['dev']); + $logger = $this->dice->create('$devLogger', [['$channel' => 'dev']]); self::assertInstanceOf(LoggerInterface::class, $logger); } @@ -164,6 +173,7 @@ class DependencyCheckTest extends TestCase /** @var ICanCache $cache */ $cache = $this->dice->create(ICanCache::class); + self::assertInstanceOf(ICanCache::class, $cache); } diff --git a/tests/src/Core/Cache/DatabaseCacheTest.php b/tests/src/Core/Cache/DatabaseCacheTest.php index e5f3359580..81804a806e 100644 --- a/tests/src/Core/Cache/DatabaseCacheTest.php +++ b/tests/src/Core/Cache/DatabaseCacheTest.php @@ -62,7 +62,7 @@ class DatabaseCacheTest extends CacheTest $dbaDefinition = (new DbaDefinition($configCache->get('system', 'basepath')))->load(); $viewDefinition = (new ViewDefinition($configCache->get('system', 'basepath')))->load(); - $dba = new StaticDatabase($config, $profiler, $dbaDefinition, $viewDefinition); + $dba = new StaticDatabase($config, $profiler, $dbaDefinition, $viewDefinition, new NullLogger()); $this->cache = new Cache\Type\DatabaseCache('database', $dba); return $this->cache; diff --git a/tests/src/Core/Config/Util/ConfigFileTransformerTest.php b/tests/src/Core/Config/Util/ConfigFileTransformerTest.php index bb156cf282..c11a770ad8 100644 --- a/tests/src/Core/Config/Util/ConfigFileTransformerTest.php +++ b/tests/src/Core/Config/Util/ConfigFileTransformerTest.php @@ -23,6 +23,9 @@ namespace Friendica\Test\src\Core\Config\Util; use Friendica\Core\Config\Util\ConfigFileTransformer; use Friendica\Test\MockedTest; +use Friendica\Test\Util\SerializableObjectDouble; +use ParagonIE\HiddenString\HiddenString; +use function PHPUnit\Framework\assertEquals; class ConfigFileTransformerTest extends MockedTest { @@ -45,9 +48,34 @@ class ConfigFileTransformerTest extends MockedTest 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/transformer/object.node.config.php'), 'assertException' => true, ], - 'ressource_invalid' => [ + 'resource' => [ 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/transformer/ressource.node.config.php'), - 'assertException' => true, + 'assertException' => false, + 'assertion' => << [ + 'ressources_not_allowed' => '', + ], +]; + +EOF, + ], + 'object_valid' => [ + 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/transformer/object_valid.node.config.php'), + 'assertException' => false, + 'assertion' => << [ + 'toString' => 'test', + 'serializable' => 'serialized', + ], +]; + +EOF, ], 'test_types' => [ 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/transformer/types.node.config.php'), @@ -63,7 +91,7 @@ class ConfigFileTransformerTest extends MockedTest * * @dataProvider dataTests */ - public function testConfigFile(string $configFile, bool $assertException = false) + public function testConfigFile(string $configFile, bool $assertException = false, $assertion = null) { $dataArray = include $configFile; @@ -73,6 +101,10 @@ class ConfigFileTransformerTest extends MockedTest $newConfig = ConfigFileTransformer::encode($dataArray); - self::assertEquals(file_get_contents($configFile), $newConfig); + if (empty($assertion)) { + self::assertEquals(file_get_contents($configFile), $newConfig); + } else { + self::assertEquals($assertion, $newConfig); + } } } diff --git a/tests/src/Core/Hooks/Model/InstanceManagerTest.php b/tests/src/Core/Hooks/Model/InstanceManagerTest.php new file mode 100644 index 0000000000..4e4c0135cb --- /dev/null +++ b/tests/src/Core/Hooks/Model/InstanceManagerTest.php @@ -0,0 +1,258 @@ +. + * + */ + +namespace Friendica\Test\src\Core\Hooks\Model; + +use Dice\Dice; +use Friendica\Core\Hooks\Model\InstanceManager; +use Friendica\Test\MockedTest; +use Friendica\Test\Util\Hooks\InstanceMocks\FakeInstance; +use Friendica\Test\Util\Hooks\InstanceMocks\FakeInstanceDecorator; +use Friendica\Test\Util\Hooks\InstanceMocks\IAmADecoratedInterface; + +class InstanceManagerTest extends MockedTest +{ + public function testEqualButNotSameInstance() + { + $instance = new InstanceManager(new Dice()); + + $instance->registerStrategy(IAmADecoratedInterface::class, 'fake', FakeInstance::class); + + $getInstanceA = $instance->getInstance(IAmADecoratedInterface::class, 'fake'); + $getInstanceB = $instance->getInstance(IAmADecoratedInterface::class, 'fake'); + + self::assertEquals($getInstanceA, $getInstanceB); + self::assertNotSame($getInstanceA, $getInstanceB); + } + + protected function tearDown(): void + { + FakeInstanceDecorator::$countInstance = 0; + + parent::tearDown(); + } + + public function dataTests(): array + { + return [ + 'only_a' => [ + 'aString' => 'test', + ], + 'a_b' => [ + 'aString' => 'test', + 'cBool' => false, + 'bString' => 'test23', + + ], + 'a_c' => [ + 'aString' => 'test', + 'cBool' => false, + 'bString' => null, + ], + 'a_b_c' => [ + 'aString' => 'test', + 'cBool' => false, + 'bString' => 'test23', + ], + 'null' => [], + ]; + } + + /** + * @dataProvider dataTests + */ + public function testInstanceWithConstructorAnonymArgs(string $aString = null, bool $cBool = null, string $bString = null) + { + $instance = new InstanceManager(new Dice()); + + $args = []; + + if (isset($aString)) { + $args[] = $aString; + } + if (isset($bString)) { + $args[] = $bString; + } + if (isset($cBool)) { + $args[] = $cBool; + } + + $instance->registerStrategy(IAmADecoratedInterface::class, 'fake', FakeInstance::class, $args); + + /** @var IAmADecoratedInterface $getInstanceA */ + $getInstanceA = $instance->getInstance(IAmADecoratedInterface::class, 'fake'); + /** @var IAmADecoratedInterface $getInstanceB */ + $getInstanceB = $instance->getInstance(IAmADecoratedInterface::class, 'fake'); + + self::assertEquals($getInstanceA, $getInstanceB); + self::assertNotSame($getInstanceA, $getInstanceB); + self::assertEquals($aString, $getInstanceA->getAText()); + self::assertEquals($aString, $getInstanceB->getAText()); + self::assertEquals($bString, $getInstanceA->getBText()); + self::assertEquals($bString, $getInstanceB->getBText()); + self::assertEquals($cBool, $getInstanceA->getCBool()); + self::assertEquals($cBool, $getInstanceB->getCBool()); + } + + /** + * @dataProvider dataTests + */ + public function testInstanceConstructorAndGetInstanceWithNamedArgs(string $aString = null, bool $cBool = null, string $bString = null) + { + $instance = new InstanceManager(new Dice()); + + $args = []; + + if (isset($aString)) { + $args[] = $aString; + } + if (isset($cBool)) { + $args[] = $cBool; + } + + $instance->registerStrategy(IAmADecoratedInterface::class, 'fake', FakeInstance::class, $args); + + /** @var IAmADecoratedInterface $getInstanceA */ + $getInstanceA = $instance->getInstance(IAmADecoratedInterface::class, 'fake', [$bString]); + /** @var IAmADecoratedInterface $getInstanceB */ + $getInstanceB = $instance->getInstance(IAmADecoratedInterface::class, 'fake', [$bString]); + + self::assertEquals($getInstanceA, $getInstanceB); + self::assertNotSame($getInstanceA, $getInstanceB); + self::assertEquals($aString, $getInstanceA->getAText()); + self::assertEquals($aString, $getInstanceB->getAText()); + self::assertEquals($bString, $getInstanceA->getBText()); + self::assertEquals($bString, $getInstanceB->getBText()); + self::assertEquals($cBool, $getInstanceA->getCBool()); + self::assertEquals($cBool, $getInstanceB->getCBool()); + } + + /** + * @dataProvider dataTests + */ + public function testInstanceWithTwoStrategies(string $aString = null, bool $cBool = null, string $bString = null) + { + $instance = new InstanceManager(new Dice()); + + $args = []; + + if (isset($aString)) { + $args[] = $aString; + } + if (isset($cBool)) { + $args[] = $cBool; + } + + $instance->registerStrategy(IAmADecoratedInterface::class, 'fake', FakeInstance::class, $args); + $instance->registerStrategy(IAmADecoratedInterface::class, 'fake23', FakeInstance::class, $args); + + /** @var IAmADecoratedInterface $getInstanceA */ + $getInstanceA = $instance->getInstance(IAmADecoratedInterface::class, 'fake', [$bString]); + /** @var IAmADecoratedInterface $getInstanceB */ + $getInstanceB = $instance->getInstance(IAmADecoratedInterface::class, 'fake23', [$bString]); + + self::assertEquals($getInstanceA, $getInstanceB); + self::assertNotSame($getInstanceA, $getInstanceB); + self::assertEquals($aString, $getInstanceA->getAText()); + self::assertEquals($aString, $getInstanceB->getAText()); + self::assertEquals($bString, $getInstanceA->getBText()); + self::assertEquals($bString, $getInstanceB->getBText()); + self::assertEquals($cBool, $getInstanceA->getCBool()); + self::assertEquals($cBool, $getInstanceB->getCBool()); + } + + /** + * @dataProvider dataTests + */ + public function testDecorator(string $aString = null, bool $cBool = null, string $bString = null) + { + $instance = new InstanceManager(new Dice()); + + $args = []; + + if (isset($aString)) { + $args[] = $aString; + } + if (isset($cBool)) { + $args[] = $cBool; + } + + $prefix = 'prefix1'; + + $instance->registerStrategy(IAmADecoratedInterface::class, 'fake', FakeInstance::class, $args); + $instance->registerStrategy(IAmADecoratedInterface::class, 'fake23', FakeInstance::class, $args); + $instance->registerDecorator(IAmADecoratedInterface::class, FakeInstanceDecorator::class, [$prefix]); + + /** @var IAmADecoratedInterface $getInstanceA */ + $getInstanceA = $instance->getInstance(IAmADecoratedInterface::class, 'fake', [$bString]); + /** @var IAmADecoratedInterface $getInstanceB */ + $getInstanceB = $instance->getInstance(IAmADecoratedInterface::class, 'fake23', [$bString]); + + self::assertEquals(2, FakeInstanceDecorator::$countInstance); + self::assertEquals($getInstanceA, $getInstanceB); + self::assertNotSame($getInstanceA, $getInstanceB); + self::assertEquals($prefix . $aString, $getInstanceA->getAText()); + self::assertEquals($prefix . $aString, $getInstanceB->getAText()); + self::assertEquals($prefix . $bString, $getInstanceA->getBText()); + self::assertEquals($prefix . $bString, $getInstanceB->getBText()); + self::assertEquals($prefix . $cBool, $getInstanceA->getCBool()); + self::assertEquals($prefix . $cBool, $getInstanceB->getCBool()); + } + + /** + * @dataProvider dataTests + */ + public function testTwoDecoratorWithPrefix(string $aString = null, bool $cBool = null, string $bString = null) + { + $instance = new InstanceManager(new Dice()); + + $args = []; + + if (isset($aString)) { + $args[] = $aString; + } + if (isset($cBool)) { + $args[] = $cBool; + } + + $prefix = 'prefix1'; + + $instance->registerStrategy(IAmADecoratedInterface::class, 'fake', FakeInstance::class, $args); + $instance->registerStrategy(IAmADecoratedInterface::class, 'fake23', FakeInstance::class, $args); + $instance->registerDecorator(IAmADecoratedInterface::class, FakeInstanceDecorator::class, [$prefix]); + $instance->registerDecorator(IAmADecoratedInterface::class, FakeInstanceDecorator::class); + + /** @var IAmADecoratedInterface $getInstanceA */ + $getInstanceA = $instance->getInstance(IAmADecoratedInterface::class, 'fake', [$bString]); + /** @var IAmADecoratedInterface $getInstanceB */ + $getInstanceB = $instance->getInstance(IAmADecoratedInterface::class, 'fake23', [$bString]); + + self::assertEquals(4, FakeInstanceDecorator::$countInstance); + self::assertEquals($getInstanceA, $getInstanceB); + self::assertNotSame($getInstanceA, $getInstanceB); + self::assertEquals($prefix . $aString, $getInstanceA->getAText()); + self::assertEquals($prefix . $aString, $getInstanceB->getAText()); + self::assertEquals($prefix . $bString, $getInstanceA->getBText()); + self::assertEquals($prefix . $bString, $getInstanceB->getBText()); + self::assertEquals($prefix . $cBool, $getInstanceA->getCBool()); + self::assertEquals($prefix . $cBool, $getInstanceB->getCBool()); + } +} diff --git a/tests/src/Core/Logger/AbstractLoggerTest.php b/tests/src/Core/Logger/AbstractLoggerTest.php index 3a5e0ecd11..4605f6f75a 100644 --- a/tests/src/Core/Logger/AbstractLoggerTest.php +++ b/tests/src/Core/Logger/AbstractLoggerTest.php @@ -21,6 +21,7 @@ namespace Friendica\Test\src\Core\Logger; +use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Test\MockedTest; use Friendica\Core\Logger\Util\Introspection; use Mockery\MockInterface; @@ -41,6 +42,10 @@ abstract class AbstractLoggerTest extends MockedTest * @var Introspection|MockInterface */ protected $introspection; + /** + * @var IManageConfigValues|MockInterface + */ + protected $config; /** * Returns the content of the current logger instance @@ -68,6 +73,8 @@ abstract class AbstractLoggerTest extends MockedTest 'line' => self::LINE, 'function' => self::FUNC ]); + + $this->config = \Mockery::mock(IManageConfigValues::class); } public function assertLogline($string) diff --git a/tests/src/Core/Logger/StreamLoggerTest.php b/tests/src/Core/Logger/StreamLoggerTest.php index a83a5c2e4e..1ddddf4c1b 100644 --- a/tests/src/Core/Logger/StreamLoggerTest.php +++ b/tests/src/Core/Logger/StreamLoggerTest.php @@ -62,7 +62,9 @@ class StreamLoggerTest extends AbstractLoggerTest $this->logfile = vfsStream::newFile('friendica.log') ->at($this->root); - $logger = new StreamLogger('test', $this->logfile->url(), $this->introspection, $this->fileSystem, $level); + $this->config->shouldReceive('get')->with('system', 'logfile')->andReturn($this->logfile->url())->once(); + + $logger = new StreamLogger('test', $this->config, $this->introspection, $this->fileSystem, $level); return $logger; } @@ -75,43 +77,6 @@ class StreamLoggerTest extends AbstractLoggerTest return $this->logfile->getContent(); } - /** - * Test if a stream is working - */ - public function testStream() - { - $logfile = vfsStream::newFile('friendica.log') - ->at($this->root); - - $filehandler = fopen($logfile->url(), 'ab'); - - $logger = new \Friendica\Core\Logger\Type\StreamLogger('test', $filehandler, $this->introspection, $this->fileSystem); - $logger->emergency('working'); - - $text = $logfile->getContent(); - - self::assertLogline($text); - } - - /** - * Test if the close statement is working - */ - public function testClose() - { - $logfile = vfsStream::newFile('friendica.log') - ->at($this->root); - - $logger = new StreamLogger('test', $logfile->url(), $this->introspection, $this->fileSystem); - $logger->emergency('working'); - $logger->close(); - // close doesn't affect - $logger->emergency('working too'); - - $text = $logfile->getContent(); - - self::assertLoglineNums(2, $text); - } - /** * Test when a file isn't set */ @@ -120,7 +85,9 @@ class StreamLoggerTest extends AbstractLoggerTest $this->expectException(LoggerArgumentException::class); $this->expectExceptionMessage("Missing stream URL."); - $logger = new StreamLogger('test', '', $this->introspection, $this->fileSystem); + $this->config->shouldReceive('get')->with('system', 'logfile')->andReturn('')->once(); + + $logger = new StreamLogger('test', $this->config, $this->introspection, $this->fileSystem); $logger->emergency('not working'); } @@ -130,13 +97,14 @@ class StreamLoggerTest extends AbstractLoggerTest */ public function testWrongUrl() { - $this->expectException(LoggerException::class); - $this->expectExceptionMessage("Cannot create stream."); + $this->expectException(LoggerArgumentException::class); $logfile = vfsStream::newFile('friendica.log') ->at($this->root)->chmod(0); - $logger = new StreamLogger('test', $logfile->url(), $this->introspection, $this->fileSystem); + $this->config->shouldReceive('get')->with('system', 'logfile')->andReturn($logfile->url())->once(); + + $logger = new StreamLogger('test', $this->config, $this->introspection, $this->fileSystem); $logger->emergency('not working'); } @@ -164,7 +132,9 @@ class StreamLoggerTest extends AbstractLoggerTest $this->expectException(LogLevelException::class); $this->expectExceptionMessageMatches("/The level \".*\" is not valid./"); - $logger = new StreamLogger('test', 'file.text', $this->introspection, $this->fileSystem, 'NOPE'); + $this->config->shouldReceive('get')->with('system', 'logfile')->andReturn('file.text')->once(); + + $logger = new StreamLogger('test', $this->config, $this->introspection, $this->fileSystem, 'NOPE'); } /** @@ -178,7 +148,9 @@ class StreamLoggerTest extends AbstractLoggerTest $logfile = vfsStream::newFile('friendica.log') ->at($this->root); - $logger = new StreamLogger('test', $logfile->url(), $this->introspection, $this->fileSystem); + $this->config->shouldReceive('get')->with('system', 'logfile')->andReturn($logfile->url())->once(); + + $logger = new StreamLogger('test', $this->config, $this->introspection, $this->fileSystem); $logger->log('NOPE', 'a test'); } @@ -191,7 +163,9 @@ class StreamLoggerTest extends AbstractLoggerTest $this->expectException(LoggerArgumentException::class); $this->expectExceptionMessage("A stream must either be a resource or a string."); - $logger = new StreamLogger('test', null, $this->introspection, $this->fileSystem); + $this->config->shouldReceive('get')->with('system', 'logfile')->andReturn(null)->once(); + + $logger = new StreamLogger('test', $this->config, $this->introspection, $this->fileSystem); } /** @@ -207,7 +181,9 @@ class StreamLoggerTest extends AbstractLoggerTest chdir($this->root->getChild('logs')->url()); - $logger = new StreamLogger('test', '../friendica.log' , $this->introspection, $this->fileSystem); + $this->config->shouldReceive('get')->with('system', 'logfile')->andReturn('../friendica.log')->once(); + + $logger = new StreamLogger('test', $this->config, $this->introspection, $this->fileSystem); $logger->info('Test'); } diff --git a/tests/src/Core/Logger/SyslogLoggerTest.php b/tests/src/Core/Logger/SyslogLoggerTest.php index 89f9d82e6c..53ace79c08 100644 --- a/tests/src/Core/Logger/SyslogLoggerTest.php +++ b/tests/src/Core/Logger/SyslogLoggerTest.php @@ -39,6 +39,10 @@ class SyslogLoggerTest extends AbstractLoggerTest parent::setUp(); $this->introspection->shouldReceive('addClasses')->with([SyslogLogger::class]); + $this->config->shouldReceive('get')->with('system', 'syslog_flags')->andReturn(SyslogLogger::DEFAULT_FLAGS) + ->once(); + $this->config->shouldReceive('get')->with('system', 'syslog_facility') + ->andReturn(SyslogLogger::DEFAULT_FACILITY)->once(); } /** @@ -54,7 +58,7 @@ class SyslogLoggerTest extends AbstractLoggerTest */ protected function getInstance($level = LogLevel::DEBUG) { - $this->logger = new SyslogLoggerWrapper('test', $this->introspection, $level); + $this->logger = new SyslogLoggerWrapper('test', $this->config, $this->introspection, $level); return $this->logger; } @@ -68,7 +72,7 @@ class SyslogLoggerTest extends AbstractLoggerTest $this->expectException(LogLevelException::class); $this->expectExceptionMessageMatches("/The level \".*\" is not valid./"); - $logger = new SyslogLoggerWrapper('test', $this->introspection, 'NOPE'); + $logger = new SyslogLoggerWrapper('test', $this->config, $this->introspection, 'NOPE'); } /** @@ -79,7 +83,7 @@ class SyslogLoggerTest extends AbstractLoggerTest $this->expectException(LogLevelException::class); $this->expectExceptionMessageMatches("/The level \".*\" is not valid./"); - $logger = new SyslogLoggerWrapper('test', $this->introspection); + $logger = new SyslogLoggerWrapper('test', $this->config, $this->introspection); $logger->log('NOPE', 'a test'); } @@ -90,7 +94,7 @@ class SyslogLoggerTest extends AbstractLoggerTest */ public function testClose() { - $logger = new SyslogLoggerWrapper('test', $this->introspection); + $logger = new SyslogLoggerWrapper('test', $this->config, $this->introspection); $logger->emergency('test'); $logger->close(); // Reopened itself diff --git a/tests/src/Core/Logger/SyslogLoggerWrapper.php b/tests/src/Core/Logger/SyslogLoggerWrapper.php index 634edc1195..9fd16706a8 100644 --- a/tests/src/Core/Logger/SyslogLoggerWrapper.php +++ b/tests/src/Core/Logger/SyslogLoggerWrapper.php @@ -21,6 +21,7 @@ namespace Friendica\Test\src\Core\Logger; +use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Logger\Type\SyslogLogger; use Friendica\Core\Logger\Util\Introspection; use Psr\Log\LogLevel; @@ -32,9 +33,9 @@ class SyslogLoggerWrapper extends SyslogLogger { private $content; - public function __construct($channel, Introspection $introspection, $level = LogLevel::NOTICE, $logOpts = LOG_PID, $logFacility = LOG_USER) + public function __construct($channel, IManageConfigValues $config, Introspection $introspection, $level = LogLevel::NOTICE) { - parent::__construct($channel, $introspection, $level, $logOpts, $logFacility); + parent::__construct($channel, $config, $introspection, $level); $this->content = ''; } diff --git a/tests/src/Util/BaseURLTest.php b/tests/src/Util/BaseURLTest.php index feda9a7c56..4095c344da 100644 --- a/tests/src/Util/BaseURLTest.php +++ b/tests/src/Util/BaseURLTest.php @@ -200,47 +200,6 @@ class BaseURLTest extends MockedTest ]; } - /** - * Test the default config determination - * @dataProvider dataDefault - */ - public function testCheck($server, $input, $assert) - { - $configMock = \Mockery::mock(IManageConfigValues::class); - $configMock->shouldReceive('get')->with('config', 'hostname')->andReturn($input['hostname']); - $configMock->shouldReceive('get')->with('system', 'urlpath')->andReturn($input['urlPath']); - $configMock->shouldReceive('get')->with('system', 'ssl_policy')->andReturn($input['sslPolicy']); - $configMock->shouldReceive('get')->with('system', 'url')->andReturn($input['url']); - - // If we don't have an urlPath as an input, we assert it, we will save it to the DB for the next time - if (!isset($input['urlPath']) && isset($assert['urlPath'])) { - $configMock->shouldReceive('set')->with('system', 'urlpath', $assert['urlPath'])->once(); - } - - // If we don't have the ssl_policy as an input, we assert it, we will save it to the DB for the next time - if (!isset($input['sslPolicy']) && isset($assert['sslPolicy'])) { - $configMock->shouldReceive('set')->with('system', 'ssl_policy', $assert['sslPolicy'])->once(); - } - - // If we don't have the hostname as an input, we assert it, we will save it to the DB for the next time - if (empty($input['hostname']) && !empty($assert['hostname'])) { - $configMock->shouldReceive('set')->with('config', 'hostname', $assert['hostname'])->once(); - } - - // If we don't have an URL at first, but we assert it, we will save it to the DB for the next time - if (empty($input['url']) && !empty($assert['url'])) { - $configMock->shouldReceive('set')->with('system', 'url', $assert['url'])->once(); - } - - $baseUrl = new BaseURL($configMock, $server); - - self::assertEquals($assert['hostname'], $baseUrl->getHostname()); - self::assertEquals($assert['urlPath'], $baseUrl->getUrlPath()); - self::assertEquals($assert['sslPolicy'], $baseUrl->getSSLPolicy()); - self::assertEquals($assert['scheme'], $baseUrl->getScheme()); - self::assertEquals($assert['url'], $baseUrl->get()); - } - public function dataSave() { return [ diff --git a/update.php b/update.php index 85a06892f0..8f93775259 100644 --- a/update.php +++ b/update.php @@ -1227,3 +1227,20 @@ function update_1510() } return Update::SUCCESS; } + +function update_1512() +{ + DI::keyValue()->set('nodeinfo_total_users', DI::config()->get('nodeinfo', 'total_users')); + DI::keyValue()->set('nodeinfo_active_users_halfyear', DI::config()->get('nodeinfo', 'active_users_halfyear')); + DI::keyValue()->set('nodeinfo_active_users_monthly', DI::config()->get('nodeinfo', 'active_users_monthly')); + DI::keyValue()->set('nodeinfo_active_users_weekly', DI::config()->get('nodeinfo', 'active_users_weekly')); + DI::keyValue()->set('nodeinfo_local_posts', DI::config()->get('nodeinfo', 'local_posts')); + DI::keyValue()->set('nodeinfo_local_comments', DI::config()->get('nodeinfo', 'local_comments')); + + DI::config()->delete('nodeinfo', 'total_users'); + DI::config()->delete('nodeinfo', 'active_users_halfyear'); + DI::config()->delete('nodeinfo', 'active_users_monthly'); + DI::config()->delete('nodeinfo', 'active_users_weekly'); + DI::config()->delete('nodeinfo', 'local_posts'); + DI::config()->delete('nodeinfo', 'local_comments'); +} diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index 938c5665ed..7634bc8e87 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 2023.03-dev\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-01-14 21:19+0000\n" +"POT-Creation-Date: 2023-01-21 09:22-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -49,7 +49,7 @@ msgstr "" #: src/Module/Attach.php:55 src/Module/BaseApi.php:95 #: src/Module/BaseNotifications.php:98 src/Module/BaseSettings.php:52 #: src/Module/Calendar/Event/API.php:88 src/Module/Calendar/Event/Form.php:84 -#: src/Module/Calendar/Export.php:62 src/Module/Calendar/Show.php:82 +#: src/Module/Calendar/Export.php:82 src/Module/Calendar/Show.php:82 #: src/Module/Contact/Advanced.php:60 src/Module/Contact/Follow.php:86 #: src/Module/Contact/Follow.php:159 src/Module/Contact/MatchInterests.php:86 #: src/Module/Contact/Suggestions.php:54 src/Module/Contact/Unfollow.php:66 @@ -302,7 +302,7 @@ msgstr "" #: mod/photos.php:819 mod/photos.php:1097 mod/photos.php:1138 #: mod/photos.php:1194 mod/photos.php:1268 #: src/Module/Calendar/Event/Form.php:250 src/Module/Contact/Advanced.php:132 -#: src/Module/Contact/Profile.php:343 +#: src/Module/Contact/Profile.php:340 #: src/Module/Debug/ActivityPubConversion.php:140 #: src/Module/Debug/Babel.php:313 src/Module/Debug/Localtime.php:64 #: src/Module/Debug/Probe.php:54 src/Module/Debug/WebFinger.php:51 @@ -385,7 +385,7 @@ msgstr "" #: mod/photos.php:67 mod/photos.php:132 mod/photos.php:577 #: src/Model/Event.php:514 src/Model/Profile.php:234 -#: src/Module/Calendar/Export.php:67 src/Module/Calendar/Show.php:74 +#: src/Module/Calendar/Export.php:74 src/Module/Calendar/Show.php:74 #: src/Module/DFRN/Poll.php:43 src/Module/Feed.php:65 src/Module/HCard.php:51 #: src/Module/Profile/Common.php:62 src/Module/Profile/Common.php:71 #: src/Module/Profile/Contacts.php:64 src/Module/Profile/Contacts.php:72 @@ -649,11 +649,11 @@ msgstr "" msgid "Map" msgstr "" -#: src/App.php:472 +#: src/App.php:470 msgid "No system theme config value set." msgstr "" -#: src/App.php:594 +#: src/App.php:592 msgid "Apologies but the website is unavailable at the moment." msgstr "" @@ -1544,36 +1544,36 @@ msgstr "" msgid "Follow Thread" msgstr "" -#: src/Content/Item.php:420 src/Model/Contact.php:1206 +#: src/Content/Item.php:420 src/Model/Contact.php:1204 msgid "View Status" msgstr "" -#: src/Content/Item.php:421 src/Content/Item.php:440 src/Model/Contact.php:1150 -#: src/Model/Contact.php:1198 src/Model/Contact.php:1207 +#: src/Content/Item.php:421 src/Content/Item.php:440 src/Model/Contact.php:1148 +#: src/Model/Contact.php:1196 src/Model/Contact.php:1205 #: src/Module/Directory.php:157 src/Module/Settings/Profile/Index.php:234 msgid "View Profile" msgstr "" -#: src/Content/Item.php:422 src/Model/Contact.php:1208 +#: src/Content/Item.php:422 src/Model/Contact.php:1206 msgid "View Photos" msgstr "" -#: src/Content/Item.php:423 src/Model/Contact.php:1199 -#: src/Model/Contact.php:1209 +#: src/Content/Item.php:423 src/Model/Contact.php:1197 +#: src/Model/Contact.php:1207 msgid "Network Posts" msgstr "" -#: src/Content/Item.php:424 src/Model/Contact.php:1200 -#: src/Model/Contact.php:1210 +#: src/Content/Item.php:424 src/Model/Contact.php:1198 +#: src/Model/Contact.php:1208 msgid "View Contact" msgstr "" -#: src/Content/Item.php:425 src/Model/Contact.php:1211 +#: src/Content/Item.php:425 src/Model/Contact.php:1209 msgid "Send PM" msgstr "" #: src/Content/Item.php:426 src/Module/Contact.php:440 -#: src/Module/Contact/Profile.php:364 src/Module/Contact/Profile.php:484 +#: src/Module/Contact/Profile.php:478 #: src/Module/Moderation/Blocklist/Contact.php:116 #: src/Module/Moderation/Users/Active.php:137 #: src/Module/Moderation/Users/Index.php:152 @@ -1581,7 +1581,7 @@ msgid "Block" msgstr "" #: src/Content/Item.php:427 src/Module/Contact.php:441 -#: src/Module/Contact/Profile.php:365 src/Module/Contact/Profile.php:492 +#: src/Module/Contact/Profile.php:486 #: src/Module/Notifications/Introductions.php:134 #: src/Module/Notifications/Introductions.php:206 #: src/Module/Notifications/Notification.php:89 @@ -1589,7 +1589,7 @@ msgid "Ignore" msgstr "" #: src/Content/Item.php:428 src/Module/Contact.php:442 -#: src/Module/Contact/Profile.php:500 +#: src/Module/Contact/Profile.php:494 msgid "Collapse" msgstr "" @@ -1598,7 +1598,7 @@ msgid "Languages" msgstr "" #: src/Content/Item.php:437 src/Content/Widget.php:80 -#: src/Model/Contact.php:1201 src/Model/Contact.php:1212 +#: src/Model/Contact.php:1199 src/Model/Contact.php:1210 #: src/Module/Contact/Follow.php:166 view/theme/vier/theme.php:196 msgid "Connect/Follow" msgstr "" @@ -1651,7 +1651,7 @@ msgstr "" #: src/Content/Nav.php:230 src/Module/BaseProfile.php:49 #: src/Module/BaseSettings.php:100 src/Module/Contact.php:476 -#: src/Module/Contact/Profile.php:399 src/Module/Profile/Profile.php:268 +#: src/Module/Contact/Profile.php:393 src/Module/Profile/Profile.php:268 #: src/Module/Welcome.php:57 view/theme/frio/theme.php:230 msgid "Profile" msgstr "" @@ -1877,9 +1877,9 @@ msgstr "" #: src/Content/Nav.php:335 src/Module/BaseModeration.php:127 #: src/Module/Moderation/Blocklist/Contact.php:110 -#: src/Module/Moderation/Blocklist/Server/Add.php:119 -#: src/Module/Moderation/Blocklist/Server/Import.php:115 -#: src/Module/Moderation/Blocklist/Server/Index.php:92 +#: src/Module/Moderation/Blocklist/Server/Add.php:121 +#: src/Module/Moderation/Blocklist/Server/Import.php:118 +#: src/Module/Moderation/Blocklist/Server/Index.php:95 #: src/Module/Moderation/Item/Delete.php:61 #: src/Module/Moderation/Summary.php:76 #: src/Module/Moderation/Users/Active.php:133 @@ -1970,7 +1970,7 @@ msgid "The end" msgstr "" #: src/Content/Text/HTML.php:884 src/Content/Widget/VCard.php:109 -#: src/Model/Profile.php:463 src/Module/Contact/Profile.php:444 +#: src/Model/Profile.php:463 src/Module/Contact/Profile.php:438 msgid "Follow" msgstr "" @@ -2097,7 +2097,7 @@ msgstr "" msgid "Organisations" msgstr "" -#: src/Content/Widget.php:523 src/Model/Contact.php:1658 +#: src/Content/Widget.php:523 src/Model/Contact.php:1656 msgid "News" msgstr "" @@ -2156,18 +2156,18 @@ msgid "More Trending Tags" msgstr "" #: src/Content/Widget/VCard.php:102 src/Model/Profile.php:378 -#: src/Module/Contact/Profile.php:388 src/Module/Profile/Profile.php:199 +#: src/Module/Contact/Profile.php:382 src/Module/Profile/Profile.php:199 msgid "XMPP:" msgstr "" #: src/Content/Widget/VCard.php:103 src/Model/Profile.php:379 -#: src/Module/Contact/Profile.php:390 src/Module/Profile/Profile.php:203 +#: src/Module/Contact/Profile.php:384 src/Module/Profile/Profile.php:203 msgid "Matrix:" msgstr "" #: src/Content/Widget/VCard.php:104 src/Model/Event.php:82 #: src/Model/Event.php:109 src/Model/Event.php:473 src/Model/Event.php:958 -#: src/Model/Profile.php:373 src/Module/Contact/Profile.php:386 +#: src/Model/Profile.php:373 src/Module/Contact/Profile.php:380 #: src/Module/Directory.php:147 src/Module/Notifications/Introductions.php:187 #: src/Module/Profile/Profile.php:221 msgid "Location:" @@ -2178,9 +2178,9 @@ msgstr "" msgid "Network:" msgstr "" -#: src/Content/Widget/VCard.php:111 src/Model/Contact.php:1202 -#: src/Model/Contact.php:1213 src/Model/Profile.php:465 -#: src/Module/Contact/Profile.php:436 +#: src/Content/Widget/VCard.php:111 src/Model/Contact.php:1200 +#: src/Model/Contact.php:1211 src/Model/Profile.php:465 +#: src/Module/Contact/Profile.php:430 msgid "Unfollow" msgstr "" @@ -2882,82 +2882,82 @@ msgstr "" msgid "Legacy module file not found: %s" msgstr "" -#: src/Model/Contact.php:1219 src/Module/Moderation/Users/Pending.php:102 +#: src/Model/Contact.php:1217 src/Module/Moderation/Users/Pending.php:102 #: src/Module/Notifications/Introductions.php:132 #: src/Module/Notifications/Introductions.php:204 msgid "Approve" msgstr "" -#: src/Model/Contact.php:1654 +#: src/Model/Contact.php:1652 msgid "Organisation" msgstr "" -#: src/Model/Contact.php:1662 +#: src/Model/Contact.php:1660 msgid "Forum" msgstr "" -#: src/Model/Contact.php:2931 +#: src/Model/Contact.php:2929 msgid "Disallowed profile URL." msgstr "" -#: src/Model/Contact.php:2936 src/Module/Friendica.php:83 +#: src/Model/Contact.php:2934 src/Module/Friendica.php:83 msgid "Blocked domain" msgstr "" -#: src/Model/Contact.php:2941 +#: src/Model/Contact.php:2939 msgid "Connect URL missing." msgstr "" -#: src/Model/Contact.php:2950 +#: src/Model/Contact.php:2948 msgid "" "The contact could not be added. Please check the relevant network " "credentials in your Settings -> Social Networks page." msgstr "" -#: src/Model/Contact.php:2968 +#: src/Model/Contact.php:2966 #, php-format msgid "Expected network %s does not match actual network %s" msgstr "" -#: src/Model/Contact.php:2985 +#: src/Model/Contact.php:2983 msgid "The profile address specified does not provide adequate information." msgstr "" -#: src/Model/Contact.php:2987 +#: src/Model/Contact.php:2985 msgid "No compatible communication protocols or feeds were discovered." msgstr "" -#: src/Model/Contact.php:2990 +#: src/Model/Contact.php:2988 msgid "An author or name was not found." msgstr "" -#: src/Model/Contact.php:2993 +#: src/Model/Contact.php:2991 msgid "No browser URL could be matched to this address." msgstr "" -#: src/Model/Contact.php:2996 +#: src/Model/Contact.php:2994 msgid "" "Unable to match @-style Identity Address with a known protocol or email " "contact." msgstr "" -#: src/Model/Contact.php:2997 +#: src/Model/Contact.php:2995 msgid "Use mailto: in front of address to force email check." msgstr "" -#: src/Model/Contact.php:3003 +#: src/Model/Contact.php:3001 msgid "" "The profile address specified belongs to a network which has been disabled " "on this site." msgstr "" -#: src/Model/Contact.php:3008 +#: src/Model/Contact.php:3006 msgid "" "Limited profile. This person will be unable to receive direct/personal " "notifications from you." msgstr "" -#: src/Model/Contact.php:3073 +#: src/Model/Contact.php:3071 msgid "Unable to retrieve contact information." msgstr "" @@ -3206,7 +3206,7 @@ msgstr "" msgid "Homepage:" msgstr "" -#: src/Model/Profile.php:377 src/Module/Contact/Profile.php:392 +#: src/Model/Profile.php:377 src/Module/Contact/Profile.php:386 #: src/Module/Notifications/Introductions.php:189 msgid "About:" msgstr "" @@ -3296,7 +3296,7 @@ msgstr "" msgid "Title/Description:" msgstr "" -#: src/Model/Profile.php:1023 src/Module/Admin/Summary.php:222 +#: src/Model/Profile.php:1023 src/Module/Admin/Summary.php:220 #: src/Module/Moderation/Summary.php:77 msgid "Summary" msgstr "" @@ -3368,8 +3368,7 @@ msgid "The password length is limited to 72 characters." msgstr "" #: src/Model/User.php:807 -msgid "" -"The password can't contain accentuated letters, white spaces or colons (:)" +msgid "The password can't contain white spaces nor accentuated letters" msgstr "" #: src/Model/User.php:1002 @@ -3624,7 +3623,7 @@ msgstr "" #: src/Module/Admin/Federation.php:207 src/Module/Admin/Logs/Settings.php:79 #: src/Module/Admin/Logs/View.php:84 src/Module/Admin/Queue.php:72 #: src/Module/Admin/Site.php:435 src/Module/Admin/Storage.php:138 -#: src/Module/Admin/Summary.php:221 src/Module/Admin/Themes/Details.php:90 +#: src/Module/Admin/Summary.php:219 src/Module/Admin/Themes/Details.php:90 #: src/Module/Admin/Themes/Index.php:111 src/Module/Admin/Tos.php:77 #: src/Module/Moderation/Users/Create.php:61 #: src/Module/Moderation/Users/Pending.php:96 @@ -4918,7 +4917,7 @@ msgid "" "received." msgstr "" -#: src/Module/Admin/Site.php:551 src/Module/Contact/Profile.php:290 +#: src/Module/Admin/Site.php:551 src/Module/Contact/Profile.php:287 #: src/Module/Settings/TwoFactor/Index.php:125 msgid "Disabled" msgstr "" @@ -5007,12 +5006,12 @@ msgstr "" msgid "Database (legacy)" msgstr "" -#: src/Module/Admin/Summary.php:57 +#: src/Module/Admin/Summary.php:55 #, php-format msgid "Template engine (%s) error: %s" msgstr "" -#: src/Module/Admin/Summary.php:61 +#: src/Module/Admin/Summary.php:59 #, php-format msgid "" "Your DB still runs with MyISAM tables. You should change the engine type to " @@ -5023,7 +5022,7 @@ msgid "" "automatic conversion.
" msgstr "" -#: src/Module/Admin/Summary.php:66 +#: src/Module/Admin/Summary.php:64 #, php-format msgid "" "Your DB still runs with InnoDB tables in the Antelope file format. You " @@ -5034,7 +5033,7 @@ msgid "" "installation for an automatic conversion.
" msgstr "" -#: src/Module/Admin/Summary.php:76 +#: src/Module/Admin/Summary.php:74 #, php-format msgid "" "Your table_definition_cache is too low (%d). This can lead to the database " @@ -5042,39 +5041,39 @@ msgid "" "to %d. See here for more information.
" msgstr "" -#: src/Module/Admin/Summary.php:86 +#: src/Module/Admin/Summary.php:84 #, php-format msgid "" "There is a new version of Friendica available for download. Your current " "version is %1$s, upstream version is %2$s" msgstr "" -#: src/Module/Admin/Summary.php:95 +#: src/Module/Admin/Summary.php:93 msgid "" "The database update failed. Please run \"php bin/console.php dbstructure " "update\" from the command line and have a look at the errors that might " "appear." msgstr "" -#: src/Module/Admin/Summary.php:99 +#: src/Module/Admin/Summary.php:97 msgid "" "The last update failed. Please run \"php bin/console.php dbstructure update" "\" from the command line and have a look at the errors that might appear. " "(Some of the errors are possibly inside the logfile.)" msgstr "" -#: src/Module/Admin/Summary.php:104 +#: src/Module/Admin/Summary.php:102 msgid "The worker was never executed. Please check your database structure!" msgstr "" -#: src/Module/Admin/Summary.php:106 +#: src/Module/Admin/Summary.php:104 #, php-format msgid "" "The last worker execution was on %s UTC. This is older than one hour. Please " "check your crontab settings." msgstr "" -#: src/Module/Admin/Summary.php:111 +#: src/Module/Admin/Summary.php:109 #, php-format msgid "" "Friendica's configuration now is stored in config/local.config.php, please " @@ -5083,7 +5082,7 @@ msgid "" "with the transition." msgstr "" -#: src/Module/Admin/Summary.php:115 +#: src/Module/Admin/Summary.php:113 #, php-format msgid "" "Friendica's configuration now is stored in config/local.config.php, please " @@ -5092,7 +5091,7 @@ msgid "" "with the transition." msgstr "" -#: src/Module/Admin/Summary.php:119 +#: src/Module/Admin/Summary.php:117 #, php-format msgid "" "Friendica's configuration store \"%s\" isn't writable. Until then database " @@ -5100,7 +5099,7 @@ msgid "" "configuration changes won't be saved." msgstr "" -#: src/Module/Admin/Summary.php:125 +#: src/Module/Admin/Summary.php:123 #, php-format msgid "" "%s is not reachable on your system. This is a severe " @@ -5108,50 +5107,50 @@ msgid "" "href=\"%s\">the installation page for help." msgstr "" -#: src/Module/Admin/Summary.php:143 +#: src/Module/Admin/Summary.php:141 #, php-format msgid "The logfile '%s' is not usable. No logging possible (error: '%s')" msgstr "" -#: src/Module/Admin/Summary.php:157 +#: src/Module/Admin/Summary.php:155 #, php-format msgid "The debug logfile '%s' is not usable. No logging possible (error: '%s')" msgstr "" -#: src/Module/Admin/Summary.php:173 +#: src/Module/Admin/Summary.php:171 #, php-format msgid "" "Friendica's system.basepath was updated from '%s' to '%s'. Please remove the " "system.basepath from your db to avoid differences." msgstr "" -#: src/Module/Admin/Summary.php:181 +#: src/Module/Admin/Summary.php:179 #, php-format msgid "" "Friendica's current system.basepath '%s' is wrong and the config file '%s' " "isn't used." msgstr "" -#: src/Module/Admin/Summary.php:189 +#: src/Module/Admin/Summary.php:187 #, php-format msgid "" "Friendica's current system.basepath '%s' is not equal to the config file " "'%s'. Please fix your configuration." msgstr "" -#: src/Module/Admin/Summary.php:200 +#: src/Module/Admin/Summary.php:198 msgid "Message queues" msgstr "" -#: src/Module/Admin/Summary.php:206 +#: src/Module/Admin/Summary.php:204 msgid "Server Settings" msgstr "" -#: src/Module/Admin/Summary.php:224 +#: src/Module/Admin/Summary.php:222 msgid "Version" msgstr "" -#: src/Module/Admin/Summary.php:228 +#: src/Module/Admin/Summary.php:226 msgid "Active addons" msgstr "" @@ -5543,13 +5542,13 @@ msgstr "" #: src/Module/Install.php:286 src/Module/Install.php:291 #: src/Module/Install.php:305 src/Module/Install.php:320 #: src/Module/Install.php:347 -#: src/Module/Moderation/Blocklist/Server/Add.php:134 #: src/Module/Moderation/Blocklist/Server/Add.php:136 -#: src/Module/Moderation/Blocklist/Server/Import.php:126 -#: src/Module/Moderation/Blocklist/Server/Index.php:83 -#: src/Module/Moderation/Blocklist/Server/Index.php:84 -#: src/Module/Moderation/Blocklist/Server/Index.php:112 -#: src/Module/Moderation/Blocklist/Server/Index.php:113 +#: src/Module/Moderation/Blocklist/Server/Add.php:138 +#: src/Module/Moderation/Blocklist/Server/Import.php:129 +#: src/Module/Moderation/Blocklist/Server/Index.php:86 +#: src/Module/Moderation/Blocklist/Server/Index.php:87 +#: src/Module/Moderation/Blocklist/Server/Index.php:115 +#: src/Module/Moderation/Blocklist/Server/Index.php:116 #: src/Module/Moderation/Item/Delete.php:67 src/Module/Register.php:148 #: src/Module/Security/TwoFactor/Verify.php:101 #: src/Module/Settings/TwoFactor/Index.php:140 @@ -5589,15 +5588,15 @@ msgstr "" msgid "Basic" msgstr "" -#: src/Module/Calendar/Export.php:77 +#: src/Module/Calendar/Export.php:94 msgid "This calendar format is not supported" msgstr "" -#: src/Module/Calendar/Export.php:79 +#: src/Module/Calendar/Export.php:96 msgid "No exportable data found" msgstr "" -#: src/Module/Calendar/Export.php:96 +#: src/Module/Calendar/Export.php:113 msgid "calendar" msgstr "" @@ -5696,20 +5695,18 @@ msgstr "" msgid "Update" msgstr "" -#: src/Module/Contact.php:440 src/Module/Contact/Profile.php:364 -#: src/Module/Contact/Profile.php:484 +#: src/Module/Contact.php:440 src/Module/Contact/Profile.php:478 #: src/Module/Moderation/Blocklist/Contact.php:117 #: src/Module/Moderation/Users/Blocked.php:138 #: src/Module/Moderation/Users/Index.php:154 msgid "Unblock" msgstr "" -#: src/Module/Contact.php:441 src/Module/Contact/Profile.php:365 -#: src/Module/Contact/Profile.php:492 +#: src/Module/Contact.php:441 src/Module/Contact/Profile.php:486 msgid "Unignore" msgstr "" -#: src/Module/Contact.php:442 src/Module/Contact/Profile.php:500 +#: src/Module/Contact.php:442 src/Module/Contact/Profile.php:494 msgid "Uncollapse" msgstr "" @@ -5761,7 +5758,7 @@ msgstr "" msgid "Pending incoming contact request" msgstr "" -#: src/Module/Contact.php:597 src/Module/Contact/Profile.php:350 +#: src/Module/Contact.php:597 src/Module/Contact/Profile.php:347 #, php-format msgid "Visit %s's profile [%s]" msgstr "" @@ -5914,7 +5911,7 @@ msgstr "" msgid "Your Identity Address:" msgstr "" -#: src/Module/Contact/Follow.php:169 src/Module/Contact/Profile.php:382 +#: src/Module/Contact/Follow.php:169 src/Module/Contact/Profile.php:376 #: src/Module/Contact/Unfollow.php:129 #: src/Module/Moderation/Blocklist/Contact.php:133 #: src/Module/Notifications/Introductions.php:129 @@ -5922,7 +5919,7 @@ msgstr "" msgid "Profile URL" msgstr "" -#: src/Module/Contact/Follow.php:170 src/Module/Contact/Profile.php:394 +#: src/Module/Contact/Follow.php:170 src/Module/Contact/Profile.php:388 #: src/Module/Notifications/Introductions.php:191 #: src/Module/Profile/Profile.php:234 msgid "Tags:" @@ -5989,220 +5986,220 @@ msgstr "" msgid "Contact has been collapsed" msgstr "" -#: src/Module/Contact/Profile.php:246 +#: src/Module/Contact/Profile.php:243 #, php-format msgid "You are mutual friends with %s" msgstr "" -#: src/Module/Contact/Profile.php:247 +#: src/Module/Contact/Profile.php:244 #, php-format msgid "You are sharing with %s" msgstr "" -#: src/Module/Contact/Profile.php:248 +#: src/Module/Contact/Profile.php:245 #, php-format msgid "%s is sharing with you" msgstr "" -#: src/Module/Contact/Profile.php:264 +#: src/Module/Contact/Profile.php:261 msgid "Private communications are not available for this contact." msgstr "" -#: src/Module/Contact/Profile.php:266 +#: src/Module/Contact/Profile.php:263 msgid "Never" msgstr "" -#: src/Module/Contact/Profile.php:269 +#: src/Module/Contact/Profile.php:266 msgid "(Update was not successful)" msgstr "" -#: src/Module/Contact/Profile.php:269 +#: src/Module/Contact/Profile.php:266 msgid "(Update was successful)" msgstr "" -#: src/Module/Contact/Profile.php:271 src/Module/Contact/Profile.php:455 +#: src/Module/Contact/Profile.php:268 src/Module/Contact/Profile.php:449 msgid "Suggest friends" msgstr "" -#: src/Module/Contact/Profile.php:275 +#: src/Module/Contact/Profile.php:272 #, php-format msgid "Network type: %s" msgstr "" -#: src/Module/Contact/Profile.php:280 +#: src/Module/Contact/Profile.php:277 msgid "Communications lost with this contact!" msgstr "" -#: src/Module/Contact/Profile.php:286 +#: src/Module/Contact/Profile.php:283 msgid "Fetch further information for feeds" msgstr "" -#: src/Module/Contact/Profile.php:288 +#: src/Module/Contact/Profile.php:285 msgid "" "Fetch information like preview pictures, title and teaser from the feed " "item. You can activate this if the feed doesn't contain much text. Keywords " "are taken from the meta header in the feed item and are posted as hash tags." msgstr "" -#: src/Module/Contact/Profile.php:291 +#: src/Module/Contact/Profile.php:288 msgid "Fetch information" msgstr "" -#: src/Module/Contact/Profile.php:292 +#: src/Module/Contact/Profile.php:289 msgid "Fetch keywords" msgstr "" -#: src/Module/Contact/Profile.php:293 +#: src/Module/Contact/Profile.php:290 msgid "Fetch information and keywords" msgstr "" -#: src/Module/Contact/Profile.php:303 src/Module/Contact/Profile.php:308 -#: src/Module/Contact/Profile.php:313 src/Module/Contact/Profile.php:319 +#: src/Module/Contact/Profile.php:300 src/Module/Contact/Profile.php:305 +#: src/Module/Contact/Profile.php:310 src/Module/Contact/Profile.php:316 msgid "No mirroring" msgstr "" -#: src/Module/Contact/Profile.php:304 src/Module/Contact/Profile.php:314 -#: src/Module/Contact/Profile.php:320 +#: src/Module/Contact/Profile.php:301 src/Module/Contact/Profile.php:311 +#: src/Module/Contact/Profile.php:317 msgid "Mirror as my own posting" msgstr "" -#: src/Module/Contact/Profile.php:309 src/Module/Contact/Profile.php:315 +#: src/Module/Contact/Profile.php:306 src/Module/Contact/Profile.php:312 msgid "Native reshare" msgstr "" -#: src/Module/Contact/Profile.php:332 +#: src/Module/Contact/Profile.php:329 msgid "Contact Information / Notes" msgstr "" -#: src/Module/Contact/Profile.php:333 +#: src/Module/Contact/Profile.php:330 msgid "Contact Settings" msgstr "" -#: src/Module/Contact/Profile.php:341 +#: src/Module/Contact/Profile.php:338 msgid "Contact" msgstr "" -#: src/Module/Contact/Profile.php:345 +#: src/Module/Contact/Profile.php:342 msgid "Their personal note" msgstr "" -#: src/Module/Contact/Profile.php:347 +#: src/Module/Contact/Profile.php:344 msgid "Edit contact notes" msgstr "" -#: src/Module/Contact/Profile.php:351 +#: src/Module/Contact/Profile.php:348 msgid "Block/Unblock contact" msgstr "" -#: src/Module/Contact/Profile.php:352 +#: src/Module/Contact/Profile.php:349 msgid "Ignore contact" msgstr "" -#: src/Module/Contact/Profile.php:353 +#: src/Module/Contact/Profile.php:350 msgid "View conversations" msgstr "" -#: src/Module/Contact/Profile.php:358 +#: src/Module/Contact/Profile.php:355 msgid "Last update:" msgstr "" -#: src/Module/Contact/Profile.php:360 +#: src/Module/Contact/Profile.php:357 msgid "Update public posts" msgstr "" -#: src/Module/Contact/Profile.php:362 src/Module/Contact/Profile.php:465 +#: src/Module/Contact/Profile.php:359 src/Module/Contact/Profile.php:459 msgid "Update now" msgstr "" -#: src/Module/Contact/Profile.php:369 -msgid "Currently blocked" -msgstr "" - -#: src/Module/Contact/Profile.php:370 -msgid "Currently ignored" -msgstr "" - -#: src/Module/Contact/Profile.php:371 -msgid "Currently collapsed" -msgstr "" - -#: src/Module/Contact/Profile.php:372 -msgid "Currently archived" -msgstr "" - -#: src/Module/Contact/Profile.php:373 +#: src/Module/Contact/Profile.php:361 msgid "Awaiting connection acknowledge" msgstr "" -#: src/Module/Contact/Profile.php:374 +#: src/Module/Contact/Profile.php:362 +msgid "Currently blocked" +msgstr "" + +#: src/Module/Contact/Profile.php:363 +msgid "Currently ignored" +msgstr "" + +#: src/Module/Contact/Profile.php:364 +msgid "Currently collapsed" +msgstr "" + +#: src/Module/Contact/Profile.php:365 +msgid "Currently archived" +msgstr "" + +#: src/Module/Contact/Profile.php:368 #: src/Module/Notifications/Introductions.php:192 msgid "Hide this contact from others" msgstr "" -#: src/Module/Contact/Profile.php:374 +#: src/Module/Contact/Profile.php:368 msgid "" "Replies/likes to your public posts may still be visible" msgstr "" -#: src/Module/Contact/Profile.php:375 +#: src/Module/Contact/Profile.php:369 msgid "Notification for new posts" msgstr "" -#: src/Module/Contact/Profile.php:375 +#: src/Module/Contact/Profile.php:369 msgid "Send a notification of every new post of this contact" msgstr "" -#: src/Module/Contact/Profile.php:377 +#: src/Module/Contact/Profile.php:371 msgid "Keyword Deny List" msgstr "" -#: src/Module/Contact/Profile.php:377 +#: src/Module/Contact/Profile.php:371 msgid "" "Comma separated list of keywords that should not be converted to hashtags, " "when \"Fetch information and keywords\" is selected" msgstr "" -#: src/Module/Contact/Profile.php:395 +#: src/Module/Contact/Profile.php:389 #: src/Module/Settings/TwoFactor/Index.php:139 msgid "Actions" msgstr "" -#: src/Module/Contact/Profile.php:397 +#: src/Module/Contact/Profile.php:391 #: src/Module/Settings/TwoFactor/Index.php:119 view/theme/frio/theme.php:229 msgid "Status" msgstr "" -#: src/Module/Contact/Profile.php:403 +#: src/Module/Contact/Profile.php:397 msgid "Mirror postings from this contact" msgstr "" -#: src/Module/Contact/Profile.php:405 +#: src/Module/Contact/Profile.php:399 msgid "" "Mark this contact as remote_self, this will cause friendica to repost new " "entries from this contact." msgstr "" -#: src/Module/Contact/Profile.php:475 +#: src/Module/Contact/Profile.php:469 msgid "Refetch contact data" msgstr "" -#: src/Module/Contact/Profile.php:486 +#: src/Module/Contact/Profile.php:480 msgid "Toggle Blocked status" msgstr "" -#: src/Module/Contact/Profile.php:494 +#: src/Module/Contact/Profile.php:488 msgid "Toggle Ignored status" msgstr "" -#: src/Module/Contact/Profile.php:502 +#: src/Module/Contact/Profile.php:496 msgid "Toggle Collapsed status" msgstr "" -#: src/Module/Contact/Profile.php:509 src/Module/Contact/Revoke.php:106 +#: src/Module/Contact/Profile.php:503 src/Module/Contact/Revoke.php:106 msgid "Revoke Follow" msgstr "" -#: src/Module/Contact/Profile.php:511 +#: src/Module/Contact/Profile.php:505 msgid "Revoke the follow from this contact" msgstr "" @@ -6725,8 +6722,8 @@ msgid "On this server the following remote servers are blocked." msgstr "" #: src/Module/Friendica.php:84 -#: src/Module/Moderation/Blocklist/Server/Index.php:84 -#: src/Module/Moderation/Blocklist/Server/Index.php:108 +#: src/Module/Moderation/Blocklist/Server/Index.php:87 +#: src/Module/Moderation/Blocklist/Server/Index.php:111 msgid "Reason for the block" msgstr "" @@ -7399,32 +7396,32 @@ msgid "" msgstr "" #: src/Module/Moderation/Blocklist/Contact.php:135 -#: src/Module/Moderation/Blocklist/Server/Import.php:121 +#: src/Module/Moderation/Blocklist/Server/Import.php:124 msgid "Block Reason" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Add.php:78 +#: src/Module/Moderation/Blocklist/Server/Add.php:80 msgid "Server domain pattern added to the blocklist." msgstr "" -#: src/Module/Moderation/Blocklist/Server/Add.php:86 +#: src/Module/Moderation/Blocklist/Server/Add.php:88 #, php-format msgid "%s server scheduled to be purged." msgid_plural "%s servers scheduled to be purged." msgstr[0] "" msgstr[1] "" -#: src/Module/Moderation/Blocklist/Server/Add.php:118 -#: src/Module/Moderation/Blocklist/Server/Import.php:114 +#: src/Module/Moderation/Blocklist/Server/Add.php:120 +#: src/Module/Moderation/Blocklist/Server/Import.php:117 msgid "← Return to the list" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Add.php:120 +#: src/Module/Moderation/Blocklist/Server/Add.php:122 msgid "Block A New Server Domain Pattern" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Add.php:121 -#: src/Module/Moderation/Blocklist/Server/Index.php:96 +#: src/Module/Moderation/Blocklist/Server/Add.php:123 +#: src/Module/Moderation/Blocklist/Server/Index.php:99 msgid "" "

The server domain pattern syntax is case-insensitive shell wildcard, " "comprising the following special characters:

\n" @@ -7434,55 +7431,55 @@ msgid "" "" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Add.php:126 -#: src/Module/Moderation/Blocklist/Server/Index.php:104 +#: src/Module/Moderation/Blocklist/Server/Add.php:128 +#: src/Module/Moderation/Blocklist/Server/Index.php:107 msgid "Check pattern" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Add.php:127 +#: src/Module/Moderation/Blocklist/Server/Add.php:129 msgid "Matching known servers" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Add.php:128 +#: src/Module/Moderation/Blocklist/Server/Add.php:130 msgid "Server Name" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Add.php:129 +#: src/Module/Moderation/Blocklist/Server/Add.php:131 msgid "Server Domain" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Add.php:130 +#: src/Module/Moderation/Blocklist/Server/Add.php:132 msgid "Known Contacts" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Add.php:131 +#: src/Module/Moderation/Blocklist/Server/Add.php:133 #, php-format msgid "%d known server" msgid_plural "%d known servers" msgstr[0] "" msgstr[1] "" -#: src/Module/Moderation/Blocklist/Server/Add.php:132 +#: src/Module/Moderation/Blocklist/Server/Add.php:134 msgid "Add pattern to the blocklist" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Add.php:134 -#: src/Module/Moderation/Blocklist/Server/Index.php:113 +#: src/Module/Moderation/Blocklist/Server/Add.php:136 +#: src/Module/Moderation/Blocklist/Server/Index.php:116 msgid "Server Domain Pattern" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Add.php:134 -#: src/Module/Moderation/Blocklist/Server/Index.php:113 +#: src/Module/Moderation/Blocklist/Server/Add.php:136 +#: src/Module/Moderation/Blocklist/Server/Index.php:116 msgid "" "The domain pattern of the new server to add to the blocklist. Do not include " "the protocol." msgstr "" -#: src/Module/Moderation/Blocklist/Server/Add.php:135 +#: src/Module/Moderation/Blocklist/Server/Add.php:137 msgid "Purge server" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Add.php:135 +#: src/Module/Moderation/Blocklist/Server/Add.php:137 msgid "" "Also purges all the locally stored content authored by the known contacts " "registered on that server. Keeps the contacts and the server records. This " @@ -7494,149 +7491,149 @@ msgid_plural "" msgstr[0] "" msgstr[1] "" -#: src/Module/Moderation/Blocklist/Server/Add.php:136 +#: src/Module/Moderation/Blocklist/Server/Add.php:138 msgid "Block reason" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Add.php:136 +#: src/Module/Moderation/Blocklist/Server/Add.php:138 msgid "" "The reason why you blocked this server domain pattern. This reason will be " "shown publicly in the server information page." msgstr "" -#: src/Module/Moderation/Blocklist/Server/Import.php:73 -#: src/Module/Moderation/Blocklist/Server/Import.php:82 +#: src/Module/Moderation/Blocklist/Server/Import.php:74 +#: src/Module/Moderation/Blocklist/Server/Import.php:83 msgid "Error importing pattern file" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Import.php:88 +#: src/Module/Moderation/Blocklist/Server/Import.php:89 msgid "Local blocklist replaced with the provided file." msgstr "" -#: src/Module/Moderation/Blocklist/Server/Import.php:92 +#: src/Module/Moderation/Blocklist/Server/Import.php:93 #, php-format msgid "%d pattern was added to the local blocklist." msgid_plural "%d patterns were added to the local blocklist." msgstr[0] "" msgstr[1] "" -#: src/Module/Moderation/Blocklist/Server/Import.php:94 +#: src/Module/Moderation/Blocklist/Server/Import.php:95 msgid "No pattern was added to the local blocklist." msgstr "" -#: src/Module/Moderation/Blocklist/Server/Import.php:116 +#: src/Module/Moderation/Blocklist/Server/Import.php:119 msgid "Import a Server Domain Pattern Blocklist" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Import.php:117 +#: src/Module/Moderation/Blocklist/Server/Import.php:120 msgid "" "

This file can be downloaded from the /friendica path of any " "Friendica server.

" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Import.php:118 -#: src/Module/Moderation/Blocklist/Server/Index.php:103 +#: src/Module/Moderation/Blocklist/Server/Import.php:121 +#: src/Module/Moderation/Blocklist/Server/Index.php:106 msgid "Upload file" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Import.php:119 +#: src/Module/Moderation/Blocklist/Server/Import.php:122 msgid "Patterns to import" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Import.php:120 +#: src/Module/Moderation/Blocklist/Server/Import.php:123 msgid "Domain Pattern" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Import.php:122 +#: src/Module/Moderation/Blocklist/Server/Import.php:125 msgid "Import Mode" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Import.php:123 +#: src/Module/Moderation/Blocklist/Server/Import.php:126 msgid "Import Patterns" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Import.php:124 +#: src/Module/Moderation/Blocklist/Server/Import.php:127 #, php-format msgid "%d total pattern" msgid_plural "%d total patterns" msgstr[0] "" msgstr[1] "" -#: src/Module/Moderation/Blocklist/Server/Import.php:126 -#: src/Module/Moderation/Blocklist/Server/Index.php:112 +#: src/Module/Moderation/Blocklist/Server/Import.php:129 +#: src/Module/Moderation/Blocklist/Server/Index.php:115 msgid "Server domain pattern blocklist CSV file" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Import.php:127 +#: src/Module/Moderation/Blocklist/Server/Import.php:130 msgid "Append" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Import.php:127 +#: src/Module/Moderation/Blocklist/Server/Import.php:130 msgid "" "Imports patterns from the file that weren't already existing in the current " "blocklist." msgstr "" -#: src/Module/Moderation/Blocklist/Server/Import.php:128 +#: src/Module/Moderation/Blocklist/Server/Import.php:131 msgid "Replace" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Import.php:128 +#: src/Module/Moderation/Blocklist/Server/Import.php:131 msgid "Replaces the current blocklist by the imported patterns." msgstr "" -#: src/Module/Moderation/Blocklist/Server/Index.php:83 -#: src/Module/Moderation/Blocklist/Server/Index.php:107 +#: src/Module/Moderation/Blocklist/Server/Index.php:86 +#: src/Module/Moderation/Blocklist/Server/Index.php:110 msgid "Blocked server domain pattern" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Index.php:85 +#: src/Module/Moderation/Blocklist/Server/Index.php:88 msgid "Delete server domain pattern" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Index.php:85 +#: src/Module/Moderation/Blocklist/Server/Index.php:88 msgid "Check to delete this entry from the blocklist" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Index.php:93 +#: src/Module/Moderation/Blocklist/Server/Index.php:96 msgid "Server Domain Pattern Blocklist" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Index.php:94 +#: src/Module/Moderation/Blocklist/Server/Index.php:97 msgid "" "This page can be used to define a blocklist of server domain patterns from " "the federated network that are not allowed to interact with your node. For " "each domain pattern you should also provide the reason why you block it." msgstr "" -#: src/Module/Moderation/Blocklist/Server/Index.php:95 +#: src/Module/Moderation/Blocklist/Server/Index.php:98 msgid "" "The list of blocked server domain patterns will be made publically available " "on the /friendica page so that your users and " "people investigating communication problems can find the reason easily." msgstr "" -#: src/Module/Moderation/Blocklist/Server/Index.php:101 +#: src/Module/Moderation/Blocklist/Server/Index.php:104 msgid "Import server domain pattern blocklist" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Index.php:102 +#: src/Module/Moderation/Blocklist/Server/Index.php:105 msgid "Add new entry to the blocklist" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Index.php:105 +#: src/Module/Moderation/Blocklist/Server/Index.php:108 msgid "Save changes to the blocklist" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Index.php:106 +#: src/Module/Moderation/Blocklist/Server/Index.php:109 msgid "Current Entries in the Blocklist" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Index.php:109 +#: src/Module/Moderation/Blocklist/Server/Index.php:112 msgid "Delete entry from the blocklist" msgstr "" -#: src/Module/Moderation/Blocklist/Server/Index.php:110 +#: src/Module/Moderation/Blocklist/Server/Index.php:113 msgid "Delete entry from the blocklist?" msgstr "" @@ -8071,7 +8068,7 @@ msgstr "" msgid "Unsupported or missing response type" msgstr "" -#: src/Module/OAuth/Authorize.php:59 src/Module/OAuth/Token.php:73 +#: src/Module/OAuth/Authorize.php:59 src/Module/OAuth/Token.php:76 msgid "Incomplete request data" msgstr "" @@ -8082,11 +8079,11 @@ msgid "" "close this window: %s" msgstr "" -#: src/Module/OAuth/Token.php:78 +#: src/Module/OAuth/Token.php:81 msgid "Invalid data or unknown client" msgstr "" -#: src/Module/OAuth/Token.php:97 +#: src/Module/OAuth/Token.php:100 msgid "Unsupported or missing grant type" msgstr "" @@ -8767,7 +8764,7 @@ msgstr "" #: src/Module/Settings/Account.php:552 msgid "" "Allowed characters are a-z, A-Z, 0-9 and special characters except white " -"spaces, accentuated letters and colon (:)." +"spaces and accentuated letters." msgstr "" #: src/Module/Security/PasswordTooLong.php:101 diff --git a/view/templates/contact_edit.tpl b/view/templates/contact_edit.tpl index 97f7a6526f..a9105d696c 100644 --- a/view/templates/contact_edit.tpl +++ b/view/templates/contact_edit.tpl @@ -1,3 +1,4 @@ +
{{* Insert Tab-Nav *}} @@ -12,7 +13,7 @@ {{* This is the Action menu where contact related actions like 'ignore', 'hide' can be performed *}}
- {{$contact_action_button}} +
@@ -34,9 +34,9 @@ {{if $poll_enabled}}
  • {{$lastupdtext}} {{$last_update}}
    - {{if $poll_interval}} - {{$updpub}} {{$poll_interval nofilter}} - {{/if}} + {{if $poll_interval}} + {{$updpub}} {{$poll_interval nofilter}} + {{/if}}
  • {{/if}} @@ -45,13 +45,12 @@ {{if $blocked && !$pending}}
  • {{$blocked}}
  • {{/if}} {{if $pending}}
  • {{$pending}}
  • {{/if}} {{if $ignored}}
  • {{$ignored}}
  • {{/if}} - {{if $collapsed}}
  • {{$collapsed}}
  • {{/if}} {{if $archived}}
  • {{$archived}}
  • {{/if}}
    {{* End of contact-edit-status-wrapper *}} {{* Some information about the contact from the profile *}} -
    {{$profileurllabel}}
    {{$profileurl}}
    +
    {{$profileurllabel}}
    {{$profileurl}}
    {{if $location}}
    {{$location_label}}
    {{$location nofilter}}
    {{/if}} {{if $xmpp}}
    {{$xmpp_label}}
    {{$xmpp}}
    {{/if}} {{if $matrix}}
    {{$matrix_label}}
    {{$matrix}}
    {{/if}} @@ -63,40 +62,39 @@
    - {{if $contact_settings_label}} + {{if $contact_settings_label}}
    -
    - {{include file="field_checkbox.tpl" field=$notify_new_posts}} - {{if $fetch_further_information}} - {{include file="field_select.tpl" field=$fetch_further_information}} - {{if $fetch_further_information.2 == 2 || $fetch_further_information.2 == 3}} {{include file="field_textarea.tpl" field=$ffi_keyword_denylist}} {{/if}} - {{/if}} - {{if $allow_remote_self}} - {{include file="field_select.tpl" field=$remote_self}} - {{/if}} +
    - {{include file="field_checkbox.tpl" field=$hidden}} + {{include file="field_checkbox.tpl" field=$notify_new_posts}} -
    -

    {{$lbl_info1}}

    - -
    -
    + {{if $fetch_further_information}} + {{include file="field_select.tpl" field=$fetch_further_information}} + {{if $fetch_further_information.2 == 2 || $fetch_further_information.2 == 3}} {{include file="field_textarea.tpl" field=$ffi_keyword_denylist}} {{/if}} + {{/if}} - {{if $reason}} + {{if $allow_remote_self}} + {{include file="field_select.tpl" field=$remote_self}} + {{/if}} + + {{include file="field_checkbox.tpl" field=$hidden}} + + {{include file="field_textarea.tpl" field=$cinfo}} + + {{if $reason}}

    {{$lbl_info2}}

    {{$reason}}

    - {{/if}} -
    - - {{/if}} + + + {{/if}} +
    {{* End of the form *}} diff --git a/view/templates/item/compose.tpl b/view/templates/item/compose.tpl index 5cf81a5f91..50e21b149f 100644 --- a/view/templates/item/compose.tpl +++ b/view/templates/item/compose.tpl @@ -69,8 +69,8 @@ - - + +

    diff --git a/view/theme/vier/templates/sub/direction.tpl b/view/templates/sub/direction.tpl similarity index 100% rename from view/theme/vier/templates/sub/direction.tpl rename to view/templates/sub/direction.tpl diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index 3c4aaa7c6e..b8437e15ff 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -367,6 +367,10 @@ btn-eventnav:hover { aside .badge { opacity: 0.7; } +.forum-widget-entry .badge, +.sidebar-group-li .badge { + margin-top: 6px; +} /* disabled elements */ .community-content-wrapper > h3, @@ -807,13 +811,15 @@ nav.navbar .nav > li > button:focus { } #offcanvasUsermenu a { display: block; + margin: -10px -15px; + padding: 10px 15px; } #offcanvasUsermenu li.nav-sitename { font-weight: bold; } #topbar-first .dropdown.account li#nav-sitename { - padding-left: 15px; - padding-right: 15px; + padding-left: 20px; + padding-right: 20px; font-weight: bold; word-break: break-word; } @@ -822,6 +828,10 @@ nav.navbar .nav > li > button:focus { background-color: $nav_bg; } /* Nav Search */ +.menu-popup { + max-height: calc(100vh - 55px); + overflow-y: auto; +} #topbar-first #search-box .navbar-form { margin: 0px; padding: 12px 12px; @@ -963,13 +973,15 @@ ul li .intro-wrapper button.intro-action-link { background-color: $nav_bg; border: none; } +.dropdown-menu .divider { + margin: 5px 0; +} .nav-pills .dropdown-menu li.divider, .nav-tabs .dropdown-menu li.divider, .account .dropdown-menu li.divider, .contact-photo-wrapper .dropdown-menu li.divider { background-color: $menu_background_hover_color; border-bottom: none; - margin: 9px 1px !important; } .nav-pills .dropdown-menu li > a, .nav-tabs .dropdown-menu li > a, @@ -987,8 +999,6 @@ ul li .intro-wrapper button.intro-action-link { .contact-photo-wrapper .dropdown-menu li .btn-link { color: $nav_icon_color; font-weight: 400; - font-size: 13px; - padding: 4px 15px; width: 100%; text-align: left; } @@ -1044,7 +1054,6 @@ aside .widget, position: relative; margin-bottom: 20px; padding: 10px; - font-size: 13px; overflow: auto; } aside .widget h3, @@ -1052,7 +1061,7 @@ aside .widget h3, font-weight: bold; font-size: 16px; margin: 0; - padding-bottom: 20px; + padding-bottom: 10px; } aside .widget ul, @@ -1065,10 +1074,11 @@ aside .widget ul, list-style: none; } +aside .widget li .label { + float: left; +} aside .widget li, .nav-container .widget li { - padding-top: 2px; - padding-bottom: 2px; padding-left: 20px; padding-right: 10px; } @@ -1081,6 +1091,12 @@ aside .widget li.selected, border-left: 3px solid $link_color !important; padding-left: 17px; } +.side-link-link, +aside .widget li a { + display: block; + padding-top: 6px; + padding-bottom: 6px; +} aside .widget li a, aside .widget li a:hover { color: $font_color_darker; @@ -1300,8 +1316,12 @@ div#sidebar-group-list { } .group-edit-tool { + padding-top: 0; color: $font_color_darker; } +.sidebar-widget-header .group-edit-tool { + margin-top: -5px; +} .faded-icon { color: $font_color_darker; @@ -1316,9 +1336,12 @@ div#sidebar-group-list { margin-left: 20px; } -aside #group-sidebar .sidebar-group-li:hover .group-edit-tool.faded-icon, -aside #saved-search-list .saved-search-li:hover .savedsearchdrop.faded-icon, -aside .widget:hover .widget-action.faded-icon { +aside .widget-action { + padding: 5px 10px; +} +aside #group-sidebar .sidebar-group-li .group-edit-tool.faded-icon:hover, +aside #saved-search-list .saved-search-li .savedsearchdrop.faded-icon:hover, +aside .widget.widget-action.faded-icon:hover { opacity: 0.8; transition: all 0.25s ease-in-out; } @@ -1328,7 +1351,7 @@ aside .widget .widget-action.faded-icon:hover { opacity: 1; } aside #group-sidebar li .group-checkbox { - margin: 0; + margin: 6px 0 0; } aside #group-sidebar li .group-edit-tool { padding-right: 10px; @@ -1762,9 +1785,6 @@ blockquote.shared_content { } /* wall items contact info */ -.media .media-body { - font-size: 13px; -} .media .media-body h4.media-heading { font-size: 14px; font-weight: 500; @@ -1930,6 +1950,9 @@ code > .hl-main { margin: 10px 0; font-size: 13px; } +.wall-item-tags:empty { + margin: 0; +} .wall-item-tags a { color: $font_color_darker; @@ -1953,14 +1976,16 @@ code > .hl-main { margin: 0; justify-content: space-between; } +.wall-item-actions .btn, .wall-item-actions a, .wall-item-actions button { - font-size: 13px; color: $font_color_darker; + background-color: transparent; } .wall-item-actions .active { font-weight: bold; color: $link_color; + box-shadow: none; } .wall-item-actions-left { display: table-cell; @@ -1970,17 +1995,31 @@ code > .hl-main { display: flex; } .wall-item-actions .checkbox { - margin: 0; - margin-left: 20px; + margin: 0 0 0 15px; +} +@media screen and (max-width: 767px) { + .wall-item-actions .btn, + .wall-item-actions a, + .wall-item-actions button { + padding-right: 12px; + padding-left: 12px; + } + .wall-item-actions .checkbox { + margin-top: 8px; + } + .wall-item-actions .like-rotator { + padding-top: 8px; + } } .wall-item-actions button:hover { - color: $font_color_darker; text-decoration: underline; } .wall-item-actions .separator { margin: 0 0.3em; } - +.wall-item-responses { + margin-top: .3em; +} .wall-item-responses > div > p { margin: 0; } @@ -2174,6 +2213,10 @@ the section element. Only after we have moved it to the nav through js */ display: none !important; } +.tabbar-wrapper__link { + padding-right: 10px; + padding-left: 10px; +} #tabmenu, .tabbar-wrapper, .tabbar, @@ -2190,7 +2233,6 @@ ul.tabs { list-style: none; height: 100%; padding: 0; - padding-top: 10px; margin: 0; } ul.tabs li { @@ -2203,8 +2245,9 @@ ul.tabs li { transition: all 0.15s ease; } ul.tabs li a { - margin-left: 10px; - margin-right: 10px; + display: block; + padding-top: 11px; + padding-bottom: 11px; } ul.tabs li:hover, ul.tabs li.active { @@ -2214,7 +2257,7 @@ ul.tabs li.active { padding-top: 0; } #dropdownMenuTools-xs { - padding: 9px 10px; + padding: 9px 15px; } ul.tabbar ul.tabs-extended:hover li.dropdown { border-bottom: 0; @@ -2236,6 +2279,12 @@ ul.dropdown-menu li:hover { box-sizing: border-box; } /* Dropdown Menu */ +.dropdown-menu li .btn-link, +.dropdown-menu li a, +.tabs .dropdown-menu li a { + padding: 6px 20px; + font-size: 14px; +} .dropdown-menu li a, .dropdown-menu li .btn-link { color: $font_color_darker; @@ -2493,20 +2542,18 @@ ul.viewcontact_wrapper > li { } .contact-wrapper .contact-actions { display: flex; + position: relative; + margin: -8px -8px 0 0; } .contact-wrapper .contact-action-link, .contact-wrapper .contact-action-link:hover, .textcomplete-item .contact-wrapper .contact-action-link { - padding: 0 5px; color: $font_color_darker; border: 0; } .contact-wrapper .contact-action-link { - opacity: 0.1; - transition: all 0.25s ease-in-out; -} -ul li:hover .contact-wrapper .contact-action-link { - opacity: 0.8; + background-color: transparent; + opacity: 0.3; transition: all 0.25s ease-in-out; } ul li:hover .contact-wrapper .contact-action-link:hover { @@ -2912,6 +2959,10 @@ ul li:hover .contact-wrapper .contact-action-link:hover { .section-subtitle-wrapper { padding: 1px 10px; } +.accordion-toggle { + width: 100%; + text-align: left; +} details.profile-jot-net[open] summary:before, .panel .section-subtitle-wrapper .accordion-toggle:before { font-family: ForkAwesome; @@ -2976,6 +3027,12 @@ details.profile-jot-net[open] summary:before { margin-top: 10px; margin-bottom: 10px; } +.section-subtitle-wrapper > h2 .accordion-toggle { + margin-top: -10px; + margin-bottom: -10px; + padding-top: 10px; + padding-bottom: 10px; +} .section-subtitle-wrapper > h3 { font-size: 16px; diff --git a/view/theme/frio/templates/calendar/calendar.tpl b/view/theme/frio/templates/calendar/calendar.tpl index f233866f0b..0872ce0c5c 100644 --- a/view/theme/frio/templates/calendar/calendar.tpl +++ b/view/theme/frio/templates/calendar/calendar.tpl @@ -17,7 +17,7 @@ {{* The dropdown to change the callendar view *}}