Merge remote-tracking branch 'upstream/develop' into mod-item
This commit is contained in:
commit
4e4eab7548
97 changed files with 2738 additions and 2497 deletions
|
|
@ -82,6 +82,10 @@ $dice = $dice->addRule(LoggerInterface::class,['constructParams' => ['auth_ejabb
|
|||
|
||||
\Friendica\DI::init($dice);
|
||||
\Friendica\Core\Logger\Handler\ErrorHandler::register($dice->create(\Psr\Log\LoggerInterface::class));
|
||||
|
||||
// Check the database structure and possibly fixes it
|
||||
\Friendica\Core\Update::check(\Friendica\DI::basePath(), true);
|
||||
|
||||
$appMode = $dice->create(Mode::class);
|
||||
|
||||
if ($appMode->isNormal()) {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ if (php_sapi_name() !== 'cli') {
|
|||
use Dice\Dice;
|
||||
use Friendica\App\Mode;
|
||||
use Friendica\Core\Logger;
|
||||
use Friendica\Core\Update;
|
||||
use Friendica\Core\Worker;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
|
|
@ -63,7 +64,6 @@ $dice = $dice->addRule(LoggerInterface::class,['constructParams' => ['daemon']])
|
|||
|
||||
DI::init($dice);
|
||||
\Friendica\Core\Logger\Handler\ErrorHandler::register($dice->create(\Psr\Log\LoggerInterface::class));
|
||||
$a = DI::app();
|
||||
|
||||
if (DI::mode()->isInstall()) {
|
||||
die("Friendica isn't properly installed yet.\n");
|
||||
|
|
@ -71,7 +71,7 @@ if (DI::mode()->isInstall()) {
|
|||
|
||||
DI::mode()->setExecutor(Mode::DAEMON);
|
||||
|
||||
DI::config()->load();
|
||||
DI::config()->reload();
|
||||
|
||||
if (empty(DI::config()->get('system', 'pidfile'))) {
|
||||
die(<<<TXT
|
||||
|
|
@ -126,7 +126,7 @@ if ($mode == 'status') {
|
|||
|
||||
unlink($pidfile);
|
||||
|
||||
DI::config()->set('system', 'worker_daemon_mode', false);
|
||||
DI::keyValue()->set('worker_daemon_mode', false);
|
||||
die("Daemon process $pid isn't running.\n");
|
||||
}
|
||||
|
||||
|
|
@ -193,6 +193,9 @@ $last_cron = 0;
|
|||
|
||||
// Now running as a daemon.
|
||||
while (true) {
|
||||
// Check the database structure and possibly fixes it
|
||||
Update::check(DI::basePath(), true);
|
||||
|
||||
if (!$do_cron && ($last_cron + $wait_interval) < time()) {
|
||||
Logger::info('Forcing cron worker call.', ['pid' => $pid]);
|
||||
$do_cron = true;
|
||||
|
|
|
|||
|
|
@ -58,12 +58,11 @@ $dice = $dice->addRule(LoggerInterface::class,['constructParams' => ['worker']])
|
|||
|
||||
DI::init($dice);
|
||||
\Friendica\Core\Logger\Handler\ErrorHandler::register($dice->create(\Psr\Log\LoggerInterface::class));
|
||||
$a = DI::app();
|
||||
|
||||
DI::mode()->setExecutor(Mode::WORKER);
|
||||
|
||||
// Check the database structure and possibly fixes it
|
||||
Update::check($a->getBasePath(), true, DI::mode());
|
||||
Update::check(DI::basePath(), true);
|
||||
|
||||
// Quit when in maintenance
|
||||
if (!DI::mode()->has(App\Mode::MAINTENANCEDISABLED)) {
|
||||
|
|
|
|||
14
database.sql
14
database.sql
|
|
@ -1,6 +1,6 @@
|
|||
-- ------------------------------------------
|
||||
-- Friendica 2023.03-dev (Giant Rhubarb)
|
||||
-- DB_UPDATE_VERSION 1507
|
||||
-- DB_UPDATE_VERSION 1509
|
||||
-- ------------------------------------------
|
||||
|
||||
|
||||
|
|
@ -494,18 +494,6 @@ CREATE TABLE IF NOT EXISTS `cache` (
|
|||
INDEX `k_expires` (`k`,`expires`)
|
||||
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Stores temporary data';
|
||||
|
||||
--
|
||||
-- TABLE config
|
||||
--
|
||||
CREATE TABLE IF NOT EXISTS `config` (
|
||||
`id` int unsigned NOT NULL auto_increment COMMENT '',
|
||||
`cat` varbinary(50) NOT NULL DEFAULT '' COMMENT '',
|
||||
`k` varbinary(50) NOT NULL DEFAULT '' COMMENT '',
|
||||
`v` mediumtext COMMENT '',
|
||||
PRIMARY KEY(`id`),
|
||||
UNIQUE INDEX `cat_k` (`cat`,`k`)
|
||||
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='main configuration storage';
|
||||
|
||||
--
|
||||
-- TABLE contact-relation
|
||||
--
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ Database Tables
|
|||
| [arrived-activity](help/database/db_arrived-activity) | Id of arrived activities |
|
||||
| [attach](help/database/db_attach) | file attachments |
|
||||
| [cache](help/database/db_cache) | Stores temporary data |
|
||||
| [config](help/database/db_config) | main configuration storage |
|
||||
| [contact](help/database/db_contact) | contact table |
|
||||
| [contact-relation](help/database/db_contact-relation) | Contact relations |
|
||||
| [conv](help/database/db_conv) | private messages |
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
Table config
|
||||
===========
|
||||
|
||||
main configuration storage
|
||||
|
||||
Fields
|
||||
------
|
||||
|
||||
| Field | Description | Type | Null | Key | Default | Extra |
|
||||
| ----- | ----------- | ------------- | ---- | --- | ------- | -------------- |
|
||||
| id | | int unsigned | NO | PRI | NULL | auto_increment |
|
||||
| cat | | varbinary(50) | NO | | | |
|
||||
| k | | varbinary(50) | NO | | | |
|
||||
| v | | mediumtext | YES | | NULL | |
|
||||
|
||||
Indexes
|
||||
------------
|
||||
|
||||
| Name | Fields |
|
||||
| ------- | -------------- |
|
||||
| PRIMARY | id |
|
||||
| cat_k | UNIQUE, cat, k |
|
||||
|
||||
|
||||
Return to [database documentation](help/database)
|
||||
|
|
@ -1,128 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Content\Text\BBCode;
|
||||
use Friendica\Content\Text\HTML;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\DI;
|
||||
use Friendica\Module\Response;
|
||||
use Friendica\Module\Security\Login;
|
||||
use Friendica\Util\XML;
|
||||
|
||||
function oexchange_init(App $a)
|
||||
{
|
||||
if ((DI::args()->getArgc() <= 1) || (DI::args()->getArgv()[1] != 'xrd')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$baseURL = DI::baseUrl()->get();
|
||||
|
||||
$xml = null;
|
||||
|
||||
XML::fromArray([
|
||||
'XRD' => [
|
||||
'@attributes' => [
|
||||
'xmlns' => 'http://docs.oasis-open.org/ns/xri/xrd-1.0',
|
||||
],
|
||||
'Subject' => $baseURL,
|
||||
'1:Property' => [
|
||||
'@attributes' => [
|
||||
'type' => 'http://www.oexchange.org/spec/0.8/prop/vendor',
|
||||
],
|
||||
'Friendica'
|
||||
],
|
||||
'2:Property' => [
|
||||
'@attributes' => [
|
||||
'type' => 'http://www.oexchange.org/spec/0.8/prop/title',
|
||||
],
|
||||
'Friendica Social Network'
|
||||
],
|
||||
'3:Property' => [
|
||||
'@attributes' => [
|
||||
'type' => 'http://www.oexchange.org/spec/0.8/prop/name',
|
||||
],
|
||||
'Friendica'
|
||||
],
|
||||
'4:Property' => [
|
||||
'@attributes' => [
|
||||
'type' => 'http://www.oexchange.org/spec/0.8/prop/prompt',
|
||||
],
|
||||
'Send to Friendica'
|
||||
],
|
||||
'1:link' => [
|
||||
'@attributes' => [
|
||||
'rel' => 'icon',
|
||||
'type' => 'image/png',
|
||||
'href' => $baseURL . '/images/friendica-16.png'
|
||||
]
|
||||
],
|
||||
'2:link' => [
|
||||
'@attributes' => [
|
||||
'rel' => 'icon32',
|
||||
'type' => 'image/png',
|
||||
'href' => $baseURL . '/images/friendica-32.png'
|
||||
]
|
||||
],
|
||||
'3:link' => [
|
||||
'@attributes' => [
|
||||
'rel' => 'http://www.oexchange.org/spec/0.8/rel/offer',
|
||||
'type' => 'text/html',
|
||||
'href' => $baseURL . '/oexchange'
|
||||
]
|
||||
],
|
||||
],
|
||||
], $xml);
|
||||
|
||||
System::httpExit($xml->saveXML(), Response::TYPE_XML, 'application/xrd+xml');
|
||||
}
|
||||
|
||||
function oexchange_content(App $a)
|
||||
{
|
||||
if (!DI::userSession()->getLocalUserId()) {
|
||||
$o = Login::form();
|
||||
return $o;
|
||||
}
|
||||
|
||||
if ((DI::args()->getArgc() > 1) && DI::args()->getArgv()[1] === 'done') {
|
||||
return;
|
||||
}
|
||||
|
||||
$url = !empty($_REQUEST['url']) ? trim($_REQUEST['url']) : '';
|
||||
$title = !empty($_REQUEST['title']) ? trim($_REQUEST['title']) : '';
|
||||
$description = !empty($_REQUEST['description']) ? trim($_REQUEST['description']) : '';
|
||||
$tags = !empty($_REQUEST['tags']) ? trim($_REQUEST['tags']) : '';
|
||||
|
||||
$s = BBCode::embedURL($url, true, $title, $description, $tags);
|
||||
|
||||
if (!strlen($s)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$post = [];
|
||||
|
||||
$post['return'] = '/oexchange/done';
|
||||
$post['body'] = HTML::toBBCode($s);
|
||||
|
||||
$_REQUEST = $post;
|
||||
require_once 'mod/item.php';
|
||||
item_post($a);
|
||||
}
|
||||
|
|
@ -937,11 +937,17 @@ function photos_content(App $a)
|
|||
$nxt = null;
|
||||
foreach ($prvnxt as $z => $entry) {
|
||||
if ($entry['resource-id'] == $ph[0]['resource-id']) {
|
||||
$prv = $z - 1;
|
||||
$nxt = $z + 1;
|
||||
$prv = $order_field === 'created' ? $z - 1 : $z + 1;
|
||||
$nxt = $order_field === 'created' ? $z + 1 : $z - 1;
|
||||
if ($prv < 0) {
|
||||
$prv = count($prvnxt) - 1;
|
||||
}
|
||||
if ($nxt < 0) {
|
||||
$nxt = count($prvnxt) - 1;
|
||||
}
|
||||
if ($prv >= count($prvnxt)) {
|
||||
$prv = 0;
|
||||
}
|
||||
if ($nxt >= count($prvnxt)) {
|
||||
$nxt = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ use Friendica\Model\Contact;
|
|||
|
||||
function update_contact_content(App $a)
|
||||
{
|
||||
if (!empty(DI::args()->get(1)) && (!empty($_GET['force']) || !DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'no_auto_update'))) {
|
||||
if (!empty(DI::args()->get(1)) && !empty($_GET['force'])) {
|
||||
$contact = Contact::getById(DI::args()->get(1), ['id', 'deleted']);
|
||||
if (DBA::isResult($contact) && empty($contact['deleted'])) {
|
||||
DI::page()['aside'] = '';
|
||||
|
|
|
|||
|
|
@ -296,8 +296,7 @@ class App
|
|||
*/
|
||||
public function getBasePath(): string
|
||||
{
|
||||
// Don't use the basepath of the config table for basepath (it should always be the config-file one)
|
||||
return $this->config->getCache()->get('system', 'basepath');
|
||||
return $this->config->get('system', 'basepath');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -360,7 +359,7 @@ class App
|
|||
$this->profiler->update($this->config);
|
||||
|
||||
Core\Hook::loadHooks();
|
||||
$loader = (new Config())->createConfigFileLoader($this->getBasePath(), $_SERVER);
|
||||
$loader = (new Config())->createConfigFileManager($this->getBasePath(), $_SERVER);
|
||||
Core\Hook::callAll('load_config', $loader);
|
||||
|
||||
// Hooks are now working, reload the whole definitions with hook enabled
|
||||
|
|
@ -660,7 +659,7 @@ class App
|
|||
$this->baseURL->redirect('install');
|
||||
} else {
|
||||
$this->checkURL();
|
||||
Core\Update::check($this->getBasePath(), false, $this->mode);
|
||||
Core\Update::check($this->getBasePath(), false);
|
||||
Core\Addon::loadAddons();
|
||||
Core\Hook::loadHooks();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -172,53 +172,32 @@ class BaseURL
|
|||
*/
|
||||
public function save($hostname = null, $sslPolicy = null, $urlPath = null): bool
|
||||
{
|
||||
$currHostname = $this->hostname;
|
||||
$currSSLPolicy = $this->sslPolicy;
|
||||
$currURLPath = $this->urlPath;
|
||||
$currUrl = $this->url;
|
||||
|
||||
$configTransaction = $this->config->beginTransaction();
|
||||
|
||||
if (!empty($hostname) && $hostname !== $this->hostname) {
|
||||
if ($this->config->set('config', 'hostname', $hostname)) {
|
||||
$this->hostname = $hostname;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
$configTransaction->set('config', 'hostname', $hostname);
|
||||
$this->hostname = $hostname;
|
||||
}
|
||||
|
||||
if (isset($sslPolicy) && $sslPolicy !== $this->sslPolicy) {
|
||||
if ($this->config->set('system', 'ssl_policy', $sslPolicy)) {
|
||||
$this->sslPolicy = $sslPolicy;
|
||||
} else {
|
||||
$this->hostname = $currHostname;
|
||||
$this->config->set('config', 'hostname', $this->hostname);
|
||||
return false;
|
||||
}
|
||||
$configTransaction->set('system', 'ssl_policy', $sslPolicy);
|
||||
$this->sslPolicy = $sslPolicy;
|
||||
}
|
||||
|
||||
if (isset($urlPath) && $urlPath !== $this->urlPath) {
|
||||
if ($this->config->set('system', 'urlpath', $urlPath)) {
|
||||
$this->urlPath = $urlPath;
|
||||
} else {
|
||||
$this->hostname = $currHostname;
|
||||
$this->sslPolicy = $currSSLPolicy;
|
||||
$this->config->set('config', 'hostname', $this->hostname);
|
||||
$this->config->set('system', 'ssl_policy', $this->sslPolicy);
|
||||
return false;
|
||||
}
|
||||
$configTransaction->set('system', 'urlpath', $urlPath);
|
||||
$this->urlPath = $urlPath;
|
||||
}
|
||||
|
||||
$this->determineBaseUrl();
|
||||
if (!$this->config->set('system', 'url', $this->url)) {
|
||||
$this->hostname = $currHostname;
|
||||
$this->sslPolicy = $currSSLPolicy;
|
||||
$this->urlPath = $currURLPath;
|
||||
$this->determineBaseUrl();
|
||||
|
||||
$this->config->set('config', 'hostname', $this->hostname);
|
||||
$this->config->set('system', 'ssl_policy', $this->sslPolicy);
|
||||
$this->config->set('system', 'urlpath', $this->urlPath);
|
||||
return false;
|
||||
if ($this->url !== $currUrl) {
|
||||
$configTransaction->set('system', 'url', $this->url);
|
||||
}
|
||||
|
||||
$configTransaction->commit();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -149,16 +149,7 @@ class Mode
|
|||
|
||||
$mode |= Mode::DBAVAILABLE;
|
||||
|
||||
if ($database->fetchFirst("SHOW TABLES LIKE 'config'") === false) {
|
||||
return new Mode($mode);
|
||||
}
|
||||
|
||||
$mode |= Mode::DBCONFIGAVAILABLE;
|
||||
|
||||
if (!empty($configCache->get('system', 'maintenance')) ||
|
||||
// Don't use Config or Configuration here because we're possibly BEFORE initializing the Configuration,
|
||||
// so this could lead to a dependency circle
|
||||
!empty($database->selectFirst('config', ['v'], ['cat' => 'system', 'k' => 'maintenance'])['v'])) {
|
||||
if (!empty($configCache->get('system', 'maintenance'))) {
|
||||
return new Mode($mode);
|
||||
}
|
||||
|
||||
|
|
@ -232,14 +223,14 @@ class Mode
|
|||
}
|
||||
|
||||
/**
|
||||
* Install mode is when the local config file is missing or the DB schema hasn't been installed yet.
|
||||
* Install mode is when the local config file is missing or the database isn't available.
|
||||
*
|
||||
* @return bool Whether installation mode is active (local/database configuration files present or not)
|
||||
*/
|
||||
public function isInstall(): bool
|
||||
{
|
||||
return !$this->has(Mode::LOCALCONFIGPRESENT) ||
|
||||
!$this->has(MODE::DBCONFIGAVAILABLE);
|
||||
!$this->has(MODE::DBAVAILABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -251,7 +242,6 @@ class Mode
|
|||
{
|
||||
return $this->has(Mode::LOCALCONFIGPRESENT) &&
|
||||
$this->has(Mode::DBAVAILABLE) &&
|
||||
$this->has(Mode::DBCONFIGAVAILABLE) &&
|
||||
$this->has(Mode::MAINTENANCEDISABLED);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ HELP;
|
|||
$this->out('Options: ' . var_export($this->options, true));
|
||||
}
|
||||
|
||||
if (!$this->appMode->has(App\Mode::DBCONFIGAVAILABLE)) {
|
||||
if (!$this->appMode->has(App\Mode::DBAVAILABLE)) {
|
||||
$this->out('Database isn\'t ready or populated yet, database cache won\'t be available');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -115,10 +115,6 @@ HELP;
|
|||
throw new CommandArgsException('Too many arguments');
|
||||
}
|
||||
|
||||
if (!$this->appMode->has(App\Mode::DBCONFIGAVAILABLE)) {
|
||||
$this->out('Database isn\'t ready or populated yet, showing file config only');
|
||||
}
|
||||
|
||||
if (count($this->args) == 3) {
|
||||
$cat = $this->getArgument(0);
|
||||
$key = $this->getArgument(1);
|
||||
|
|
@ -157,7 +153,7 @@ HELP;
|
|||
|
||||
if (count($this->args) == 1) {
|
||||
$cat = $this->getArgument(0);
|
||||
$this->config->load($cat);
|
||||
$this->config->reload();
|
||||
$configCache = $this->config->getCache();
|
||||
|
||||
if ($configCache->get($cat) !== null) {
|
||||
|
|
@ -178,11 +174,7 @@ HELP;
|
|||
}
|
||||
|
||||
if (count($this->args) == 0) {
|
||||
$this->config->load();
|
||||
|
||||
if ($this->config->get('system', 'config_adapter') == 'jit' && $this->appMode->has(App\Mode::DBCONFIGAVAILABLE)) {
|
||||
$this->out('Warning: The JIT (Just In Time) Config adapter doesn\'t support loading the entire configuration, showing file config only');
|
||||
}
|
||||
$this->config->reload();
|
||||
|
||||
$config = $this->config->getCache()->getAll();
|
||||
foreach ($config as $cat => $section) {
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ HELP;
|
|||
$this->out('Options: ' . var_export($this->options, true));
|
||||
}
|
||||
|
||||
if (!$this->appMode->has(App\Mode::DBCONFIGAVAILABLE)) {
|
||||
if (!$this->appMode->has(App\Mode::DBAVAILABLE)) {
|
||||
$this->out('Database isn\'t ready or populated yet, database cache won\'t be available');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -100,16 +100,20 @@ HELP;
|
|||
|
||||
$enabled = intval($this->getArgument(0));
|
||||
|
||||
$this->config->set('system', 'maintenance', $enabled);
|
||||
$transactionConfig = $this->config->beginTransaction();
|
||||
|
||||
$transactionConfig->set('system', 'maintenance', $enabled);
|
||||
|
||||
$reason = $this->getArgument(1);
|
||||
|
||||
if ($enabled && $this->getArgument(1)) {
|
||||
$this->config->set('system', 'maintenance_reason', $this->getArgument(1));
|
||||
$transactionConfig->set('system', 'maintenance_reason', $this->getArgument(1));
|
||||
} else {
|
||||
$this->config->set('system', 'maintenance_reason', '');
|
||||
$transactionConfig->delete('system', 'maintenance_reason');
|
||||
}
|
||||
|
||||
$transactionConfig->commit();
|
||||
|
||||
if ($enabled) {
|
||||
$mode_str = "maintenance mode";
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -101,9 +101,10 @@ HELP;
|
|||
$old_host = str_replace('http://', '@', Strings::normaliseLink($old_url));
|
||||
|
||||
$this->out('Entering maintenance mode');
|
||||
$this->config->set('system', 'maintenance', true);
|
||||
$this->config->set('system', 'maintenance_reason', 'Relocating node to ' . $new_url);
|
||||
|
||||
$this->config->beginTransaction()
|
||||
->set('system', 'maintenance', true)
|
||||
->set('system', 'maintenance_reason', 'Relocating node to ' . $new_url)
|
||||
->commit();
|
||||
try {
|
||||
if (!$this->database->transaction()) {
|
||||
throw new \Exception('Unable to start a transaction, please retry later.');
|
||||
|
|
@ -189,8 +190,10 @@ HELP;
|
|||
return 1;
|
||||
} finally {
|
||||
$this->out('Leaving maintenance mode');
|
||||
$this->config->set('system', 'maintenance', false);
|
||||
$this->config->set('system', 'maintenance_reason', '');
|
||||
$this->config->beginTransaction()
|
||||
->set('system', 'maintenance', false)
|
||||
->delete('system', 'maintenance_reason')
|
||||
->commit();
|
||||
}
|
||||
|
||||
// send relocate
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
namespace Friendica\Core;
|
||||
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Util\Strings;
|
||||
|
|
@ -85,15 +84,19 @@ class Addon
|
|||
public static function getAdminList()
|
||||
{
|
||||
$addons_admin = [];
|
||||
$addonsAdminStmt = DBA::select('addon', ['name'], ['plugin_admin' => 1], ['order' => ['name']]);
|
||||
while ($addon = DBA::fetch($addonsAdminStmt)) {
|
||||
$addons_admin[$addon['name']] = [
|
||||
'url' => 'admin/addons/' . $addon['name'],
|
||||
'name' => $addon['name'],
|
||||
$addons = DI::config()->get('addons');
|
||||
ksort($addons);
|
||||
foreach ($addons as $name => $data) {
|
||||
if (empty($data['admin'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$addons_admin[$name] = [
|
||||
'url' => 'admin/addons/' . $name,
|
||||
'name' => $name,
|
||||
'class' => 'addon'
|
||||
];
|
||||
}
|
||||
DBA::close($addonsAdminStmt);
|
||||
|
||||
return $addons_admin;
|
||||
}
|
||||
|
|
@ -113,8 +116,7 @@ class Addon
|
|||
*/
|
||||
public static function loadAddons()
|
||||
{
|
||||
$installed_addons = DBA::selectToArray('addon', ['name'], ['installed' => true]);
|
||||
self::$addons = array_column($installed_addons, 'name');
|
||||
self::$addons = array_keys(DI::config()->get('addons') ?? []);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -129,7 +131,7 @@ class Addon
|
|||
$addon = Strings::sanitizeFilePathItem($addon);
|
||||
|
||||
Logger::debug("Addon {addon}: {action}", ['action' => 'uninstall', 'addon' => $addon]);
|
||||
DBA::delete('addon', ['name' => $addon]);
|
||||
DI::config()->delete('addons', $addon);
|
||||
|
||||
@include_once('addon/' . $addon . '/' . $addon . '.php');
|
||||
if (function_exists($addon . '_uninstall')) {
|
||||
|
|
@ -168,12 +170,9 @@ class Addon
|
|||
$func(DI::app());
|
||||
}
|
||||
|
||||
DBA::insert('addon', [
|
||||
'name' => $addon,
|
||||
'installed' => true,
|
||||
'timestamp' => $t,
|
||||
'plugin_admin' => function_exists($addon . '_addon_admin'),
|
||||
'hidden' => file_exists('addon/' . $addon . '/.hidden')
|
||||
DI::config()->set('addons', $addon, [
|
||||
'last_update' => $t,
|
||||
'admin' => function_exists($addon . '_addon_admin'),
|
||||
]);
|
||||
|
||||
if (!self::isEnabled($addon)) {
|
||||
|
|
@ -190,20 +189,20 @@ class Addon
|
|||
*/
|
||||
public static function reload()
|
||||
{
|
||||
$addons = DBA::selectToArray('addon', [], ['installed' => true]);
|
||||
$addons = DI::config()->get('addons');
|
||||
|
||||
foreach ($addons as $addon) {
|
||||
$addonname = Strings::sanitizeFilePathItem(trim($addon['name']));
|
||||
foreach ($addons as $name => $data) {
|
||||
$addonname = Strings::sanitizeFilePathItem(trim($name));
|
||||
$addon_file_path = 'addon/' . $addonname . '/' . $addonname . '.php';
|
||||
if (file_exists($addon_file_path) && $addon['timestamp'] == filemtime($addon_file_path)) {
|
||||
if (file_exists($addon_file_path) && $data['last_update'] == filemtime($addon_file_path)) {
|
||||
// Addon unmodified, skipping
|
||||
continue;
|
||||
}
|
||||
|
||||
Logger::debug("Addon {addon}: {action}", ['action' => 'reload', 'addon' => $addon['name']]);
|
||||
Logger::debug("Addon {addon}: {action}", ['action' => 'reload', 'addon' => $name]);
|
||||
|
||||
self::uninstall($addon['name']);
|
||||
self::install($addon['name']);
|
||||
self::uninstall($name);
|
||||
self::install($name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -313,11 +312,9 @@ class Addon
|
|||
public static function getVisibleList(): array
|
||||
{
|
||||
$visible_addons = [];
|
||||
$stmt = DBA::select('addon', ['name'], ['hidden' => false, 'installed' => true]);
|
||||
if (DBA::isResult($stmt)) {
|
||||
foreach (DBA::toArray($stmt) as $addon) {
|
||||
$visible_addons[] = $addon['name'];
|
||||
}
|
||||
$addons = DI::config()->get('addons');
|
||||
foreach ($addons as $name => $data) {
|
||||
$visible_addons[] = $name;
|
||||
}
|
||||
|
||||
return $visible_addons;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
namespace Friendica\Core\Config\Capability;
|
||||
|
||||
use Friendica\Core\Config\Exception\ConfigPersistenceException;
|
||||
use Friendica\Core\Config\Util\ConfigFileManager;
|
||||
use Friendica\Core\Config\ValueObject\Cache;
|
||||
|
||||
/**
|
||||
|
|
@ -30,36 +31,46 @@ use Friendica\Core\Config\ValueObject\Cache;
|
|||
interface IManageConfigValues
|
||||
{
|
||||
/**
|
||||
* Loads all configuration values of family into a cached storage.
|
||||
* Reloads all configuration values (from filesystem and environment variables)
|
||||
*
|
||||
* All configuration values of the system are stored in the cache.
|
||||
*
|
||||
* @param string $cat The category of the configuration value
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws ConfigPersistenceException In case the persistence layer throws errors
|
||||
*/
|
||||
public function load(string $cat = 'config');
|
||||
public function reload();
|
||||
|
||||
/**
|
||||
* Get a particular user's config variable given the category name
|
||||
* ($cat) and a $key.
|
||||
*
|
||||
* Get a particular config value from the given category ($cat)
|
||||
* and the $key from a cached storage either from the database or from the cache.
|
||||
*
|
||||
* @param string $cat The category of the configuration value
|
||||
* @param string $key The configuration key to query
|
||||
* @param string $cat The category of the configuration value
|
||||
* @param ?string $key The configuration key to query (if null, the whole array at the category will get returned)
|
||||
* @param mixed $default_value Deprecated, use `Config->get($cat, $key, null, $refresh) ?? $default_value` instead
|
||||
* @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false)
|
||||
*
|
||||
* @return mixed Stored value or null if it does not exist
|
||||
*
|
||||
* @throws ConfigPersistenceException In case the persistence layer throws errors
|
||||
*
|
||||
*/
|
||||
public function get(string $cat, string $key, $default_value = null, bool $refresh = false);
|
||||
public function get(string $cat, string $key = null, $default_value = null);
|
||||
|
||||
/**
|
||||
* Load all configuration values from a given cache and saves it back in the configuration node store
|
||||
* @see ConfigFileManager::CONFIG_DATA_FILE
|
||||
*
|
||||
* All configuration values of the system are stored in the cache.
|
||||
*
|
||||
* @param Cache $cache a new cache
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws ConfigPersistenceException In case the persistence layer throws errors
|
||||
*/
|
||||
public function load(Cache $cache);
|
||||
|
||||
/**
|
||||
* Sets a configuration value for system config
|
||||
|
|
@ -78,6 +89,15 @@ interface IManageConfigValues
|
|||
*/
|
||||
public function set(string $cat, string $key, $value): bool;
|
||||
|
||||
/**
|
||||
* Creates a transactional config value store, which is used to set a bunch of values at once
|
||||
*
|
||||
* It relies on the current instance, so after save(), the values of this config class will get altered at once too.
|
||||
*
|
||||
* @return ISetConfigValuesTransactionally
|
||||
*/
|
||||
public function beginTransaction(): ISetConfigValuesTransactionally;
|
||||
|
||||
/**
|
||||
* Deletes the given key from the system configuration.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Core\Config\Capability;
|
||||
|
||||
use Friendica\Core\Config\Exception\ConfigPersistenceException;
|
||||
|
||||
/**
|
||||
* Interface for transactional saving of config values
|
||||
* It buffers every set/delete until "save()" is called
|
||||
*/
|
||||
interface ISetConfigValuesTransactionally
|
||||
{
|
||||
/**
|
||||
* Sets a configuration value for system config
|
||||
*
|
||||
* Stores a config value ($value) in the category ($cat) under the key ($key)
|
||||
*
|
||||
* Note: Please do not store booleans - convert to 0/1 integer values!
|
||||
*
|
||||
* @param string $cat The category of the configuration value
|
||||
* @param string $key The configuration key to set
|
||||
* @param mixed $value The value to store
|
||||
*
|
||||
* @return static the current instance
|
||||
*/
|
||||
public function set(string $cat, string $key, $value): self;
|
||||
|
||||
/**
|
||||
* Deletes the given key from the system configuration.
|
||||
*
|
||||
* @param string $cat The category of the configuration value
|
||||
* @param string $key The configuration key to delete
|
||||
*
|
||||
* @return static the current instance
|
||||
*
|
||||
*/
|
||||
public function delete(string $cat, string $key): self;
|
||||
|
||||
/**
|
||||
* Commits the changes of the current transaction
|
||||
*
|
||||
* @throws ConfigPersistenceException In case the persistence layer throws errors
|
||||
*/
|
||||
public function commit(): void;
|
||||
}
|
||||
|
|
@ -21,12 +21,12 @@
|
|||
|
||||
namespace Friendica\Core\Config\Factory;
|
||||
|
||||
use Friendica\Core\Config\Capability;
|
||||
use Friendica\Core\Config\Repository;
|
||||
use Friendica\Core\Config\Type;
|
||||
use Friendica\Core\Config\Util;
|
||||
use Friendica\Core\Config\ValueObject\Cache;
|
||||
|
||||
/**
|
||||
* The config factory for creating either the cache or the whole model
|
||||
*/
|
||||
class Config
|
||||
{
|
||||
/**
|
||||
|
|
@ -54,9 +54,9 @@ class Config
|
|||
* @param string $basePath The basepath of FRIENDICA
|
||||
* @param array $server The $_SERVER array
|
||||
*
|
||||
* @return Util\ConfigFileLoader
|
||||
* @return Util\ConfigFileManager
|
||||
*/
|
||||
public function createConfigFileLoader(string $basePath, array $server = []): Util\ConfigFileLoader
|
||||
public function createConfigFileManager(string $basePath, array $server = []): Util\ConfigFileManager
|
||||
{
|
||||
if (!empty($server[self::CONFIG_DIR_ENV]) && is_dir($server[self::CONFIG_DIR_ENV])) {
|
||||
$configDir = $server[self::CONFIG_DIR_ENV];
|
||||
|
|
@ -65,37 +65,19 @@ class Config
|
|||
}
|
||||
$staticDir = $basePath . DIRECTORY_SEPARATOR . self::STATIC_DIR;
|
||||
|
||||
return new Util\ConfigFileLoader($basePath, $configDir, $staticDir);
|
||||
return new Util\ConfigFileManager($basePath, $configDir, $staticDir, $server);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Util\ConfigFileLoader $loader The Config Cache loader (INI/config/.htconfig)
|
||||
* @param array $server
|
||||
* @param Util\ConfigFileManager $configFileManager The Config Cache manager (INI/config/.htconfig)
|
||||
*
|
||||
* @return Cache
|
||||
*/
|
||||
public function createCache(Util\ConfigFileLoader $loader, array $server = []): Cache
|
||||
public function createCache(Util\ConfigFileManager $configFileManager): Cache
|
||||
{
|
||||
$configCache = new Cache();
|
||||
$loader->setupCache($configCache, $server);
|
||||
$configFileManager->setupCache($configCache);
|
||||
|
||||
return $configCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Cache $configCache The config cache of this adapter
|
||||
* @param Repository\Config $configRepo The configuration repository
|
||||
*
|
||||
* @return Capability\IManageConfigValues
|
||||
*/
|
||||
public function create(Cache $configCache, Repository\Config $configRepo)
|
||||
{
|
||||
if ($configCache->get('system', 'config_adapter') === 'preload') {
|
||||
$configuration = new Type\PreloadConfig($configCache, $configRepo);
|
||||
} else {
|
||||
$configuration = new Type\JitConfig($configCache, $configRepo);
|
||||
}
|
||||
|
||||
return $configuration;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
126
src/Core/Config/Model/Config.php
Normal file
126
src/Core/Config/Model/Config.php
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Core\Config\Model;
|
||||
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\Config\Capability\ISetConfigValuesTransactionally;
|
||||
use Friendica\Core\Config\Exception\ConfigFileException;
|
||||
use Friendica\Core\Config\Exception\ConfigPersistenceException;
|
||||
use Friendica\Core\Config\Util\ConfigFileManager;
|
||||
use Friendica\Core\Config\ValueObject\Cache;
|
||||
|
||||
/**
|
||||
* Configuration model, which manages the whole system configuration
|
||||
*/
|
||||
class Config implements IManageConfigValues
|
||||
{
|
||||
/** @var Cache */
|
||||
protected $configCache;
|
||||
|
||||
/** @var ConfigFileManager */
|
||||
protected $configFileManager;
|
||||
|
||||
/**
|
||||
* @param ConfigFileManager $configFileManager The configuration file manager to save back configs
|
||||
* @param Cache $configCache The configuration cache (based on the config-files)
|
||||
*/
|
||||
public function __construct(ConfigFileManager $configFileManager, Cache $configCache)
|
||||
{
|
||||
$this->configFileManager = $configFileManager;
|
||||
$this->configCache = $configCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getCache(): Cache
|
||||
{
|
||||
return $this->configCache;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function beginTransaction(): ISetConfigValuesTransactionally
|
||||
{
|
||||
return new ConfigTransaction($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the current Configuration back into the data config.
|
||||
* @see ConfigFileManager::CONFIG_DATA_FILE
|
||||
*/
|
||||
protected function save()
|
||||
{
|
||||
try {
|
||||
$this->configFileManager->saveData($this->configCache);
|
||||
} catch (ConfigFileException $e) {
|
||||
throw new ConfigPersistenceException('Cannot save config', $e);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function reload()
|
||||
{
|
||||
$configCache = new Cache();
|
||||
|
||||
try {
|
||||
$this->configFileManager->setupCache($configCache);
|
||||
} catch (ConfigFileException $e) {
|
||||
throw new ConfigPersistenceException('Cannot reload config', $e);
|
||||
}
|
||||
$this->configCache = $configCache;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function load(Cache $cache)
|
||||
{
|
||||
$this->configCache = $cache;
|
||||
$this->save();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function get(string $cat, string $key = null, $default_value = null)
|
||||
{
|
||||
return $this->configCache->get($cat, $key) ?? $default_value;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function set(string $cat, string $key, $value): bool
|
||||
{
|
||||
if ($this->configCache->set($cat, $key, $value, Cache::SOURCE_DATA)) {
|
||||
$this->save();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function delete(string $cat, string $key): bool
|
||||
{
|
||||
if ($this->configCache->delete($cat, $key, Cache::SOURCE_DATA)) {
|
||||
$this->save();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
81
src/Core/Config/Model/ConfigTransaction.php
Normal file
81
src/Core/Config/Model/ConfigTransaction.php
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Core\Config\Model;
|
||||
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\Config\Capability\ISetConfigValuesTransactionally;
|
||||
use Friendica\Core\Config\Exception\ConfigPersistenceException;
|
||||
use Friendica\Core\Config\ValueObject\Cache;
|
||||
|
||||
/**
|
||||
* Transaction class for configurations, which sets values into a temporary buffer until "save()" is called
|
||||
*/
|
||||
class ConfigTransaction implements ISetConfigValuesTransactionally
|
||||
{
|
||||
/** @var IManageConfigValues */
|
||||
protected $config;
|
||||
/** @var Cache */
|
||||
protected $cache;
|
||||
/** @var bool field to check if something is to save */
|
||||
protected $changedConfig = false;
|
||||
|
||||
public function __construct(IManageConfigValues $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->cache = clone $config->getCache();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function set(string $cat, string $key, $value): ISetConfigValuesTransactionally
|
||||
{
|
||||
$this->cache->set($cat, $key, $value, Cache::SOURCE_DATA);
|
||||
$this->changedConfig = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function delete(string $cat, string $key): ISetConfigValuesTransactionally
|
||||
{
|
||||
$this->cache->delete($cat, $key, Cache::SOURCE_DATA);
|
||||
$this->changedConfig = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function commit(): void
|
||||
{
|
||||
// If nothing changed, just do nothing :)
|
||||
if (!$this->changedConfig) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->config->load($this->cache);
|
||||
$this->cache = clone $this->config->getCache();
|
||||
} catch (\Exception $e) {
|
||||
throw new ConfigPersistenceException('Cannot save config', $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,191 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Core\Config\Repository;
|
||||
|
||||
use Friendica\App\Mode;
|
||||
use Friendica\Core\Config\Exception\ConfigPersistenceException;
|
||||
use Friendica\Core\Config\Util\ValueConversion;
|
||||
use Friendica\Database\Database;
|
||||
|
||||
/**
|
||||
* The Config Repository, which is using the general DB-model backend for configs
|
||||
*/
|
||||
class Config
|
||||
{
|
||||
/** @var Database */
|
||||
protected $db;
|
||||
/** @var Mode */
|
||||
protected $mode;
|
||||
|
||||
public function __construct(Database $db, Mode $mode)
|
||||
{
|
||||
$this->db = $db;
|
||||
$this->mode = $mode;
|
||||
}
|
||||
|
||||
protected static $table_name = 'config';
|
||||
|
||||
/**
|
||||
* Checks if the model is currently connected
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isConnected(): bool
|
||||
{
|
||||
return $this->db->isConnected() && !$this->mode->isInstall();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all configuration values and returns the loaded category as an array.
|
||||
*
|
||||
* @param string|null $cat The category of the configuration values to load
|
||||
*
|
||||
* @return array The config array
|
||||
*
|
||||
* @throws ConfigPersistenceException In case the persistence layer throws errors
|
||||
*/
|
||||
public function load(?string $cat = null): array
|
||||
{
|
||||
$return = [];
|
||||
|
||||
try {
|
||||
if (empty($cat)) {
|
||||
$configs = $this->db->select(static::$table_name, ['cat', 'v', 'k']);
|
||||
} else {
|
||||
$configs = $this->db->select(static::$table_name, ['cat', 'v', 'k'], ['cat' => $cat]);
|
||||
}
|
||||
|
||||
while ($config = $this->db->fetch($configs)) {
|
||||
$key = $config['k'];
|
||||
$value = ValueConversion::toConfigValue($config['v']);
|
||||
|
||||
// just save it in case it is set
|
||||
if (isset($value)) {
|
||||
$return[$config['cat']][$key] = $value;
|
||||
}
|
||||
}
|
||||
} catch (\Exception $exception) {
|
||||
throw new ConfigPersistenceException(sprintf('Cannot load config category %s', $cat), $exception);
|
||||
} finally {
|
||||
$this->db->close($configs);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a particular, system-wide config variable out of the DB with the
|
||||
* given category name ($cat) and a key ($key).
|
||||
*
|
||||
* Note: Boolean variables are defined as 0/1 in the database
|
||||
*
|
||||
* @param string $cat The category of the configuration value
|
||||
* @param string $key The configuration key to query
|
||||
*
|
||||
* @return array|string|null Stored value or null if it does not exist
|
||||
*
|
||||
* @throws ConfigPersistenceException In case the persistence layer throws errors
|
||||
*/
|
||||
public function get(string $cat, string $key)
|
||||
{
|
||||
if (!$this->isConnected()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
$config = $this->db->selectFirst(static::$table_name, ['v'], ['cat' => $cat, 'k' => $key]);
|
||||
if ($this->db->isResult($config)) {
|
||||
$value = ValueConversion::toConfigValue($config['v']);
|
||||
|
||||
// just return it in case it is set
|
||||
if (isset($value)) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
} catch (\Exception $exception) {
|
||||
throw new ConfigPersistenceException(sprintf('Cannot get config with category %s and key %s', $cat, $key), $exception);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a config value ($value) in the category ($cat) under the key ($key).
|
||||
*
|
||||
* Note: Please do not store booleans - convert to 0/1 integer values!
|
||||
*
|
||||
* @param string $cat The category of the configuration value
|
||||
* @param string $key The configuration key to set
|
||||
* @param mixed $value The value to store
|
||||
*
|
||||
* @return bool Operation success
|
||||
*
|
||||
* @throws ConfigPersistenceException In case the persistence layer throws errors
|
||||
*/
|
||||
public function set(string $cat, string $key, $value): bool
|
||||
{
|
||||
if (!$this->isConnected()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We store our setting values in a string variable.
|
||||
// So we have to do the conversion here so that the compare below works.
|
||||
// The exception are array values.
|
||||
$compare_value = (!is_array($value) ? (string)$value : $value);
|
||||
$stored_value = $this->get($cat, $key);
|
||||
|
||||
if (isset($stored_value) && ($stored_value === $compare_value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$dbValue = ValueConversion::toDbValue($value);
|
||||
|
||||
try {
|
||||
return $this->db->update(static::$table_name, ['v' => $dbValue], ['cat' => $cat, 'k' => $key], true);
|
||||
} catch (\Exception $exception) {
|
||||
throw new ConfigPersistenceException(sprintf('Cannot set config with category %s and key %s', $cat, $key), $exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the configured value from the database.
|
||||
*
|
||||
* @param string $cat The category of the configuration value
|
||||
* @param string $key The configuration key to delete
|
||||
*
|
||||
* @return bool Operation success
|
||||
*
|
||||
* @throws ConfigPersistenceException In case the persistence layer throws errors
|
||||
*/
|
||||
public function delete(string $cat, string $key): bool
|
||||
{
|
||||
if (!$this->isConnected()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return $this->db->delete(static::$table_name, ['cat' => $cat, 'k' => $key]);
|
||||
} catch (\Exception $exception) {
|
||||
throw new ConfigPersistenceException(sprintf('Cannot delete config with category %s and key %s', $cat, $key), $exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Core\Config\Type;
|
||||
|
||||
use Friendica\Core\Config\Repository\Config;
|
||||
use Friendica\Core\Config\ValueObject\Cache;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
|
||||
/**
|
||||
* This class is responsible for all system-wide configuration values in Friendica
|
||||
* There are two types of storage
|
||||
* - The Config-Files (loaded into the FileCache @see Cache)
|
||||
* - The Config-Repository (per Config-Repository @see Config )
|
||||
*/
|
||||
abstract class AbstractConfig implements IManageConfigValues
|
||||
{
|
||||
/**
|
||||
* @var Cache
|
||||
*/
|
||||
protected $configCache;
|
||||
|
||||
/**
|
||||
* @var Config
|
||||
*/
|
||||
protected $configRepo;
|
||||
|
||||
/**
|
||||
* @param Cache $configCache The configuration cache (based on the config-files)
|
||||
* @param Config $configRepo The configuration repository
|
||||
*/
|
||||
public function __construct(Cache $configCache, Config $configRepo)
|
||||
{
|
||||
$this->configCache = $configCache;
|
||||
$this->configRepo = $configRepo;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getCache(): Cache
|
||||
{
|
||||
return $this->configCache;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,139 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Core\Config\Type;
|
||||
|
||||
use Friendica\Core\Config\ValueObject\Cache;
|
||||
use Friendica\Core\Config\Repository\Config;
|
||||
|
||||
/**
|
||||
* This class implements the Just-In-Time configuration, which will cache
|
||||
* config values in a cache, once they are retrieved.
|
||||
*
|
||||
* Default Configuration type.
|
||||
* Provides the best performance for pages loading few configuration variables.
|
||||
*/
|
||||
class JitConfig extends AbstractConfig
|
||||
{
|
||||
/**
|
||||
* @var array Array of already loaded db values (even if there was no value)
|
||||
*/
|
||||
private $db_loaded;
|
||||
|
||||
/**
|
||||
* @param Cache $configCache The configuration cache (based on the config-files)
|
||||
* @param Config $configRepo The configuration model
|
||||
*/
|
||||
public function __construct(Cache $configCache, Config $configRepo)
|
||||
{
|
||||
parent::__construct($configCache, $configRepo);
|
||||
$this->db_loaded = [];
|
||||
|
||||
$this->load();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function load(string $cat = 'config')
|
||||
{
|
||||
// If not connected, do nothing
|
||||
if (!$this->configRepo->isConnected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$config = $this->configRepo->load($cat);
|
||||
|
||||
if (!empty($config[$cat])) {
|
||||
foreach ($config[$cat] as $key => $value) {
|
||||
$this->db_loaded[$cat][$key] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// load the whole category out of the DB into the cache
|
||||
$this->configCache->load($config, Cache::SOURCE_DB);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get(string $cat, string $key, $default_value = null, bool $refresh = false)
|
||||
{
|
||||
// if the value isn't loaded or refresh is needed, load it to the cache
|
||||
if ($this->configRepo->isConnected() &&
|
||||
(empty($this->db_loaded[$cat][$key]) ||
|
||||
$refresh)) {
|
||||
$dbValue = $this->configRepo->get($cat, $key);
|
||||
|
||||
if (isset($dbValue)) {
|
||||
$this->configCache->set($cat, $key, $dbValue, Cache::SOURCE_DB);
|
||||
unset($dbValue);
|
||||
}
|
||||
|
||||
$this->db_loaded[$cat][$key] = true;
|
||||
}
|
||||
|
||||
// use the config cache for return
|
||||
$result = $this->configCache->get($cat, $key);
|
||||
|
||||
return (isset($result)) ? $result : $default_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function set(string $cat, string $key, $value): bool
|
||||
{
|
||||
// set the cache first
|
||||
$cached = $this->configCache->set($cat, $key, $value, Cache::SOURCE_DB);
|
||||
|
||||
// If there is no connected adapter, we're finished
|
||||
if (!$this->configRepo->isConnected()) {
|
||||
return $cached;
|
||||
}
|
||||
|
||||
$stored = $this->configRepo->set($cat, $key, $value);
|
||||
|
||||
$this->db_loaded[$cat][$key] = $stored;
|
||||
|
||||
return $cached && $stored;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function delete(string $cat, string $key): bool
|
||||
{
|
||||
$cacheRemoved = $this->configCache->delete($cat, $key);
|
||||
|
||||
if (isset($this->db_loaded[$cat][$key])) {
|
||||
unset($this->db_loaded[$cat][$key]);
|
||||
}
|
||||
|
||||
if (!$this->configRepo->isConnected()) {
|
||||
return $cacheRemoved;
|
||||
}
|
||||
|
||||
$storeRemoved = $this->configRepo->delete($cat, $key);
|
||||
|
||||
return $cacheRemoved || $storeRemoved;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Core\Config\Type;
|
||||
|
||||
use Friendica\Core\Config\ValueObject\Cache;
|
||||
use Friendica\Core\Config\Repository\Config;
|
||||
|
||||
/**
|
||||
* This class implements the preload configuration, which will cache
|
||||
* all config values per call in a cache.
|
||||
*
|
||||
* Minimizes the number of database queries to retrieve configuration values at the cost of memory.
|
||||
*/
|
||||
class PreloadConfig extends AbstractConfig
|
||||
{
|
||||
/** @var bool */
|
||||
private $config_loaded;
|
||||
|
||||
/**
|
||||
* @param Cache $configCache The configuration cache (based on the config-files)
|
||||
* @param Config $configRepo The configuration model
|
||||
*/
|
||||
public function __construct(Cache $configCache, Config $configRepo)
|
||||
{
|
||||
parent::__construct($configCache, $configRepo);
|
||||
$this->config_loaded = false;
|
||||
|
||||
$this->load();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* This loads all config values everytime load is called
|
||||
*/
|
||||
public function load(string $cat = 'config')
|
||||
{
|
||||
// Don't load the whole configuration twice
|
||||
if ($this->config_loaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If not connected, do nothing
|
||||
if (!$this->configRepo->isConnected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$config = $this->configRepo->load();
|
||||
$this->config_loaded = true;
|
||||
|
||||
// load the whole category out of the DB into the cache
|
||||
$this->configCache->load($config, Cache::SOURCE_DB);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get(string $cat, string $key, $default_value = null, bool $refresh = false)
|
||||
{
|
||||
if ($refresh) {
|
||||
if ($this->configRepo->isConnected()) {
|
||||
$config = $this->configRepo->get($cat, $key);
|
||||
if (isset($config)) {
|
||||
$this->configCache->set($cat, $key, $config, Cache::SOURCE_DB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// use the config cache for return
|
||||
$result = $this->configCache->get($cat, $key);
|
||||
|
||||
return (isset($result)) ? $result : $default_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function set(string $cat, string $key, $value): bool
|
||||
{
|
||||
if (!$this->config_loaded) {
|
||||
$this->load();
|
||||
}
|
||||
|
||||
// set the cache first
|
||||
$cached = $this->configCache->set($cat, $key, $value, Cache::SOURCE_DB);
|
||||
|
||||
// If there is no connected adapter, we're finished
|
||||
if (!$this->configRepo->isConnected()) {
|
||||
return $cached;
|
||||
}
|
||||
|
||||
$stored = $this->configRepo->set($cat, $key, $value);
|
||||
|
||||
return $cached && $stored;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function delete(string $cat, string $key): bool
|
||||
{
|
||||
if ($this->config_loaded) {
|
||||
$this->load();
|
||||
}
|
||||
|
||||
$cacheRemoved = $this->configCache->delete($cat, $key);
|
||||
|
||||
if (!$this->configRepo->isConnected()) {
|
||||
return $cacheRemoved;
|
||||
}
|
||||
|
||||
$storeRemoved = $this->configRepo->delete($cat, $key);
|
||||
|
||||
return $cacheRemoved || $storeRemoved;
|
||||
}
|
||||
}
|
||||
|
|
@ -26,22 +26,15 @@ use Friendica\Core\Config\Exception\ConfigFileException;
|
|||
use Friendica\Core\Config\ValueObject\Cache;
|
||||
|
||||
/**
|
||||
* The ConfigFileLoader loads config-files and stores them in a ConfigCache ( @see Cache )
|
||||
* The ConfigFileLoader loads and saves config-files and stores them in a ConfigCache ( @see Cache )
|
||||
*
|
||||
* It is capable of loading the following config files:
|
||||
* - *.config.php (current)
|
||||
* - *.ini.php (deprecated)
|
||||
* - *.htconfig.php (deprecated)
|
||||
*/
|
||||
class ConfigFileLoader
|
||||
class ConfigFileManager
|
||||
{
|
||||
/**
|
||||
* The default name of the user defined ini file
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const CONFIG_INI = 'local';
|
||||
|
||||
/**
|
||||
* The default name of the user defined legacy config file
|
||||
*
|
||||
|
|
@ -49,6 +42,13 @@ class ConfigFileLoader
|
|||
*/
|
||||
const CONFIG_HTCONFIG = 'htconfig';
|
||||
|
||||
/**
|
||||
* The config file, where overrides per admin page/console are saved at
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const CONFIG_DATA_FILE = 'node.config.php';
|
||||
|
||||
/**
|
||||
* The sample string inside the configs, which shouldn't get loaded
|
||||
*
|
||||
|
|
@ -69,16 +69,22 @@ class ConfigFileLoader
|
|||
*/
|
||||
private $staticDir;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $server;
|
||||
|
||||
/**
|
||||
* @param string $baseDir The base
|
||||
* @param string $configDir
|
||||
* @param string $staticDir
|
||||
*/
|
||||
public function __construct(string $baseDir, string $configDir, string $staticDir)
|
||||
public function __construct(string $baseDir, string $configDir, string $staticDir, array $server = [])
|
||||
{
|
||||
$this->baseDir = $baseDir;
|
||||
$this->configDir = $configDir;
|
||||
$this->staticDir = $staticDir;
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -87,31 +93,33 @@ class ConfigFileLoader
|
|||
* First loads the default value for all the configuration keys, then the legacy configuration files, then the
|
||||
* expected local.config.php
|
||||
*
|
||||
* @param Cache $config The config cache to load to
|
||||
* @param array $server The $_SERVER array
|
||||
* @param bool $raw Setup the raw config format
|
||||
* @param Cache $configCache The config cache to load to
|
||||
* @param bool $raw Set up the raw config format
|
||||
*
|
||||
* @throws ConfigFileException
|
||||
*/
|
||||
public function setupCache(Cache $config, array $server = [], bool $raw = false)
|
||||
public function setupCache(Cache $configCache, bool $raw = false)
|
||||
{
|
||||
// Load static config files first, the order is important
|
||||
$config->load($this->loadStaticConfig('defaults'), Cache::SOURCE_STATIC);
|
||||
$config->load($this->loadStaticConfig('settings'), Cache::SOURCE_STATIC);
|
||||
$configCache->load($this->loadStaticConfig('defaults'), Cache::SOURCE_STATIC);
|
||||
$configCache->load($this->loadStaticConfig('settings'), Cache::SOURCE_STATIC);
|
||||
|
||||
// try to load the legacy config first
|
||||
$config->load($this->loadLegacyConfig('htpreconfig'), Cache::SOURCE_FILE);
|
||||
$config->load($this->loadLegacyConfig('htconfig'), Cache::SOURCE_FILE);
|
||||
$configCache->load($this->loadLegacyConfig('htpreconfig'), Cache::SOURCE_FILE);
|
||||
$configCache->load($this->loadLegacyConfig('htconfig'), Cache::SOURCE_FILE);
|
||||
|
||||
// Now load every other config you find inside the 'config/' directory
|
||||
$this->loadCoreConfig($config);
|
||||
$this->loadCoreConfig($configCache);
|
||||
|
||||
$config->load($this->loadEnvConfig($server), Cache::SOURCE_ENV);
|
||||
// Now load the node.config.php file with the node specific config values (based on admin gui/console actions)
|
||||
$this->loadDataConfig($configCache);
|
||||
|
||||
$configCache->load($this->loadEnvConfig(), Cache::SOURCE_ENV);
|
||||
|
||||
// In case of install mode, add the found basepath (because there isn't a basepath set yet
|
||||
if (!$raw && empty($config->get('system', 'basepath'))) {
|
||||
if (!$raw && empty($configCache->get('system', 'basepath'))) {
|
||||
// Setting at least the basepath we know
|
||||
$config->set('system', 'basepath', $this->baseDir, Cache::SOURCE_FILE);
|
||||
$configCache->set('system', 'basepath', $this->baseDir, Cache::SOURCE_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -131,7 +139,7 @@ class ConfigFileLoader
|
|||
|
||||
if (file_exists($configName)) {
|
||||
return $this->loadConfigFile($configName);
|
||||
} elseif (file_exists($iniName)) {
|
||||
} else if (file_exists($iniName)) {
|
||||
return $this->loadINIConfigFile($iniName);
|
||||
} else {
|
||||
return [];
|
||||
|
|
@ -141,20 +149,172 @@ class ConfigFileLoader
|
|||
/**
|
||||
* Tries to load the specified core-configuration into the config cache.
|
||||
*
|
||||
* @param Cache $config The Config cache
|
||||
* @param Cache $configCache The Config cache
|
||||
*
|
||||
* @throws ConfigFileException if the configuration file isn't readable
|
||||
*/
|
||||
private function loadCoreConfig(Cache $config)
|
||||
private function loadCoreConfig(Cache $configCache)
|
||||
{
|
||||
// try to load legacy ini-files first
|
||||
foreach ($this->getConfigFiles(true) as $configFile) {
|
||||
$config->load($this->loadINIConfigFile($configFile), Cache::SOURCE_FILE);
|
||||
$configCache->load($this->loadINIConfigFile($configFile), Cache::SOURCE_FILE);
|
||||
}
|
||||
|
||||
// try to load supported config at last to overwrite it
|
||||
foreach ($this->getConfigFiles() as $configFile) {
|
||||
$config->load($this->loadConfigFile($configFile), Cache::SOURCE_FILE);
|
||||
$configCache->load($this->loadConfigFile($configFile), Cache::SOURCE_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to load the data config file with the overridden data
|
||||
*
|
||||
* @param Cache $configCache The Config cache
|
||||
*
|
||||
* @throws ConfigFileException In case the config file isn't loadable
|
||||
*/
|
||||
private function loadDataConfig(Cache $configCache)
|
||||
{
|
||||
$filename = $this->configDir . '/' . self::CONFIG_DATA_FILE;
|
||||
|
||||
if (file_exists($filename)) {
|
||||
|
||||
// The fallback empty return content
|
||||
$content = '<?php return [];';
|
||||
|
||||
/**
|
||||
* This code-block creates a readonly node.config.php content stream (fopen() with "r")
|
||||
* The stream is locked shared (LOCK_SH), so not exclusively, but the OS knows that there's a lock
|
||||
*
|
||||
* Any exclusive locking (LOCK_EX) would need to wait until all LOCK_SHs are unlocked
|
||||
*/
|
||||
$configStream = fopen($filename, 'r');
|
||||
try {
|
||||
if (flock($configStream, LOCK_SH)) {
|
||||
$content = fread($configStream, filesize($filename));
|
||||
if (!$content) {
|
||||
throw new ConfigFileException(sprintf('Couldn\'t read file %s', $filename));
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
// unlock and close the stream for every circumstances
|
||||
flock($configStream, LOCK_UN);
|
||||
fclose($configStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the content string as PHP code
|
||||
*
|
||||
* @see https://www.php.net/manual/en/function.eval.php
|
||||
*
|
||||
* @note
|
||||
* To leave the PHP mode, we have to use the appropriate PHP tags '?>' as prefix.
|
||||
*/
|
||||
$dataArray = eval('?>' . $content);
|
||||
|
||||
if (is_array($dataArray)) {
|
||||
$configCache->load($dataArray, Cache::SOURCE_DATA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks, if the node.config.php is writable
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function dataIsWritable(): bool
|
||||
{
|
||||
$filename = $this->configDir . '/' . self::CONFIG_DATA_FILE;
|
||||
|
||||
if (file_exists($filename)) {
|
||||
return is_writable($filename);
|
||||
} else {
|
||||
return is_writable($this->configDir);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves overridden config entries back into the data.config.php
|
||||
*
|
||||
* @param Cache $configCache The config cache
|
||||
*
|
||||
* @throws ConfigFileException In case the config file isn't writeable or the data is invalid
|
||||
*/
|
||||
public function saveData(Cache $configCache)
|
||||
{
|
||||
$filename = $this->configDir . '/' . self::CONFIG_DATA_FILE;
|
||||
|
||||
if (file_exists($filename)) {
|
||||
$fileExists = true;
|
||||
} else {
|
||||
$fileExists = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a read-write stream
|
||||
*
|
||||
* @see https://www.php.net/manual/en/function.fopen.php
|
||||
* @note Open the file for reading and writing. If the file does not exist, it is created.
|
||||
* If it exists, it is neither truncated (as opposed to 'w'), nor the call to this function fails
|
||||
* (as is the case with 'x'). The file pointer is positioned on the beginning of the file.
|
||||
*
|
||||
*/
|
||||
if (($configStream = @fopen($filename, 'c+')) === false) {
|
||||
throw new ConfigFileException(sprintf('Cannot open file "%s" in mode c+', $filename));
|
||||
}
|
||||
|
||||
try {
|
||||
// We do want an exclusive lock, so we wait until every LOCK_SH (config reading) is unlocked
|
||||
if (flock($configStream, LOCK_EX)) {
|
||||
|
||||
/**
|
||||
* If the file exists, we read the whole file again to avoid a race condition with concurrent threads that could have modified the file between the first config read of this thread and now
|
||||
* Since we're currently exclusive locked, no other process can now change the config again
|
||||
*/
|
||||
if ($fileExists) {
|
||||
// When reading the config file too fast, we get a wrong filesize, "clearstatcache" prevents that
|
||||
clearstatcache(true, $filename);
|
||||
$content = fread($configStream, filesize($filename));
|
||||
if (!$content) {
|
||||
throw new ConfigFileException(sprintf('Cannot read file %s', $filename));
|
||||
}
|
||||
|
||||
// Event truncating the whole content wouldn't automatically rewind the stream,
|
||||
// so we need to do it manually
|
||||
rewind($configStream);
|
||||
|
||||
$dataArray = eval('?>' . $content);
|
||||
|
||||
// Merge the new content into the existing file based config cache and use it
|
||||
// as the new config cache
|
||||
if (is_array($dataArray)) {
|
||||
$fileConfigCache = new Cache();
|
||||
$fileConfigCache->load($dataArray, Cache::SOURCE_DATA);
|
||||
$configCache = $fileConfigCache->merge($configCache);
|
||||
}
|
||||
}
|
||||
|
||||
// Only SOURCE_DATA is wanted, the rest isn't part of the node.config.php file
|
||||
$data = $configCache->getDataBySource(Cache::SOURCE_DATA);
|
||||
|
||||
$encodedData = ConfigFileTransformer::encode($data);
|
||||
if (!$encodedData) {
|
||||
throw new ConfigFileException('config source cannot get encoded');
|
||||
}
|
||||
|
||||
// Once again to avoid wrong, implicit "filesize" calls during the fwrite() or ftruncate() call
|
||||
clearstatcache(true, $filename);
|
||||
if (!ftruncate($configStream, 0) ||
|
||||
!fwrite($configStream, $encodedData) ||
|
||||
!fflush($configStream)) {
|
||||
throw new ConfigFileException(sprintf('Cannot modify locked file %s', $filename));
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
// unlock and close the stream for every circumstances
|
||||
flock($configStream, LOCK_UN);
|
||||
fclose($configStream);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -172,7 +332,7 @@ class ConfigFileLoader
|
|||
$filepath = $this->baseDir . DIRECTORY_SEPARATOR . // /var/www/html/
|
||||
Addon::DIRECTORY . DIRECTORY_SEPARATOR . // addon/
|
||||
$name . DIRECTORY_SEPARATOR . // openstreetmap/
|
||||
'config'. DIRECTORY_SEPARATOR . // config/
|
||||
'config' . DIRECTORY_SEPARATOR . // config/
|
||||
$name . ".config.php"; // openstreetmap.config.php
|
||||
|
||||
if (file_exists($filepath)) {
|
||||
|
|
@ -185,13 +345,11 @@ class ConfigFileLoader
|
|||
/**
|
||||
* Tries to load environment specific variables, based on the `env.config.php` mapping table
|
||||
*
|
||||
* @param array $server The $_SERVER variable
|
||||
*
|
||||
* @return array The config array (empty if no config was found)
|
||||
*
|
||||
* @throws ConfigFileException if the configuration file isn't readable
|
||||
*/
|
||||
public function loadEnvConfig(array $server): array
|
||||
protected function loadEnvConfig(): array
|
||||
{
|
||||
$filepath = $this->staticDir . DIRECTORY_SEPARATOR . // /var/www/html/static/
|
||||
"env.config.php"; // env.config.php
|
||||
|
|
@ -205,8 +363,8 @@ class ConfigFileLoader
|
|||
$return = [];
|
||||
|
||||
foreach ($envConfig as $envKey => $configStructure) {
|
||||
if (isset($server[$envKey])) {
|
||||
$return[$configStructure[0]][$configStructure[1]] = $server[$envKey];
|
||||
if (isset($this->server[$envKey])) {
|
||||
$return[$configStructure[0]][$configStructure[1]] = $this->server[$envKey];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -231,7 +389,9 @@ class ConfigFileLoader
|
|||
$sampleEnd = self::SAMPLE_END . ($ini ? '.ini.php' : '.config.php');
|
||||
|
||||
foreach ($files as $filename) {
|
||||
if (fnmatch($filePattern, $filename) && substr_compare($filename, $sampleEnd, -strlen($sampleEnd))) {
|
||||
if (fnmatch($filePattern, $filename) &&
|
||||
substr_compare($filename, $sampleEnd, -strlen($sampleEnd)) &&
|
||||
$filename !== self::CONFIG_DATA_FILE) {
|
||||
$found[] = $this->configDir . '/' . $filename;
|
||||
}
|
||||
}
|
||||
|
|
@ -353,12 +513,16 @@ class ConfigFileLoader
|
|||
*/
|
||||
private function loadConfigFile(string $filepath): array
|
||||
{
|
||||
$config = include($filepath);
|
||||
if (file_exists($filepath)) {
|
||||
$config = include $filepath;
|
||||
|
||||
if (!is_array($config)) {
|
||||
throw new ConfigFileException('Error loading config file ' . $filepath);
|
||||
if (!is_array($config)) {
|
||||
throw new ConfigFileException('Error loading config file ' . $filepath);
|
||||
}
|
||||
|
||||
return $config;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
}
|
||||
92
src/Core/Config/Util/ConfigFileTransformer.php
Normal file
92
src/Core/Config/Util/ConfigFileTransformer.php
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Core\Config\Util;
|
||||
|
||||
/**
|
||||
* Util to transform back the config array into a string
|
||||
*/
|
||||
class ConfigFileTransformer
|
||||
{
|
||||
public static function encode(array $data): string
|
||||
{
|
||||
$dataString = '<?php' . PHP_EOL . PHP_EOL;
|
||||
$dataString .= 'return [' . PHP_EOL;
|
||||
|
||||
$categories = array_keys($data);
|
||||
|
||||
foreach ($categories as $category) {
|
||||
if (is_null($data[$category])) {
|
||||
$dataString .= "\t'$category' => null," . PHP_EOL;
|
||||
continue;
|
||||
}
|
||||
|
||||
$dataString .= "\t'$category' => [" . PHP_EOL;
|
||||
|
||||
if (is_array($data[$category])) {
|
||||
$keys = array_keys($data[$category]);
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$dataString .= static::mapConfigValue($key, $data[$category][$key]);
|
||||
}
|
||||
}
|
||||
$dataString .= "\t]," . PHP_EOL;
|
||||
}
|
||||
|
||||
$dataString .= "];" . PHP_EOL;
|
||||
|
||||
return $dataString;
|
||||
}
|
||||
|
||||
protected static function extractArray(array $config, int $level = 0): string
|
||||
{
|
||||
$string = '';
|
||||
|
||||
foreach ($config as $configKey => $configValue) {
|
||||
$string .= static::mapConfigValue($configKey, $configValue, $level);
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
protected static function mapConfigValue(string $key, $value, $level = 0): string
|
||||
{
|
||||
$string = str_repeat("\t", $level + 2) . "'$key' => ";
|
||||
|
||||
if (is_null($value)) {
|
||||
$string .= "null,";
|
||||
} elseif (is_array($value)) {
|
||||
$string .= "[" . PHP_EOL;
|
||||
$string .= static::extractArray($value, ++$level);
|
||||
$string .= str_repeat("\t", $level + 1) . '],';
|
||||
} elseif (is_bool($value)) {
|
||||
$string .= ($value ? 'true' : 'false') . ",";
|
||||
} elseif (is_numeric($value)) {
|
||||
$string .= $value . ",";
|
||||
} else {
|
||||
$string .= sprintf('\'%s\',', addcslashes($value, '\'\\'));
|
||||
}
|
||||
|
||||
$string .= PHP_EOL;
|
||||
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
|
|
@ -21,13 +21,13 @@
|
|||
|
||||
namespace Friendica\Core\Config\ValueObject;
|
||||
|
||||
use Friendica\Core\Config\Util\ConfigFileLoader;
|
||||
use Friendica\Core\Config\Util\ConfigFileManager;
|
||||
use ParagonIE\HiddenString\HiddenString;
|
||||
|
||||
/**
|
||||
* The Friendica config cache for the application
|
||||
* Initial, all *.config.php files are loaded into this cache with the
|
||||
* ConfigFileLoader ( @see ConfigFileLoader )
|
||||
* ConfigFileManager ( @see ConfigFileManager )
|
||||
*/
|
||||
class Cache
|
||||
{
|
||||
|
|
@ -35,8 +35,8 @@ class Cache
|
|||
const SOURCE_STATIC = 0;
|
||||
/** @var int Indicates that the cache entry is set by file - Low Priority */
|
||||
const SOURCE_FILE = 1;
|
||||
/** @var int Indicates that the cache entry is set by the DB config table - Middle Priority */
|
||||
const SOURCE_DB = 2;
|
||||
/** @var int Indicates that the cache entry is manually set by the application (per admin page/console) - Middle Priority */
|
||||
const SOURCE_DATA = 2;
|
||||
/** @var int Indicates that the cache entry is set by a server environment variable - High Priority */
|
||||
const SOURCE_ENV = 3;
|
||||
/** @var int Indicates that the cache entry is fixed and must not be changed */
|
||||
|
|
@ -65,7 +65,7 @@ class Cache
|
|||
* @param bool $hidePasswordOutput True, if cache variables should take extra care of password values
|
||||
* @param int $source Sets a source of the initial config values
|
||||
*/
|
||||
public function __construct(array $config = [], bool $hidePasswordOutput = true, $source = self::SOURCE_DEFAULT)
|
||||
public function __construct(array $config = [], bool $hidePasswordOutput = true, int $source = self::SOURCE_DEFAULT)
|
||||
{
|
||||
$this->hidePasswordOutput = $hidePasswordOutput;
|
||||
$this->load($config, $source);
|
||||
|
|
@ -87,11 +87,10 @@ class Cache
|
|||
$keys = array_keys($config[$category]);
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$value = $config[$category][$key];
|
||||
if (isset($value)) {
|
||||
$this->set($category, $key, $value, $source);
|
||||
}
|
||||
$this->set($category, $key, $config[$category][$key] ?? null, $source);
|
||||
}
|
||||
} else {
|
||||
$this->set($category, null, $config[$category], $source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -128,62 +127,132 @@ class Cache
|
|||
return $this->source[$cat][$key] ?? -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the whole config array based on the given source type
|
||||
*
|
||||
* @param int $source Indicates the source of the config entry
|
||||
*
|
||||
* @return array The config array part of the given source
|
||||
*/
|
||||
public function getDataBySource(int $source): array
|
||||
{
|
||||
$data = [];
|
||||
|
||||
$categories = array_keys($this->source);
|
||||
|
||||
foreach ($categories as $category) {
|
||||
if (is_array($this->source[$category])) {
|
||||
$keys = array_keys($this->source[$category]);
|
||||
|
||||
foreach ($keys as $key) {
|
||||
if ($this->source[$category][$key] === $source) {
|
||||
$data[$category][$key] = $this->config[$category][$key];
|
||||
}
|
||||
}
|
||||
} elseif (is_int($this->source[$category])) {
|
||||
$data[$category] = null;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a value in the config cache. Accepts raw output from the config table
|
||||
*
|
||||
* @param string $cat Config category
|
||||
* @param string $key Config key
|
||||
* @param mixed $value Value to set
|
||||
* @param int $source The source of the current config key
|
||||
* @param string $cat Config category
|
||||
* @param ?string $key Config key
|
||||
* @param ?mixed $value Value to set
|
||||
* @param int $source The source of the current config key
|
||||
*
|
||||
* @return bool True, if the value is set
|
||||
*/
|
||||
public function set(string $cat, string $key, $value, int $source = self::SOURCE_DEFAULT): bool
|
||||
public function set(string $cat, string $key = null, $value = null, int $source = self::SOURCE_DEFAULT): bool
|
||||
{
|
||||
if (!isset($this->config[$cat])) {
|
||||
if (!isset($this->config[$cat]) && $key !== null) {
|
||||
$this->config[$cat] = [];
|
||||
$this->source[$cat] = [];
|
||||
}
|
||||
|
||||
if (isset($this->source[$cat][$key]) &&
|
||||
$source < $this->source[$cat][$key]) {
|
||||
if ((isset($this->source[$cat][$key]) && $source < $this->source[$cat][$key]) ||
|
||||
(is_int($this->source[$cat] ?? null) && $source < $this->source[$cat])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->hidePasswordOutput &&
|
||||
$key == 'password' &&
|
||||
is_string($value)) {
|
||||
$this->config[$cat][$key] = new HiddenString((string)$value);
|
||||
$this->setCatKeyValueSource($cat, $key, new HiddenString($value), $source);
|
||||
} else if (is_string($value)) {
|
||||
$this->setCatKeyValueSource($cat, $key, self::toConfigValue($value), $source);
|
||||
} else {
|
||||
$this->config[$cat][$key] = $value;
|
||||
$this->setCatKeyValueSource($cat, $key, $value, $source);
|
||||
}
|
||||
|
||||
$this->source[$cat][$key] = $source;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function setCatKeyValueSource(string $cat, string $key = null, $value = null, int $source = self::SOURCE_DEFAULT)
|
||||
{
|
||||
if (isset($key)) {
|
||||
$this->config[$cat][$key] = $value;
|
||||
$this->source[$cat][$key] = $source;
|
||||
} else {
|
||||
$this->config[$cat] = $value;
|
||||
$this->source[$cat] = $source;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a DB value to a config value
|
||||
* - null = The db-value isn't set
|
||||
* - bool = The db-value is either '0' or '1'
|
||||
* - array = The db-value is a serialized array
|
||||
* - string = The db-value is a string
|
||||
*
|
||||
* Keep in mind that there aren't any numeric/integer config values in the database
|
||||
*
|
||||
* @param string|null $value
|
||||
*
|
||||
* @return null|array|string
|
||||
*/
|
||||
public static function toConfigValue(?string $value)
|
||||
{
|
||||
if (!isset($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (preg_match("|^a:[0-9]+:{.*}$|s", $value)) {
|
||||
return unserialize($value);
|
||||
} else {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a value from the config cache.
|
||||
*
|
||||
* @param string $cat Config category
|
||||
* @param string $key Config key
|
||||
* @param string $cat Config category
|
||||
* @param ?string $key Config key (if not set, the whole category will get deleted)
|
||||
* @param int $source The source of the current config key
|
||||
*
|
||||
* @return bool true, if deleted
|
||||
*/
|
||||
public function delete(string $cat, string $key): bool
|
||||
public function delete(string $cat, string $key = null, int $source = self::SOURCE_DEFAULT): bool
|
||||
{
|
||||
if (isset($this->config[$cat][$key])) {
|
||||
unset($this->config[$cat][$key]);
|
||||
unset($this->source[$cat][$key]);
|
||||
if (count($this->config[$cat]) == 0) {
|
||||
unset($this->config[$cat]);
|
||||
unset($this->source[$cat]);
|
||||
$this->config[$cat][$key] = null;
|
||||
$this->source[$cat][$key] = $source;
|
||||
if (empty(array_filter($this->config[$cat], function($value) { return !is_null($value); }))) {
|
||||
$this->config[$cat] = null;
|
||||
$this->source[$cat] = $source;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
} elseif (isset($this->config[$cat])) {
|
||||
$this->config[$cat] = null;
|
||||
$this->source[$cat] = $source;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -223,4 +292,39 @@ class Cache
|
|||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges a new Cache into the existing one and returns the merged Cache
|
||||
*
|
||||
* @param Cache $cache The cache, which should get merged into this Cache
|
||||
*
|
||||
* @return Cache The merged Cache
|
||||
*/
|
||||
public function merge(Cache $cache): Cache
|
||||
{
|
||||
$newConfig = $this->config;
|
||||
$newSource = $this->source;
|
||||
|
||||
$categories = array_keys($cache->config);
|
||||
|
||||
foreach ($categories as $category) {
|
||||
if (is_array($cache->config[$category])) {
|
||||
$keys = array_keys($cache->config[$category]);
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$newConfig[$category][$key] = $cache->config[$category][$key];
|
||||
$newSource[$category][$key] = $cache->source[$category][$key];
|
||||
}
|
||||
} else {
|
||||
$newConfig[$category] = $cache->config[$category];
|
||||
$newSource[$category] = $cache->source[$category];
|
||||
}
|
||||
}
|
||||
|
||||
$newCache = new Cache();
|
||||
$newCache->config = $newConfig;
|
||||
$newCache->source = $newSource;
|
||||
|
||||
return $newCache;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
namespace Friendica\Core\KeyValueStorage\Type;
|
||||
|
||||
use Friendica\Core\Config\Util\ValueConversion;
|
||||
use Friendica\Core\PConfig\Util\ValueConversion;
|
||||
use Friendica\Core\KeyValueStorage\Exceptions\KeyValueStoragePersistenceException;
|
||||
use Friendica\Database\Database;
|
||||
|
||||
|
|
|
|||
|
|
@ -85,10 +85,15 @@ class L10n
|
|||
* @var Database
|
||||
*/
|
||||
private $dba;
|
||||
/**
|
||||
* @var IManageConfigValues
|
||||
*/
|
||||
private $config;
|
||||
|
||||
public function __construct(IManageConfigValues $config, Database $dba, IHandleSessions $session, array $server, array $get)
|
||||
{
|
||||
$this->dba = $dba;
|
||||
$this->config = $config;
|
||||
|
||||
$this->loadTranslationTable(L10n::detectLanguage($server, $get, $config->get('system', 'language', self::DEFAULT)));
|
||||
$this->setSessionVariable($session);
|
||||
|
|
@ -157,9 +162,9 @@ class L10n
|
|||
$a->strings = [];
|
||||
|
||||
// load enabled addons strings
|
||||
$addons = $this->dba->select('addon', ['name'], ['installed' => true]);
|
||||
while ($p = $this->dba->fetch($addons)) {
|
||||
$name = Strings::sanitizeFilePathItem($p['name']);
|
||||
$addons = array_keys($this->config->get('addons') ?? []);
|
||||
foreach ($addons as $addon) {
|
||||
$name = Strings::sanitizeFilePathItem($addon);
|
||||
if (file_exists(__DIR__ . "/../../addon/$name/lang/$lang/strings.php")) {
|
||||
include __DIR__ . "/../../addon/$name/lang/$lang/strings.php";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
namespace Friendica\Core\PConfig\Repository;
|
||||
|
||||
use Friendica\App\Mode;
|
||||
use Friendica\Core\Config\Util\ValueConversion;
|
||||
use Friendica\Core\PConfig\Util\ValueConversion;
|
||||
use Friendica\Core\PConfig\Exception\PConfigPersistenceException;
|
||||
use Friendica\Database\Database;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Core\Config\Util;
|
||||
namespace Friendica\Core\PConfig\Util;
|
||||
|
||||
/**
|
||||
* Util class to help to convert from/to (p)config values
|
||||
|
|
@ -63,7 +63,11 @@ class ExternalResource implements ICanReadFromStorage
|
|||
Logger::debug('Got picture', ['Content-Type' => $fetchResult->getHeader('Content-Type'), 'uid' => $data->uid, 'url' => $data->url]);
|
||||
return $fetchResult->getBody();
|
||||
} else {
|
||||
throw new ReferenceStorageException(sprintf('External resource failed to get %s', $reference), $fetchResult->getReturnCode(), new Exception($fetchResult->getBody()));
|
||||
if (empty($fetchResult)) {
|
||||
throw new ReferenceStorageException(sprintf('External resource failed to get %s', $reference));
|
||||
} else {
|
||||
throw new ReferenceStorageException(sprintf('External resource failed to get %s', $reference), $fetchResult->getReturnCode(), new Exception($fetchResult->getBody()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -294,7 +294,7 @@ class System
|
|||
}
|
||||
|
||||
DI::apiResponse()->setType(Response::TYPE_XML);
|
||||
DI::apiResponse()->addContent(XML::fromArray(["result" => $result], $xml));
|
||||
DI::apiResponse()->addContent(XML::fromArray(['result' => $result]));
|
||||
DI::page()->exit(DI::apiResponse()->generate());
|
||||
|
||||
self::exit();
|
||||
|
|
|
|||
|
|
@ -47,22 +47,32 @@ class Update
|
|||
* @return void
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function check(string $basePath, bool $via_worker, App\Mode $mode)
|
||||
public static function check(string $basePath, bool $via_worker)
|
||||
{
|
||||
if (!DBA::connected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't check the status if the last update was failed
|
||||
if (DI::config()->get('system', 'update', Update::SUCCESS, true) == Update::FAILED) {
|
||||
if (DI::config()->get('system', 'update', Update::SUCCESS) == Update::FAILED) {
|
||||
return;
|
||||
}
|
||||
|
||||
$build = DI::config()->get('system', 'build');
|
||||
|
||||
if (empty($build)) {
|
||||
DI::config()->set('system', 'build', DB_UPDATE_VERSION - 1);
|
||||
$build = DB_UPDATE_VERSION - 1;
|
||||
// legacy option - check if there's something in the Config table
|
||||
if (DBStructure::existsTable('config')) {
|
||||
$dbConfig = DBA::selectFirst('config', ['v'], ['cat' => 'system', 'k' => 'build']);
|
||||
if (!empty($dbConfig)) {
|
||||
$build = $dbConfig['v'];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($build)) {
|
||||
DI::config()->set('system', 'build', DB_UPDATE_VERSION - 1);
|
||||
$build = DB_UPDATE_VERSION - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// We don't support upgrading from very old versions anymore
|
||||
|
|
@ -119,11 +129,21 @@ class Update
|
|||
DI::lock()->release('dbupdate', true);
|
||||
}
|
||||
|
||||
$build = DI::config()->get('system', 'build', null, true);
|
||||
$build = DI::config()->get('system', 'build');
|
||||
|
||||
if (empty($build) || ($build > DB_UPDATE_VERSION)) {
|
||||
$build = DB_UPDATE_VERSION - 1;
|
||||
DI::config()->set('system', 'build', $build);
|
||||
if (empty($build)) {
|
||||
// legacy option - check if there's something in the Config table
|
||||
if (DBStructure::existsTable('config')) {
|
||||
$dbConfig = DBA::selectFirst('config', ['v'], ['cat' => 'system', 'k' => 'build']);
|
||||
if (!empty($dbConfig)) {
|
||||
$build = $dbConfig['v'];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($build) || ($build > DB_UPDATE_VERSION)) {
|
||||
DI::config()->set('system', 'build', DB_UPDATE_VERSION - 1);
|
||||
$build = DB_UPDATE_VERSION - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($build != DB_UPDATE_VERSION || $force) {
|
||||
|
|
@ -132,7 +152,7 @@ class Update
|
|||
$stored = intval($build);
|
||||
$current = intval(DB_UPDATE_VERSION);
|
||||
if ($stored < $current || $force) {
|
||||
DI::config()->load('database');
|
||||
DI::config()->reload();
|
||||
|
||||
// Compare the current structure with the defined structure
|
||||
// If the Lock is acquired, never release it automatically to avoid double updates
|
||||
|
|
@ -141,11 +161,21 @@ class Update
|
|||
Logger::notice('Update starting.', ['from' => $stored, 'to' => $current]);
|
||||
|
||||
// Checks if the build changed during Lock acquiring (so no double update occurs)
|
||||
$retryBuild = DI::config()->get('system', 'build', null, true);
|
||||
if ($retryBuild !== $build) {
|
||||
Logger::notice('Update already done.', ['from' => $stored, 'to' => $current]);
|
||||
DI::lock()->release('dbupdate');
|
||||
return '';
|
||||
$retryBuild = DI::config()->get('system', 'build');
|
||||
if ($retryBuild != $build) {
|
||||
// legacy option - check if there's something in the Config table
|
||||
if (DBStructure::existsTable('config')) {
|
||||
$dbConfig = DBA::selectFirst('config', ['v'], ['cat' => 'system', 'k' => 'build']);
|
||||
if (!empty($dbConfig)) {
|
||||
$retryBuild = intval($dbConfig['v']);
|
||||
}
|
||||
}
|
||||
|
||||
if ($retryBuild != $build) {
|
||||
Logger::notice('Update already done.', ['from' => $build, 'retry' => $retryBuild, 'to' => $current]);
|
||||
DI::lock()->release('dbupdate');
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
DI::config()->set('system', 'maintenance', 1);
|
||||
|
|
@ -160,8 +190,10 @@ class Update
|
|||
Logger::warning('Pre update failed', ['version' => $version]);
|
||||
DI::config()->set('system', 'update', Update::FAILED);
|
||||
DI::lock()->release('dbupdate');
|
||||
DI::config()->set('system', 'maintenance', 0);
|
||||
DI::config()->set('system', 'maintenance_reason', '');
|
||||
DI::config()->beginTransaction()
|
||||
->set('system', 'maintenance', false)
|
||||
->delete('system', 'maintenance_reason')
|
||||
->commit();
|
||||
return $r;
|
||||
} else {
|
||||
Logger::notice('Pre update executed.', ['version' => $version]);
|
||||
|
|
@ -181,8 +213,10 @@ class Update
|
|||
Logger::error('Update ERROR.', ['from' => $stored, 'to' => $current, 'retval' => $retval]);
|
||||
DI::config()->set('system', 'update', Update::FAILED);
|
||||
DI::lock()->release('dbupdate');
|
||||
DI::config()->set('system', 'maintenance', 0);
|
||||
DI::config()->set('system', 'maintenance_reason', '');
|
||||
DI::config()->beginTransaction()
|
||||
->set('system', 'maintenance', false)
|
||||
->delete('system', 'maintenance_reason')
|
||||
->commit();
|
||||
return $retval;
|
||||
} else {
|
||||
Logger::notice('Database structure update finished.', ['from' => $stored, 'to' => $current]);
|
||||
|
|
@ -198,8 +232,10 @@ class Update
|
|||
Logger::warning('Post update failed', ['version' => $version]);
|
||||
DI::config()->set('system', 'update', Update::FAILED);
|
||||
DI::lock()->release('dbupdate');
|
||||
DI::config()->set('system', 'maintenance', 0);
|
||||
DI::config()->set('system', 'maintenance_reason', '');
|
||||
DI::config()->beginTransaction()
|
||||
->set('system', 'maintenance', false)
|
||||
->delete('system', 'maintenance_reason')
|
||||
->commit();
|
||||
return $r;
|
||||
} else {
|
||||
DI::config()->set('system', 'build', $version);
|
||||
|
|
@ -210,8 +246,10 @@ class Update
|
|||
DI::config()->set('system', 'build', $current);
|
||||
DI::config()->set('system', 'update', Update::SUCCESS);
|
||||
DI::lock()->release('dbupdate');
|
||||
DI::config()->set('system', 'maintenance', 0);
|
||||
DI::config()->set('system', 'maintenance_reason', '');
|
||||
DI::config()->beginTransaction()
|
||||
->set('system', 'maintenance', false)
|
||||
->delete('system', 'maintenance_reason')
|
||||
->commit();
|
||||
|
||||
Logger::notice('Update success.', ['from' => $stored, 'to' => $current]);
|
||||
if ($sendMail) {
|
||||
|
|
|
|||
|
|
@ -331,7 +331,7 @@ class Worker
|
|||
$mypid = getmypid();
|
||||
|
||||
// Quit when in maintenance
|
||||
if (DI::config()->get('system', 'maintenance', false, true)) {
|
||||
if (DI::config()->get('system', 'maintenance', false)) {
|
||||
Logger::notice('Maintenance mode - quit process', ['pid' => $mypid]);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1315,8 +1315,8 @@ class Worker
|
|||
return $added;
|
||||
}
|
||||
|
||||
// Quit on daemon mode
|
||||
if (Worker\Daemon::isMode()) {
|
||||
// Quit on daemon mode, except the priority is critical (like for db updates)
|
||||
if (Worker\Daemon::isMode() && $priority !== self::PRIORITY_CRITICAL) {
|
||||
return $added;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -181,6 +181,11 @@ abstract class DI
|
|||
return self::$dice->create(Core\Config\Capability\IManageConfigValues::class);
|
||||
}
|
||||
|
||||
public static function configFileManager(): Core\Config\Util\ConfigFileManager
|
||||
{
|
||||
return self::$dice->create(Core\Config\Util\ConfigFileManager::class);
|
||||
}
|
||||
|
||||
public static function keyValue(): Core\KeyValueStorage\Capabilities\IManageKeyValuePairs
|
||||
{
|
||||
return self::$dice->create(Core\KeyValueStorage\Capabilities\IManageKeyValuePairs::class);
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ class DBStructure
|
|||
$old_tables = ['fserver', 'gcign', 'gcontact', 'gcontact-relation', 'gfollower' ,'glink', 'item-delivery-data',
|
||||
'item-activity', 'item-content', 'item_id', 'participation', 'poll', 'poll_result', 'queue', 'retriever_rule',
|
||||
'deliverq', 'dsprphotoq', 'ffinder', 'sign', 'spam', 'term', 'user-item', 'thread', 'item', 'challenge',
|
||||
'auth_codes', 'tokens', 'clients', 'profile_check', 'host', 'conversation', 'fcontact'];
|
||||
'auth_codes', 'tokens', 'clients', 'profile_check', 'host', 'conversation', 'fcontact', 'config', 'addon'];
|
||||
|
||||
$tables = DBA::selectToArray('INFORMATION_SCHEMA.TABLES', ['TABLE_NAME'],
|
||||
['TABLE_SCHEMA' => DBA::databaseName(), 'TABLE_TYPE' => 'BASE TABLE']);
|
||||
|
|
@ -176,14 +176,16 @@ class DBStructure
|
|||
public static function performUpdate(bool $enable_maintenance_mode = true, bool $verbose = false): string
|
||||
{
|
||||
if ($enable_maintenance_mode) {
|
||||
DI::config()->set('system', 'maintenance', 1);
|
||||
DI::config()->set('system', 'maintenance', true);
|
||||
}
|
||||
|
||||
$status = self::update($verbose, true);
|
||||
|
||||
if ($enable_maintenance_mode) {
|
||||
DI::config()->set('system', 'maintenance', 0);
|
||||
DI::config()->set('system', 'maintenance_reason', '');
|
||||
DI::config()->beginTransaction()
|
||||
->set('system', 'maintenance', false)
|
||||
->delete('system', 'maintenance_reason')
|
||||
->commit();
|
||||
}
|
||||
|
||||
return $status;
|
||||
|
|
|
|||
|
|
@ -44,7 +44,9 @@ use Friendica\Util\Network;
|
|||
use Friendica\Util\Strings;
|
||||
use Friendica\Util\XML;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\Worker\UpdateGServer;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
/**
|
||||
* This class handles GServer related functions
|
||||
|
|
@ -99,11 +101,11 @@ class GServer
|
|||
*/
|
||||
public static function add(string $url, bool $only_nodeinfo = false)
|
||||
{
|
||||
if (self::getID($url, false)) {
|
||||
if (self::getID($url)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Worker::add(Worker::PRIORITY_LOW, 'UpdateGServer', $url, $only_nodeinfo);
|
||||
UpdateGServer::add(Worker::PRIORITY_LOW, $url, $only_nodeinfo);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -191,8 +193,9 @@ class GServer
|
|||
return false;
|
||||
} else {
|
||||
if (strtotime($gserver['next_contact']) < time()) {
|
||||
Worker::add(Worker::PRIORITY_LOW, 'UpdateGServer', $gserver['url'], false);
|
||||
UpdateGServer::add(Worker::PRIORITY_LOW, $gserver['url']);
|
||||
}
|
||||
|
||||
return self::isDefunct($gserver);
|
||||
}
|
||||
}
|
||||
|
|
@ -210,8 +213,9 @@ class GServer
|
|||
return true;
|
||||
} else {
|
||||
if (strtotime($gserver['next_contact']) < time()) {
|
||||
Worker::add(Worker::PRIORITY_LOW, 'UpdateGServer', $gserver['url'], false);
|
||||
UpdateGServer::add(Worker::PRIORITY_LOW, $gserver['url']);
|
||||
}
|
||||
|
||||
return !$gserver['failed'] && in_array($gserver['network'], Protocol::FEDERATED);
|
||||
}
|
||||
}
|
||||
|
|
@ -252,7 +256,7 @@ class GServer
|
|||
}
|
||||
|
||||
if (!empty($server) && (empty($gserver) || strtotime($gserver['next_contact']) < time())) {
|
||||
Worker::add(Worker::PRIORITY_LOW, 'UpdateGServer', $server, false);
|
||||
UpdateGServer::add(Worker::PRIORITY_LOW, $server);
|
||||
}
|
||||
|
||||
return $reachable;
|
||||
|
|
@ -375,7 +379,7 @@ class GServer
|
|||
Logger::info('Reset failed status for server', ['url' => $gserver['url']]);
|
||||
|
||||
if (strtotime($gserver['next_contact']) < time()) {
|
||||
Worker::add(Worker::PRIORITY_LOW, 'UpdateGServer', $gserver['url'], false);
|
||||
UpdateGServer::add(Worker::PRIORITY_LOW, $gserver['url']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -393,7 +397,7 @@ class GServer
|
|||
Logger::info('Set failed status for server', ['url' => $gserver['url']]);
|
||||
|
||||
if (strtotime($gserver['next_contact']) < time()) {
|
||||
Worker::add(Worker::PRIORITY_LOW, 'UpdateGServer', $gserver['url'], false);
|
||||
UpdateGServer::add(Worker::PRIORITY_LOW, $gserver['url']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -442,18 +446,41 @@ class GServer
|
|||
*
|
||||
* @return string cleaned URL
|
||||
* @throws Exception
|
||||
* @deprecated since 2023.03 Use cleanUri instead
|
||||
*/
|
||||
public static function cleanURL(string $dirtyUrl): string
|
||||
{
|
||||
try {
|
||||
$url = str_replace('/index.php', '', trim($dirtyUrl, '/'));
|
||||
return (string)(new Uri($url))->withUserInfo('')->withQuery('')->withFragment('');
|
||||
return (string)self::cleanUri(new Uri($dirtyUrl));
|
||||
} catch (\Throwable $e) {
|
||||
Logger::warning('Invalid URL', ['dirtyUrl' => $dirtyUrl, 'url' => $url]);
|
||||
Logger::warning('Invalid URL', ['dirtyUrl' => $dirtyUrl]);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove unwanted content from the given URI
|
||||
*
|
||||
* @param UriInterface $dirtyUri
|
||||
*
|
||||
* @return UriInterface cleaned URI
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function cleanUri(UriInterface $dirtyUri): string
|
||||
{
|
||||
return $dirtyUri
|
||||
->withUserInfo('')
|
||||
->withQuery('')
|
||||
->withFragment('')
|
||||
->withPath(
|
||||
preg_replace(
|
||||
'#(?:^|/)index\.php#',
|
||||
'',
|
||||
rtrim($dirtyUri->getPath(), '/')
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect server data (type, protocol, version number, ...)
|
||||
* The detected data is then updated or inserted in the gserver table.
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ class Link
|
|||
$timeout = DI::config()->get('system', 'xrd_timeout');
|
||||
|
||||
$curlResult = HTTPSignature::fetchRaw($url, 0, [HttpClientOptions::TIMEOUT => $timeout, HttpClientOptions::ACCEPT_CONTENT => $accept]);
|
||||
if (!$curlResult->isSuccess()) {
|
||||
if (empty($curlResult) || !$curlResult->isSuccess()) {
|
||||
return [];
|
||||
}
|
||||
$fields = ['mimetype' => $curlResult->getHeader('Content-Type')[0]];
|
||||
|
|
|
|||
|
|
@ -48,8 +48,6 @@ class Site extends BaseAdmin
|
|||
|
||||
self::checkFormSecurityTokenRedirectOnError('/admin/site', 'admin_site');
|
||||
|
||||
$a = DI::app();
|
||||
|
||||
if (!empty($_POST['republish_directory'])) {
|
||||
Worker::add(Worker::PRIORITY_LOW, 'Directory');
|
||||
return;
|
||||
|
|
@ -146,9 +144,11 @@ class Site extends BaseAdmin
|
|||
$relay_user_tags = !empty($_POST['relay_user_tags']);
|
||||
$active_panel = (!empty($_POST['active_panel']) ? "#" . trim($_POST['active_panel']) : '');
|
||||
|
||||
$transactionConfig = DI::config()->beginTransaction();
|
||||
|
||||
// Has the directory url changed? If yes, then resubmit the existing profiles there
|
||||
if ($global_directory != DI::config()->get('system', 'directory') && ($global_directory != '')) {
|
||||
DI::config()->set('system', 'directory', $global_directory);
|
||||
$transactionConfig->set('system', 'directory', $global_directory);
|
||||
Worker::add(Worker::PRIORITY_LOW, 'Directory');
|
||||
}
|
||||
|
||||
|
|
@ -194,131 +194,133 @@ class Site extends BaseAdmin
|
|||
);
|
||||
}
|
||||
}
|
||||
DI::config()->set('system', 'ssl_policy' , $ssl_policy);
|
||||
DI::config()->set('system', 'maxloadavg' , $maxloadavg);
|
||||
DI::config()->set('system', 'min_memory' , $min_memory);
|
||||
DI::config()->set('system', 'optimize_tables' , $optimize_tables);
|
||||
DI::config()->set('system', 'contact_discovery' , $contact_discovery);
|
||||
DI::config()->set('system', 'synchronize_directory' , $synchronize_directory);
|
||||
DI::config()->set('system', 'poco_requery_days' , $poco_requery_days);
|
||||
DI::config()->set('system', 'poco_discovery' , $poco_discovery);
|
||||
DI::config()->set('system', 'poco_local_search' , $poco_local_search);
|
||||
DI::config()->set('system', 'nodeinfo' , $nodeinfo);
|
||||
DI::config()->set('config', 'sitename' , $sitename);
|
||||
DI::config()->set('config', 'sender_email' , $sender_email);
|
||||
DI::config()->set('system', 'suppress_tags' , $suppress_tags);
|
||||
DI::config()->set('system', 'shortcut_icon' , $shortcut_icon);
|
||||
DI::config()->set('system', 'touch_icon' , $touch_icon);
|
||||
$transactionConfig->set('system', 'ssl_policy' , $ssl_policy);
|
||||
$transactionConfig->set('system', 'maxloadavg' , $maxloadavg);
|
||||
$transactionConfig->set('system', 'min_memory' , $min_memory);
|
||||
$transactionConfig->set('system', 'optimize_tables' , $optimize_tables);
|
||||
$transactionConfig->set('system', 'contact_discovery' , $contact_discovery);
|
||||
$transactionConfig->set('system', 'synchronize_directory' , $synchronize_directory);
|
||||
$transactionConfig->set('system', 'poco_requery_days' , $poco_requery_days);
|
||||
$transactionConfig->set('system', 'poco_discovery' , $poco_discovery);
|
||||
$transactionConfig->set('system', 'poco_local_search' , $poco_local_search);
|
||||
$transactionConfig->set('system', 'nodeinfo' , $nodeinfo);
|
||||
$transactionConfig->set('config', 'sitename' , $sitename);
|
||||
$transactionConfig->set('config', 'sender_email' , $sender_email);
|
||||
$transactionConfig->set('system', 'suppress_tags' , $suppress_tags);
|
||||
$transactionConfig->set('system', 'shortcut_icon' , $shortcut_icon);
|
||||
$transactionConfig->set('system', 'touch_icon' , $touch_icon);
|
||||
|
||||
if ($banner == "") {
|
||||
DI::config()->delete('system', 'banner');
|
||||
$transactionConfig->delete('system', 'banner');
|
||||
} else {
|
||||
DI::config()->set('system', 'banner', $banner);
|
||||
$transactionConfig->set('system', 'banner', $banner);
|
||||
}
|
||||
|
||||
if (empty($email_banner)) {
|
||||
DI::config()->delete('system', 'email_banner');
|
||||
$transactionConfig->delete('system', 'email_banner');
|
||||
} else {
|
||||
DI::config()->set('system', 'email_banner', $email_banner);
|
||||
$transactionConfig->set('system', 'email_banner', $email_banner);
|
||||
}
|
||||
|
||||
if (empty($additional_info)) {
|
||||
DI::config()->delete('config', 'info');
|
||||
$transactionConfig->delete('config', 'info');
|
||||
} else {
|
||||
DI::config()->set('config', 'info', $additional_info);
|
||||
$transactionConfig->set('config', 'info', $additional_info);
|
||||
}
|
||||
DI::config()->set('system', 'language', $language);
|
||||
DI::config()->set('system', 'theme', $theme);
|
||||
$transactionConfig->set('system', 'language', $language);
|
||||
$transactionConfig->set('system', 'theme', $theme);
|
||||
Theme::install($theme);
|
||||
|
||||
if ($theme_mobile == '---') {
|
||||
DI::config()->delete('system', 'mobile-theme');
|
||||
$transactionConfig->delete('system', 'mobile-theme');
|
||||
} else {
|
||||
DI::config()->set('system', 'mobile-theme', $theme_mobile);
|
||||
$transactionConfig->set('system', 'mobile-theme', $theme_mobile);
|
||||
}
|
||||
if ($singleuser == '---') {
|
||||
DI::config()->delete('system', 'singleuser');
|
||||
$transactionConfig->delete('system', 'singleuser');
|
||||
} else {
|
||||
DI::config()->set('system', 'singleuser', $singleuser);
|
||||
$transactionConfig->set('system', 'singleuser', $singleuser);
|
||||
}
|
||||
if (preg_match('/\d+(?:\s*[kmg])?/i', $maximagesize)) {
|
||||
DI::config()->set('system', 'maximagesize', $maximagesize);
|
||||
$transactionConfig->set('system', 'maximagesize', $maximagesize);
|
||||
} else {
|
||||
DI::sysmsg()->addNotice(DI::l10n()->t('%s is no valid input for maximum image size', $maximagesize));
|
||||
}
|
||||
DI::config()->set('system', 'max_image_length' , $maximagelength);
|
||||
DI::config()->set('system', 'jpeg_quality' , $jpegimagequality);
|
||||
$transactionConfig->set('system', 'max_image_length' , $maximagelength);
|
||||
$transactionConfig->set('system', 'jpeg_quality' , $jpegimagequality);
|
||||
|
||||
DI::config()->set('config', 'register_policy' , $register_policy);
|
||||
DI::config()->set('system', 'max_daily_registrations', $daily_registrations);
|
||||
DI::config()->set('system', 'account_abandon_days' , $abandon_days);
|
||||
DI::config()->set('config', 'register_text' , $register_text);
|
||||
DI::config()->set('system', 'allowed_sites' , $allowed_sites);
|
||||
DI::config()->set('system', 'allowed_email' , $allowed_email);
|
||||
DI::config()->set('system', 'forbidden_nicknames' , $forbidden_nicknames);
|
||||
DI::config()->set('system', 'system_actor_name' , $system_actor_name);
|
||||
DI::config()->set('system', 'no_oembed_rich_content' , $no_oembed_rich_content);
|
||||
DI::config()->set('system', 'allowed_oembed' , $allowed_oembed);
|
||||
DI::config()->set('system', 'block_public' , $block_public);
|
||||
DI::config()->set('system', 'publish_all' , $force_publish);
|
||||
DI::config()->set('system', 'newuser_private' , $newuser_private);
|
||||
DI::config()->set('system', 'enotify_no_content' , $enotify_no_content);
|
||||
DI::config()->set('system', 'disable_embedded' , $disable_embedded);
|
||||
DI::config()->set('system', 'allow_users_remote_self', $allow_users_remote_self);
|
||||
DI::config()->set('system', 'explicit_content' , $explicit_content);
|
||||
DI::config()->set('system', 'proxify_content' , $proxify_content);
|
||||
DI::config()->set('system', 'cache_contact_avatar' , $cache_contact_avatar);
|
||||
DI::config()->set('system', 'check_new_version_url' , $check_new_version_url);
|
||||
$transactionConfig->set('config', 'register_policy' , $register_policy);
|
||||
$transactionConfig->set('system', 'max_daily_registrations', $daily_registrations);
|
||||
$transactionConfig->set('system', 'account_abandon_days' , $abandon_days);
|
||||
$transactionConfig->set('config', 'register_text' , $register_text);
|
||||
$transactionConfig->set('system', 'allowed_sites' , $allowed_sites);
|
||||
$transactionConfig->set('system', 'allowed_email' , $allowed_email);
|
||||
$transactionConfig->set('system', 'forbidden_nicknames' , $forbidden_nicknames);
|
||||
$transactionConfig->set('system', 'system_actor_name' , $system_actor_name);
|
||||
$transactionConfig->set('system', 'no_oembed_rich_content' , $no_oembed_rich_content);
|
||||
$transactionConfig->set('system', 'allowed_oembed' , $allowed_oembed);
|
||||
$transactionConfig->set('system', 'block_public' , $block_public);
|
||||
$transactionConfig->set('system', 'publish_all' , $force_publish);
|
||||
$transactionConfig->set('system', 'newuser_private' , $newuser_private);
|
||||
$transactionConfig->set('system', 'enotify_no_content' , $enotify_no_content);
|
||||
$transactionConfig->set('system', 'disable_embedded' , $disable_embedded);
|
||||
$transactionConfig->set('system', 'allow_users_remote_self', $allow_users_remote_self);
|
||||
$transactionConfig->set('system', 'explicit_content' , $explicit_content);
|
||||
$transactionConfig->set('system', 'proxify_content' , $proxify_content);
|
||||
$transactionConfig->set('system', 'cache_contact_avatar' , $cache_contact_avatar);
|
||||
$transactionConfig->set('system', 'check_new_version_url' , $check_new_version_url);
|
||||
|
||||
DI::config()->set('system', 'block_extended_register', !$enable_multi_reg);
|
||||
DI::config()->set('system', 'no_openid' , !$enable_openid);
|
||||
DI::config()->set('system', 'no_regfullname' , !$enable_regfullname);
|
||||
DI::config()->set('system', 'register_notification' , $register_notification);
|
||||
DI::config()->set('system', 'community_page_style' , $community_page_style);
|
||||
DI::config()->set('system', 'max_author_posts_community_page', $max_author_posts_community_page);
|
||||
DI::config()->set('system', 'verifyssl' , $verifyssl);
|
||||
DI::config()->set('system', 'proxyuser' , $proxyuser);
|
||||
DI::config()->set('system', 'proxy' , $proxy);
|
||||
DI::config()->set('system', 'curl_timeout' , $timeout);
|
||||
DI::config()->set('system', 'imap_disabled' , !$mail_enabled && function_exists('imap_open'));
|
||||
DI::config()->set('system', 'ostatus_disabled' , !$ostatus_enabled);
|
||||
DI::config()->set('system', 'diaspora_enabled' , $diaspora_enabled);
|
||||
$transactionConfig->set('system', 'block_extended_register', !$enable_multi_reg);
|
||||
$transactionConfig->set('system', 'no_openid' , !$enable_openid);
|
||||
$transactionConfig->set('system', 'no_regfullname' , !$enable_regfullname);
|
||||
$transactionConfig->set('system', 'register_notification' , $register_notification);
|
||||
$transactionConfig->set('system', 'community_page_style' , $community_page_style);
|
||||
$transactionConfig->set('system', 'max_author_posts_community_page', $max_author_posts_community_page);
|
||||
$transactionConfig->set('system', 'verifyssl' , $verifyssl);
|
||||
$transactionConfig->set('system', 'proxyuser' , $proxyuser);
|
||||
$transactionConfig->set('system', 'proxy' , $proxy);
|
||||
$transactionConfig->set('system', 'curl_timeout' , $timeout);
|
||||
$transactionConfig->set('system', 'imap_disabled' , !$mail_enabled && function_exists('imap_open'));
|
||||
$transactionConfig->set('system', 'ostatus_disabled' , !$ostatus_enabled);
|
||||
$transactionConfig->set('system', 'diaspora_enabled' , $diaspora_enabled);
|
||||
|
||||
DI::config()->set('config', 'private_addons' , $private_addons);
|
||||
$transactionConfig->set('config', 'private_addons' , $private_addons);
|
||||
|
||||
DI::config()->set('system', 'force_ssl' , $force_ssl);
|
||||
DI::config()->set('system', 'hide_help' , !$show_help);
|
||||
$transactionConfig->set('system', 'force_ssl' , $force_ssl);
|
||||
$transactionConfig->set('system', 'hide_help' , !$show_help);
|
||||
|
||||
DI::config()->set('system', 'dbclean' , $dbclean);
|
||||
DI::config()->set('system', 'dbclean-expire-days' , $dbclean_expire_days);
|
||||
DI::config()->set('system', 'dbclean_expire_conversation', $dbclean_expire_conv);
|
||||
$transactionConfig->set('system', 'dbclean' , $dbclean);
|
||||
$transactionConfig->set('system', 'dbclean-expire-days' , $dbclean_expire_days);
|
||||
$transactionConfig->set('system', 'dbclean_expire_conversation', $dbclean_expire_conv);
|
||||
|
||||
if ($dbclean_unclaimed == 0) {
|
||||
$dbclean_unclaimed = $dbclean_expire_days;
|
||||
}
|
||||
|
||||
DI::config()->set('system', 'dbclean-expire-unclaimed', $dbclean_unclaimed);
|
||||
$transactionConfig->set('system', 'dbclean-expire-unclaimed', $dbclean_unclaimed);
|
||||
|
||||
DI::config()->set('system', 'max_comments', $max_comments);
|
||||
DI::config()->set('system', 'max_display_comments', $max_display_comments);
|
||||
$transactionConfig->set('system', 'max_comments', $max_comments);
|
||||
$transactionConfig->set('system', 'max_display_comments', $max_display_comments);
|
||||
|
||||
if ($temppath != '') {
|
||||
$temppath = BasePath::getRealPath($temppath);
|
||||
}
|
||||
|
||||
DI::config()->set('system', 'temppath', $temppath);
|
||||
$transactionConfig->set('system', 'temppath', $temppath);
|
||||
|
||||
DI::config()->set('system', 'only_tag_search' , $only_tag_search);
|
||||
DI::config()->set('system', 'compute_group_counts', $compute_group_counts);
|
||||
$transactionConfig->set('system', 'only_tag_search' , $only_tag_search);
|
||||
$transactionConfig->set('system', 'compute_group_counts', $compute_group_counts);
|
||||
|
||||
DI::config()->set('system', 'worker_queues' , $worker_queues);
|
||||
DI::config()->set('system', 'worker_fastlane' , $worker_fastlane);
|
||||
$transactionConfig->set('system', 'worker_queues' , $worker_queues);
|
||||
$transactionConfig->set('system', 'worker_fastlane' , $worker_fastlane);
|
||||
|
||||
DI::config()->set('system', 'relay_directly' , $relay_directly);
|
||||
DI::config()->set('system', 'relay_scope' , $relay_scope);
|
||||
DI::config()->set('system', 'relay_server_tags', $relay_server_tags);
|
||||
DI::config()->set('system', 'relay_deny_tags' , $relay_deny_tags);
|
||||
DI::config()->set('system', 'relay_user_tags' , $relay_user_tags);
|
||||
$transactionConfig->set('system', 'relay_directly' , $relay_directly);
|
||||
$transactionConfig->set('system', 'relay_scope' , $relay_scope);
|
||||
$transactionConfig->set('system', 'relay_server_tags', $relay_server_tags);
|
||||
$transactionConfig->set('system', 'relay_deny_tags' , $relay_deny_tags);
|
||||
$transactionConfig->set('system', 'relay_user_tags' , $relay_user_tags);
|
||||
|
||||
$transactionConfig->commit();
|
||||
|
||||
DI::baseUrl()->redirect('admin/site' . $active_panel);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ namespace Friendica\Module\Admin;
|
|||
|
||||
use Friendica\App;
|
||||
use Friendica\Core\Addon;
|
||||
use Friendica\Core\Config\Util\ConfigFileManager;
|
||||
use Friendica\Core\Config\ValueObject\Cache;
|
||||
use Friendica\Core\Logger;
|
||||
use Friendica\Core\Renderer;
|
||||
|
|
@ -114,6 +115,10 @@ class Summary extends BaseAdmin
|
|||
$warningtext[] = DI::l10n()->t('Friendica\'s configuration now is stored in config/local.config.php, please copy config/local-sample.config.php and move your config from <code>config/local.ini.php</code>. See <a href="%s">the Config help page</a> for help with the transition.', DI::baseUrl()->get() . '/help/Config');
|
||||
}
|
||||
|
||||
if (!DI::configFileManager()->dataIsWritable()) {
|
||||
$warningtext[] = DI::l10n()->t('Friendica\'s configuration store "%s" isn\'t writable. Until then database updates won\'t be applied automatically, admin settings and console configuration changes won\'t be saved.', ConfigFileManager::CONFIG_DATA_FILE);
|
||||
}
|
||||
|
||||
// Check server vitality
|
||||
if (!self::checkSelfHostMeta()) {
|
||||
$well_known = DI::baseUrl()->get() . Probe::HOST_META;
|
||||
|
|
@ -154,7 +159,7 @@ class Summary extends BaseAdmin
|
|||
}
|
||||
|
||||
// check legacy basepath settings
|
||||
$configLoader = (new Config())->createConfigFileLoader($a->getBasePath(), $_SERVER);
|
||||
$configLoader = (new Config())->createConfigFileManager($a->getBasePath(), $_SERVER);
|
||||
$configCache = new Cache();
|
||||
$configLoader->setupCache($configCache);
|
||||
$confBasepath = $configCache->get('system', 'basepath');
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ class ApiResponse extends Response
|
|||
|
||||
$data3 = [$root_element => $data2];
|
||||
|
||||
return XML::fromArray($data3, $xml, false, $namespaces);
|
||||
return XML::fromArray($data3, $dummy, false, $namespaces);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ class Friendica extends BaseModule
|
|||
|
||||
$visible_addons = Addon::getVisibleList();
|
||||
|
||||
$config->load('feature_lock');
|
||||
$config->reload();
|
||||
$locked_features = [];
|
||||
$featureLocks = $config->get('config', 'feature_lock');
|
||||
if (isset($featureLocks)) {
|
||||
|
|
|
|||
|
|
@ -43,8 +43,6 @@ class OpenSearch extends BaseModule
|
|||
$baseUrl = DI::baseUrl()->get();
|
||||
|
||||
/** @var DOMDocument $xml */
|
||||
$xml = null;
|
||||
|
||||
XML::fromArray([
|
||||
'OpenSearchDescription' => [
|
||||
'@attributes' => [
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ class ReallySimpleDiscovery extends BaseModule
|
|||
{
|
||||
protected function rawContent(array $request = [])
|
||||
{
|
||||
$xml = null;
|
||||
$content = XML::fromArray([
|
||||
'rsd' => [
|
||||
'@attributes' => [
|
||||
|
|
@ -67,7 +66,7 @@ class ReallySimpleDiscovery extends BaseModule
|
|||
],
|
||||
],
|
||||
],
|
||||
], $xml);
|
||||
]);
|
||||
System::httpExit($content, Response::TYPE_XML);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,6 @@ class Display extends BaseSettings
|
|||
$first_day_of_week = !empty($request['first_day_of_week']) ? intval($request['first_day_of_week']) : 0;
|
||||
$calendar_default_view = !empty($request['calendar_default_view']) ? trim($request['calendar_default_view']) : 'month';
|
||||
$infinite_scroll = !empty($request['infinite_scroll']) ? intval($request['infinite_scroll']) : 0;
|
||||
$no_auto_update = !empty($request['no_auto_update']) ? intval($request['no_auto_update']) : 0;
|
||||
$enable_smart_threading = !empty($request['enable_smart_threading']) ? intval($request['enable_smart_threading']) : 0;
|
||||
$enable_dislike = !empty($request['enable_dislike']) ? intval($request['enable_dislike']) : 0;
|
||||
$display_resharer = !empty($request['display_resharer']) ? intval($request['display_resharer']) : 0;
|
||||
|
|
@ -113,7 +112,6 @@ class Display extends BaseSettings
|
|||
$this->pConfig->set($uid, 'system', 'itemspage_network' , $itemspage_network);
|
||||
$this->pConfig->set($uid, 'system', 'itemspage_mobile_network', $itemspage_mobile_network);
|
||||
$this->pConfig->set($uid, 'system', 'update_interval' , $browser_update);
|
||||
$this->pConfig->set($uid, 'system', 'no_auto_update' , $no_auto_update);
|
||||
$this->pConfig->set($uid, 'system', 'no_smilies' , !$enable_smile);
|
||||
$this->pConfig->set($uid, 'system', 'infinite_scroll' , $infinite_scroll);
|
||||
$this->pConfig->set($uid, 'system', 'no_smart_threading' , !$enable_smart_threading);
|
||||
|
|
@ -202,7 +200,6 @@ class Display extends BaseSettings
|
|||
$browser_update = (($browser_update == 0) ? 40 : $browser_update / 1000); // default if not set: 40 seconds
|
||||
}
|
||||
|
||||
$no_auto_update = $this->pConfig->get($uid, 'system', 'no_auto_update', 0);
|
||||
$enable_smile = !$this->pConfig->get($uid, 'system', 'no_smilies', 0);
|
||||
$infinite_scroll = $this->pConfig->get($uid, 'system', 'infinite_scroll', 0);
|
||||
$enable_smart_threading = !$this->pConfig->get($uid, 'system', 'no_smart_threading', 0);
|
||||
|
|
@ -265,7 +262,6 @@ class Display extends BaseSettings
|
|||
'$itemspage_network' => ['itemspage_network' , $this->t('Number of items to display per page:'), $itemspage_network, $this->t('Maximum of 100 items')],
|
||||
'$itemspage_mobile_network' => ['itemspage_mobile_network', $this->t('Number of items to display per page when viewed from mobile device:'), $itemspage_mobile_network, $this->t('Maximum of 100 items')],
|
||||
'$ajaxint' => ['browser_update' , $this->t('Update browser every xx seconds'), $browser_update, $this->t('Minimum of 10 seconds. Enter -1 to disable it.')],
|
||||
'$no_auto_update' => ['no_auto_update' , $this->t('Automatic updates only at the top of the post stream pages'), $no_auto_update, $this->t('Auto update may add new posts at the top of the post stream pages, which can affect the scroll position and perturb normal reading if it happens anywhere else the top of the page.')],
|
||||
'$enable_smile' => ['enable_smile' , $this->t('Display emoticons'), $enable_smile, $this->t('When enabled, emoticons are replaced with matching symbols.')],
|
||||
'$infinite_scroll' => ['infinite_scroll' , $this->t('Infinite scroll'), $infinite_scroll, $this->t('Automatic fetch new items when reaching the page end.')],
|
||||
'$enable_smart_threading' => ['enable_smart_threading' , $this->t('Enable Smart Threading'), $enable_smart_threading, $this->t('Enable the automatic suppression of extraneous thread indentation.')],
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class Community extends CommunityModule
|
|||
$this->parseRequest();
|
||||
|
||||
$o = '';
|
||||
if (!empty($_GET['force']) || !DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'no_auto_update')) {
|
||||
if (!empty($request['force'])) {
|
||||
$o = DI::conversation()->create(self::getItems(), 'community', true, false, 'commented', DI::userSession()->getLocalUserId());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,53 +31,55 @@ class Network extends NetworkModule
|
|||
{
|
||||
protected function rawContent(array $request = [])
|
||||
{
|
||||
if (!isset($_GET['p']) || !isset($_GET['item'])) {
|
||||
if (!isset($request['p']) || !isset($request['item'])) {
|
||||
System::exit();
|
||||
}
|
||||
|
||||
$this->parseRequest($_GET);
|
||||
$this->parseRequest($request);
|
||||
|
||||
$profile_uid = intval($_GET['p']);
|
||||
$profile_uid = intval($request['p']);
|
||||
|
||||
$o = '';
|
||||
|
||||
if (!DI::pConfig()->get($profile_uid, 'system', 'no_auto_update') || ($_GET['force'] == 1)) {
|
||||
if (!empty($_GET['item'])) {
|
||||
$item = Post::selectFirst(['parent'], ['id' => $_GET['item']]);
|
||||
$parent = $item['parent'] ?? 0;
|
||||
} else {
|
||||
$parent = 0;
|
||||
}
|
||||
|
||||
$conditionFields = [];
|
||||
if (!empty($parent)) {
|
||||
// Load only a single thread
|
||||
$conditionFields['parent'] = $parent;
|
||||
} elseif (self::$order === 'received') {
|
||||
// Only load new toplevel posts
|
||||
$conditionFields['unseen'] = true;
|
||||
$conditionFields['gravity'] = Item::GRAVITY_PARENT;
|
||||
} else {
|
||||
// Load all unseen items
|
||||
$conditionFields['unseen'] = true;
|
||||
}
|
||||
|
||||
$params = ['limit' => 100];
|
||||
$table = 'network-item-view';
|
||||
|
||||
$items = self::getItems($table, $params, $conditionFields);
|
||||
|
||||
if (self::$order === 'received') {
|
||||
$ordering = '`received`';
|
||||
} elseif (self::$order === 'created') {
|
||||
$ordering = '`created`';
|
||||
} else {
|
||||
$ordering = '`commented`';
|
||||
}
|
||||
|
||||
$o = DI::conversation()->create($items, 'network', $profile_uid, false, $ordering, DI::userSession()->getLocalUserId());
|
||||
if (empty($request['force'])) {
|
||||
System::htmlUpdateExit($o);
|
||||
}
|
||||
|
||||
if (!empty($request['item'])) {
|
||||
$item = Post::selectFirst(['parent'], ['id' => $request['item']]);
|
||||
$parent = $item['parent'] ?? 0;
|
||||
} else {
|
||||
$parent = 0;
|
||||
}
|
||||
|
||||
$conditionFields = [];
|
||||
if (!empty($parent)) {
|
||||
// Load only a single thread
|
||||
$conditionFields['parent'] = $parent;
|
||||
} elseif (self::$order === 'received') {
|
||||
// Only load new toplevel posts
|
||||
$conditionFields['unseen'] = true;
|
||||
$conditionFields['gravity'] = Item::GRAVITY_PARENT;
|
||||
} else {
|
||||
// Load all unseen items
|
||||
$conditionFields['unseen'] = true;
|
||||
}
|
||||
|
||||
$params = ['limit' => 100];
|
||||
$table = 'network-item-view';
|
||||
|
||||
$items = self::getItems($table, $params, $conditionFields);
|
||||
|
||||
if (self::$order === 'received') {
|
||||
$ordering = '`received`';
|
||||
} elseif (self::$order === 'created') {
|
||||
$ordering = '`created`';
|
||||
} else {
|
||||
$ordering = '`commented`';
|
||||
}
|
||||
|
||||
$o = DI::conversation()->create($items, 'network', $profile_uid, false, $ordering, DI::userSession()->getLocalUserId());
|
||||
|
||||
System::htmlUpdateExit($o);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class Profile extends BaseModule
|
|||
$a = DI::app();
|
||||
|
||||
// Ensure we've got a profile owner if updating.
|
||||
$a->setProfileOwner((int)($_GET['p'] ?? 0));
|
||||
$a->setProfileOwner((int)($request['p'] ?? 0));
|
||||
|
||||
if (DI::config()->get('system', 'block_public') && !DI::userSession()->getLocalUserId() && !DI::userSession()->getRemoteContactID($a->getProfileOwner())) {
|
||||
throw new ForbiddenException();
|
||||
|
|
@ -58,7 +58,7 @@ class Profile extends BaseModule
|
|||
|
||||
$o = '';
|
||||
|
||||
if (empty($_GET['force']) && DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'no_auto_update')) {
|
||||
if (empty($request['force'])) {
|
||||
System::htmlUpdateExit($o);
|
||||
}
|
||||
|
||||
|
|
@ -73,9 +73,9 @@ class Profile extends BaseModule
|
|||
AND `visible` AND (NOT `deleted` OR `gravity` = ?)
|
||||
AND `wall` " . $sql_extra, $a->getProfileOwner(), Item::GRAVITY_ACTIVITY];
|
||||
|
||||
if ($_GET['force'] && !empty($_GET['item'])) {
|
||||
if ($request['force'] && !empty($request['item'])) {
|
||||
// When the parent is provided, we only fetch this
|
||||
$condition = DBA::mergeConditions($condition, ['parent' => $_GET['item']]);
|
||||
$condition = DBA::mergeConditions($condition, ['parent' => $request['item']]);
|
||||
} elseif ($is_owner || !$last_updated) {
|
||||
// If the page user is the owner of the page we should query for unseen
|
||||
// items. Otherwise use a timestamp of the last succesful update request.
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ class HostMeta extends BaseModule
|
|||
|
||||
$domain = DI::baseUrl()->get();
|
||||
|
||||
$xml = null;
|
||||
XML::fromArray([
|
||||
'XRD' => [
|
||||
'@attributes' => [
|
||||
|
|
@ -81,13 +80,6 @@ class HostMeta extends BaseModule
|
|||
'href' => $domain . '/amcd'
|
||||
]
|
||||
],
|
||||
'5:link' => [
|
||||
'@attributes' => [
|
||||
'rel' => 'http://oexchange.org/spec/0.8/rel/resident-target',
|
||||
'type' => 'application/xrd+xml',
|
||||
'href' => $domain . '/oexchange/xrd'
|
||||
]
|
||||
],
|
||||
'Property' => [
|
||||
'@attributes' => [
|
||||
'type' => 'http://salmon-protocol.org/ns/magic-key',
|
||||
|
|
|
|||
|
|
@ -230,9 +230,7 @@ class Xrd extends BaseModule
|
|||
{
|
||||
$baseURL = $this->baseUrl->get();
|
||||
|
||||
$xml = null;
|
||||
|
||||
XML::fromArray([
|
||||
$xmlString = XML::fromArray([
|
||||
'XRD' => [
|
||||
'@attributes' => [
|
||||
'xmlns' => 'http://docs.oasis-open.org/ns/xri/xrd-1.0',
|
||||
|
|
@ -319,10 +317,10 @@ class Xrd extends BaseModule
|
|||
]
|
||||
],
|
||||
],
|
||||
], $xml);
|
||||
]);
|
||||
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
|
||||
System::httpExit($xml->saveXML(), Response::TYPE_XML, 'application/xrd+xml');
|
||||
System::httpExit($xmlString, Response::TYPE_XML, 'application/xrd+xml');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,11 +50,11 @@ class Subscription extends BaseDataTransferObject
|
|||
$this->id = (string)$subscription['id'];
|
||||
$this->endpoint = $subscription['endpoint'];
|
||||
$this->alerts = [
|
||||
Notification::TYPE_FOLLOW => $subscription[Notification::TYPE_FOLLOW],
|
||||
Notification::TYPE_LIKE => $subscription[Notification::TYPE_LIKE],
|
||||
Notification::TYPE_RESHARE => $subscription[Notification::TYPE_RESHARE],
|
||||
Notification::TYPE_MENTION => $subscription[Notification::TYPE_MENTION],
|
||||
Notification::TYPE_POLL => $subscription[Notification::TYPE_POLL],
|
||||
Notification::TYPE_FOLLOW => (bool)$subscription[Notification::TYPE_FOLLOW],
|
||||
Notification::TYPE_LIKE => (bool)$subscription[Notification::TYPE_LIKE],
|
||||
Notification::TYPE_RESHARE => (bool)$subscription[Notification::TYPE_RESHARE],
|
||||
Notification::TYPE_MENTION => (bool)$subscription[Notification::TYPE_MENTION],
|
||||
Notification::TYPE_POLL => (bool)$subscription[Notification::TYPE_POLL],
|
||||
];
|
||||
|
||||
$this->server_key = $vapid;
|
||||
|
|
|
|||
|
|
@ -2855,7 +2855,7 @@ class Diaspora
|
|||
|
||||
$namespaces = ['me' => ActivityNamespace::SALMON_ME];
|
||||
|
||||
return XML::fromArray($xmldata, $xml, false, $namespaces);
|
||||
return XML::fromArray($xmldata, $dummy, false, $namespaces);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2974,12 +2974,11 @@ class Diaspora
|
|||
* @param array $message The message data
|
||||
*
|
||||
* @return string The post XML
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function buildPostXml(string $type, array $message): string
|
||||
{
|
||||
$data = [$type => $message];
|
||||
|
||||
return XML::fromArray($data, $xml);
|
||||
return XML::fromArray([$type => $message]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ class Salmon
|
|||
|
||||
$namespaces = ['me' => ActivityNamespace::SALMON_ME];
|
||||
|
||||
$salmon = XML::fromArray($xmldata, $xml, false, $namespaces);
|
||||
$salmon = XML::fromArray($xmldata, $dummy, false, $namespaces);
|
||||
|
||||
// slap them
|
||||
$postResult = DI::httpClient()->post($url, $salmon, [
|
||||
|
|
@ -187,9 +187,7 @@ class Salmon
|
|||
]
|
||||
];
|
||||
|
||||
$namespaces = ['me' => ActivityNamespace::SALMON_ME];
|
||||
|
||||
$salmon = XML::fromArray($xmldata, $xml, false, $namespaces);
|
||||
$salmon = XML::fromArray($xmldata, $dummy, false, $namespaces);
|
||||
|
||||
// slap them
|
||||
$postResult = DI::httpClient()->post($url, $salmon, [
|
||||
|
|
@ -214,9 +212,7 @@ class Salmon
|
|||
]
|
||||
];
|
||||
|
||||
$namespaces = ['me' => ActivityNamespace::SALMON_ME];
|
||||
|
||||
$salmon = XML::fromArray($xmldata, $xml, false, $namespaces);
|
||||
$salmon = XML::fromArray($xmldata, $dummy, false, $namespaces);
|
||||
|
||||
// slap them
|
||||
$postResult = DI::httpClient()->post($url, $salmon, [
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ use Friendica\Network\HTTPClient\Client\HttpClientAccept;
|
|||
use Friendica\Network\HTTPClient\Client\HttpClientOptions;
|
||||
use Friendica\Network\HTTPException\NotModifiedException;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
class Network
|
||||
{
|
||||
|
|
@ -177,11 +178,28 @@ class Network
|
|||
* @param string $url The url to check the domain from
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @deprecated since 2023.03 Use isUriBlocked instead
|
||||
*/
|
||||
public static function isUrlBlocked(string $url): bool
|
||||
{
|
||||
$host = @parse_url($url, PHP_URL_HOST);
|
||||
if (!$host) {
|
||||
try {
|
||||
return self::isUriBlocked(new Uri($url));
|
||||
} catch (\Throwable $e) {
|
||||
Logger::warning('Invalid URL', ['url' => $url]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the provided URI domain is on the domain blocklist.
|
||||
*
|
||||
* @param UriInterface $uri
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isUriBlocked(UriInterface $uri): bool
|
||||
{
|
||||
if (!$uri->getHost()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -191,7 +209,7 @@ class Network
|
|||
}
|
||||
|
||||
foreach ($domain_blocklist as $domain_block) {
|
||||
if (fnmatch(strtolower($domain_block['domain']), strtolower($host))) {
|
||||
if (fnmatch(strtolower($domain_block['domain']), strtolower($uri->getHost()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,14 +37,15 @@ class XML
|
|||
/**
|
||||
* Creates an XML structure out of a given array
|
||||
*
|
||||
* @param array $array The array of the XML structure that will be generated
|
||||
* @param object $xml The created XML will be returned by reference
|
||||
* @param bool $remove_header Should the XML header be removed or not?
|
||||
* @param array $namespaces List of namespaces
|
||||
* @param bool $root interally used parameter. Mustn't be used from outside.
|
||||
* @param array $array The array of the XML structure that will be generated
|
||||
* @param object|null $xml The created XML will be returned by reference
|
||||
* @param bool $remove_header Should the XML header be removed or not?
|
||||
* @param array $namespaces List of namespaces
|
||||
* @param bool $root interally used parameter. Mustn't be used from outside.
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function fromArray(array $array, &$xml, bool $remove_header = false, array $namespaces = [], bool $root = true): string
|
||||
public static function fromArray(array $array, object &$xml = null, bool $remove_header = false, array $namespaces = [], bool $root = true): string
|
||||
{
|
||||
if ($root) {
|
||||
foreach ($array as $key => $value) {
|
||||
|
|
@ -125,7 +126,7 @@ class XML
|
|||
|
||||
if (!is_array($value)) {
|
||||
$element = $xml->addChild($key, self::escape($value ?? ''), $namespace);
|
||||
} elseif (is_array($value)) {
|
||||
} else {
|
||||
$element = $xml->addChild($key, null, $namespace);
|
||||
self::fromArray($value, $element, $remove_header, $namespaces, false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class DBUpdate
|
|||
public static function execute()
|
||||
{
|
||||
// Just in case the last update wasn't failed
|
||||
if (DI::config()->get('system', 'update', Update::SUCCESS, true) != Update::FAILED) {
|
||||
if (DI::config()->get('system', 'update', Update::SUCCESS) != Update::FAILED) {
|
||||
Update::run(DI::app()->getBasePath());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ use Friendica\Core\Logger;
|
|||
use Friendica\Core\Worker;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Network\HTTPException\InternalServerErrorException;
|
||||
use Friendica\Util\Network;
|
||||
|
||||
class UpdateContact
|
||||
{
|
||||
|
|
@ -38,6 +39,11 @@ class UpdateContact
|
|||
*/
|
||||
public static function execute(int $contact_id)
|
||||
{
|
||||
// Silently dropping the task if the contact is blocked
|
||||
if (Contact::isBlocked($contact_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$success = Contact::updateFromProbe($contact_id);
|
||||
|
||||
Logger::info('Updated from probe', ['id' => $contact_id, 'success' => $success]);
|
||||
|
|
@ -55,6 +61,11 @@ class UpdateContact
|
|||
throw new \InvalidArgumentException('Invalid value provided for contact_id');
|
||||
}
|
||||
|
||||
// Dropping the task if the contact is blocked
|
||||
if (Contact::isBlocked($contact_id)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Worker::add($run_parameters, 'UpdateContact', $contact_id);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,9 +22,14 @@
|
|||
namespace Friendica\Worker;
|
||||
|
||||
use Friendica\Core\Logger;
|
||||
use Friendica\Core\Worker;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\Model\GServer;
|
||||
use Friendica\Network\HTTPException\InternalServerErrorException;
|
||||
use Friendica\Util\Network;
|
||||
use Friendica\Util\Strings;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
class UpdateGServer
|
||||
{
|
||||
|
|
@ -34,8 +39,9 @@ class UpdateGServer
|
|||
* @param string $server_url Server URL
|
||||
* @param boolean $only_nodeinfo Only use nodeinfo for server detection
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function execute(string $server_url, bool $only_nodeinfo = false)
|
||||
public static function execute(string $server_url, bool $only_nodeinfo)
|
||||
{
|
||||
if (empty($server_url)) {
|
||||
return;
|
||||
|
|
@ -47,6 +53,11 @@ class UpdateGServer
|
|||
return;
|
||||
}
|
||||
|
||||
// Silently dropping the worker task if the server domain is blocked
|
||||
if (Network::isUrlBlocked($filtered)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (($filtered != $server_url) && DBA::exists('gserver', ['nurl' => Strings::normaliseLink($server_url)])) {
|
||||
GServer::setFailureByUrl($server_url);
|
||||
return;
|
||||
|
|
@ -61,4 +72,23 @@ class UpdateGServer
|
|||
$ret = GServer::check($filtered, '', true, $only_nodeinfo);
|
||||
Logger::info('Updated gserver', ['url' => $filtered, 'result' => $ret]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|int $run_parameters Priority constant or array of options described in Worker::add
|
||||
* @param string $serverUrl
|
||||
* @param bool $onlyNodeInfo Only use NodeInfo for server detection
|
||||
* @return int
|
||||
* @throws InternalServerErrorException
|
||||
*/
|
||||
public static function add($run_parameters, string $serverUrl, bool $onlyNodeInfo = false): int
|
||||
{
|
||||
// Dropping the worker task if the server domain is blocked
|
||||
if (Network::isUrlBlocked($serverUrl)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// We have to convert the Uri back to string because worker parameters are saved in JSON format which
|
||||
// doesn't allow for structured objects.
|
||||
return Worker::add($run_parameters, 'UpdateGServer', $serverUrl, $onlyNodeInfo);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ use Friendica\Database\DBA;
|
|||
use Friendica\DI;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\Strings;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
|
||||
class UpdateGServers
|
||||
{
|
||||
|
|
@ -63,12 +64,12 @@ class UpdateGServers
|
|||
// There are duplicated "url" but not "nurl". So we check both addresses instead of just overwriting them,
|
||||
// since that would mean loosing data.
|
||||
if (!empty($gserver['url'])) {
|
||||
if (Worker::add(Worker::PRIORITY_LOW, 'UpdateGServer', $gserver['url'])) {
|
||||
if (UpdateGServer::add(Worker::PRIORITY_LOW, $gserver['url'])) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
if (!empty($gserver['nurl']) && ($gserver['nurl'] != Strings::normaliseLink($gserver['url']))) {
|
||||
if (Worker::add(Worker::PRIORITY_LOW, 'UpdateGServer', $gserver['nurl'])) {
|
||||
if (UpdateGServer::add(Worker::PRIORITY_LOW, $gserver['nurl'])) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
use Friendica\Database\DBA;
|
||||
|
||||
if (!defined('DB_UPDATE_VERSION')) {
|
||||
define('DB_UPDATE_VERSION', 1507);
|
||||
define('DB_UPDATE_VERSION', 1509);
|
||||
}
|
||||
|
||||
return [
|
||||
|
|
@ -553,19 +553,6 @@ return [
|
|||
"k_expires" => ["k", "expires"],
|
||||
]
|
||||
],
|
||||
"config" => [
|
||||
"comment" => "main configuration storage",
|
||||
"fields" => [
|
||||
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
|
||||
"cat" => ["type" => "varbinary(50)", "not null" => "1", "default" => "", "comment" => ""],
|
||||
"k" => ["type" => "varbinary(50)", "not null" => "1", "default" => "", "comment" => ""],
|
||||
"v" => ["type" => "mediumtext", "comment" => ""],
|
||||
],
|
||||
"indexes" => [
|
||||
"PRIMARY" => ["id"],
|
||||
"cat_k" => ["UNIQUE", "cat", "k"],
|
||||
]
|
||||
],
|
||||
"contact-relation" => [
|
||||
"comment" => "Contact relations",
|
||||
"fields" => [
|
||||
|
|
|
|||
|
|
@ -76,10 +76,10 @@ return [
|
|||
$_SERVER
|
||||
]
|
||||
],
|
||||
Config\Util\ConfigFileLoader::class => [
|
||||
Config\Util\ConfigFileManager::class => [
|
||||
'instanceOf' => Config\Factory\Config::class,
|
||||
'call' => [
|
||||
['createConfigFileLoader', [
|
||||
['createConfigFileManager', [
|
||||
[Dice::INSTANCE => '$basepath'],
|
||||
$_SERVER,
|
||||
], Dice::CHAIN_CALL],
|
||||
|
|
@ -88,7 +88,7 @@ return [
|
|||
Config\ValueObject\Cache::class => [
|
||||
'instanceOf' => Config\Factory\Config::class,
|
||||
'call' => [
|
||||
['createCache', [$_SERVER], Dice::CHAIN_CALL],
|
||||
['createCache', [], Dice::CHAIN_CALL],
|
||||
],
|
||||
],
|
||||
App\Mode::class => [
|
||||
|
|
@ -98,9 +98,9 @@ return [
|
|||
],
|
||||
],
|
||||
Config\Capability\IManageConfigValues::class => [
|
||||
'instanceOf' => Config\Factory\Config::class,
|
||||
'call' => [
|
||||
['create', [], Dice::CHAIN_CALL],
|
||||
'instanceOf' => Config\Model\Config::class,
|
||||
'constructParams' => [
|
||||
$_SERVER,
|
||||
],
|
||||
],
|
||||
PConfig\Capability\IManagePersonalConfigValues::class => [
|
||||
|
|
|
|||
|
|
@ -52,10 +52,6 @@ return [
|
|||
// Enter 0 for no time limit.
|
||||
'account_abandon_days' => 0,
|
||||
|
||||
// addon (Comma-separated list)
|
||||
// Manual list of addons which are enabled on this system.
|
||||
'addon' => '',
|
||||
|
||||
// add_missing_posts (boolean)
|
||||
// Checks for missing entries in "post", "post-thread" or "post-thread-user" and creates them
|
||||
'add_missing_posts' => false,
|
||||
|
|
|
|||
|
|
@ -25,20 +25,24 @@ namespace Friendica\Test;
|
|||
use Dice\Dice;
|
||||
use Friendica\App\Arguments;
|
||||
use Friendica\App\Router;
|
||||
use Friendica\Core\Config\Factory\Config;
|
||||
use Friendica\Core\Config\Util\ConfigFileManager;
|
||||
use Friendica\Core\Config\ValueObject\Cache;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\Session\Capability\IHandleSessions;
|
||||
use Friendica\Core\Session\Type\Memory;
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Database\DBStructure;
|
||||
use Friendica\DI;
|
||||
use Friendica\Test\Util\Database\StaticDatabase;
|
||||
use Friendica\Test\Util\VFSTrait;
|
||||
|
||||
/**
|
||||
* Parent class for test cases requiring fixtures
|
||||
*/
|
||||
abstract class FixtureTest extends DatabaseTest
|
||||
{
|
||||
use VFSTrait;
|
||||
|
||||
/** @var Dice */
|
||||
protected $dice;
|
||||
|
||||
|
|
@ -47,6 +51,8 @@ abstract class FixtureTest extends DatabaseTest
|
|||
*/
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->setUpVfsDir();
|
||||
|
||||
parent::setUp();
|
||||
|
||||
$server = $_SERVER;
|
||||
|
|
@ -54,6 +60,10 @@ abstract class FixtureTest extends DatabaseTest
|
|||
|
||||
$this->dice = (new Dice())
|
||||
->addRules(include __DIR__ . '/../static/dependencies.config.php')
|
||||
->addRule(ConfigFileManager::class, [
|
||||
'instanceOf' => Config::class,
|
||||
'call' => [['createConfigFileManager', [$this->root->url(), $server,],
|
||||
Dice::CHAIN_CALL]]])
|
||||
->addRule(Database::class, ['instanceOf' => StaticDatabase::class, 'shared' => true])
|
||||
->addRule(IHandleSessions::class, ['instanceOf' => Memory::class, 'shared' => true, 'call' => null])
|
||||
->addRule(Arguments::class, [
|
||||
|
|
@ -64,7 +74,6 @@ abstract class FixtureTest extends DatabaseTest
|
|||
]);
|
||||
DI::init($this->dice);
|
||||
|
||||
/** @var IManageConfigValues $config */
|
||||
$configCache = $this->dice->create(Cache::class);
|
||||
$configCache->set('database', 'disable_pdo', true);
|
||||
|
||||
|
|
|
|||
|
|
@ -54,6 +54,21 @@ trait VFSTrait
|
|||
$this->setConfigFile('defaults.config.php', true);
|
||||
$this->setConfigFile('settings.config.php', true);
|
||||
$this->setConfigFile('local.config.php');
|
||||
$this->setDataFile('node.config.php');
|
||||
}
|
||||
|
||||
protected function setDataFile(string $filename)
|
||||
{
|
||||
$file = dirname(__DIR__) . DIRECTORY_SEPARATOR .
|
||||
'datasets' . DIRECTORY_SEPARATOR .
|
||||
'config' . DIRECTORY_SEPARATOR .
|
||||
$filename;
|
||||
|
||||
if (file_exists($file)) {
|
||||
vfsStream::newFile($filename)
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(file_get_contents($file));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -36,33 +36,6 @@ return [
|
|||
'mail',
|
||||
'post-delivery-data',
|
||||
// Base test config to avoid notice messages
|
||||
'config' => [
|
||||
[
|
||||
'cat' => 'system',
|
||||
'k' => 'url',
|
||||
'v' => 'http://localhost',
|
||||
],
|
||||
[
|
||||
'cat' => 'config',
|
||||
'k' => 'hostname',
|
||||
'v' => 'localhost',
|
||||
],
|
||||
[
|
||||
'cat' => 'system',
|
||||
'k' => 'worker_dont_fork',
|
||||
'v' => '1',
|
||||
],
|
||||
[
|
||||
'cat' => 'system',
|
||||
'k' => 'curl_timeout',
|
||||
'v' => '1',
|
||||
],
|
||||
[
|
||||
'cat' => 'system',
|
||||
'k' => 'xrd_timeout',
|
||||
'v' => '1',
|
||||
],
|
||||
],
|
||||
'user' => [
|
||||
[
|
||||
'uid' => 42,
|
||||
|
|
|
|||
22
tests/datasets/config/A.node.config.php
Normal file
22
tests/datasets/config/A.node.config.php
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'database' => [
|
||||
'hostname' => 'testhost',
|
||||
'username' => 'testuser',
|
||||
'password' => 'testpw',
|
||||
'database' => 'testdb',
|
||||
'charset' => 'utf8mb4',
|
||||
],
|
||||
'config' => [
|
||||
'admin_email' => 'admin@test.it',
|
||||
'sitename' => 'Friendica Social Network',
|
||||
'register_policy' => 2,
|
||||
'register_text' => '',
|
||||
],
|
||||
'system' => [
|
||||
'default_timezone' => 'UTC',
|
||||
'language' => 'en',
|
||||
'theme' => 'frio',
|
||||
],
|
||||
];
|
||||
39
tests/datasets/config/B.node.config.php
Normal file
39
tests/datasets/config/B.node.config.php
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'database' => [
|
||||
'hostname' => 'testhost',
|
||||
'username' => 'testuser',
|
||||
'password' => 'testpw',
|
||||
'database' => 'testdb',
|
||||
'charset' => 'utf8mb4',
|
||||
],
|
||||
'config' => [
|
||||
'admin_email' => 'admin@test.it',
|
||||
'sitename' => 'Friendica Social Network',
|
||||
'register_policy' => 2,
|
||||
'register_text' => '',
|
||||
'test' => [
|
||||
'a' => [
|
||||
'next' => 'value',
|
||||
'bool' => false,
|
||||
'innerArray' => [
|
||||
'a' => 4.55,
|
||||
'b' => false,
|
||||
'string2' => 'false',
|
||||
],
|
||||
],
|
||||
'v' => true,
|
||||
'v3' => 1,
|
||||
'v4' => 5.6443,
|
||||
],
|
||||
],
|
||||
'system' => [
|
||||
'default_timezone' => 'UTC',
|
||||
'language' => 'en',
|
||||
'theme' => 'frio',
|
||||
'int' => 23,
|
||||
'float' => 2.5,
|
||||
'with special chars' => 'I can\'t follow this "$&§%"$%§$%&\'[),',
|
||||
],
|
||||
];
|
||||
48
tests/datasets/config/C.node.config.php
Normal file
48
tests/datasets/config/C.node.config.php
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'config' => [
|
||||
'hostname' => 'friendica.local',
|
||||
],
|
||||
'system' => [
|
||||
'disable_email_validation' => 1,
|
||||
'disable_password_exposed' => 1,
|
||||
'throttle_limit_day' => 100,
|
||||
'throttle_limit_week' => 100,
|
||||
'throttle_limit_month' => 100,
|
||||
'temppath' => '/tmp/friendica.local',
|
||||
'theme' => 'frio',
|
||||
'url' => 'https://friendica.local',
|
||||
'urlpath' => '',
|
||||
'build' => 1508,
|
||||
'maintenance' => false,
|
||||
'dbupdate' => 1,
|
||||
'update' => 0,
|
||||
'spoolpath' => '/tmp/localhost/spool',
|
||||
'actor_name' => 'friendica',
|
||||
'site_prvkey' => '-----BEGIN PRIVATE KEY-----
|
||||
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALgypZoZ2X7rYCHT
|
||||
pXZRPKZYOJrtzAZoAD6a2FESfax/mW7tGF8/XGcsu4E8a0WUs18CDb09iDlECs0r
|
||||
WFkyxOsS55FyDPVNOVheU6ziqmjTNggr1qR8iIpPW2xHAnFjCfvJxgaUfszdoeUV
|
||||
mhA++BrxFGRpfcH49O+dVcjisJEVAgMBAAECgYEAq0QsRkSSvjgMgmdQCdsvEVwm
|
||||
BafldG9vCsbfK0KOJ73c5A8AAk/fku88yMVs2J2SylwWekakStrBUFNlKkrSXEv3
|
||||
r1l0b+dfniaTGJkawqgRh+U/0G9LN+cdZYt5EuhNhCbmIQB+FOI12jAx6COwEENi
|
||||
824zrrwn0BU1VTOMwwECQQDnBqq0J9JCJAtjqX+3xd8DvTRYjYvtvXlQ8fwrGxBc
|
||||
GwURNG8aMGTaj+sn2kVWNt4wLQqj/CTJ42y0bkKYMJftAkEAzBwSqfuMZD/+nEkM
|
||||
wDQb1G2z+BaxLh5JJQo80WX9tORbspOkbEuPgFprO6NB0/vNH5m4AaL3jymokH1p
|
||||
JfVoyQJBAN+GSsmOMdf+qepeiA0V7OXgPXJkWXvHtEZGK1bFk7maBvgThF+RbTMu
|
||||
xjZD8IwvACEao03wWuPfIEEe4V4Avi0CQCc5FdUYg+gX7CO4XfzphpeR5U29fprw
|
||||
MvotN3a99L04TO7KNISjGJZ/ya+SNeo4rzhtX9DgslYOmVf64aPrvxECQQDB79vF
|
||||
Kx2HyacBSErXrlqqkPdFo8KxhKCAVhrs0VBU1WPswolzsZvRdFuielhGP49DjjE7
|
||||
JV1Als1hl1xTduNb
|
||||
-----END PRIVATE KEY-----
|
||||
',
|
||||
'site_pubkey' => '-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4MqWaGdl+62Ah06V2UTymWDia
|
||||
7cwGaAA+mthREn2sf5lu7RhfP1xnLLuBPGtFlLNfAg29PYg5RArNK1hZMsTrEueR
|
||||
cgz1TTlYXlOs4qpo0zYIK9akfIiKT1tsRwJxYwn7ycYGlH7M3aHlFZoQPvga8RRk
|
||||
aX3B+PTvnVXI4rCRFQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
',
|
||||
],
|
||||
];
|
||||
13
tests/datasets/config/node.config.php
Normal file
13
tests/datasets/config/node.config.php
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'config' => [
|
||||
'hostname' => 'localhost',
|
||||
],
|
||||
'system' => [
|
||||
'url' => 'http://localhost',
|
||||
"worker_dont_fork" => 1,
|
||||
"curl_timeout"=> 1,
|
||||
"xrd_timeout"=> 1,
|
||||
],
|
||||
];
|
||||
|
|
@ -31,7 +31,7 @@ use Friendica\Core\Lock\Capability\ICanLock;
|
|||
use Friendica\Database\Database;
|
||||
use Friendica\Test\Util\VFSTrait;
|
||||
use Friendica\Util\BasePath;
|
||||
use Friendica\Core\Config\Util\ConfigFileLoader;
|
||||
use Friendica\Core\Config\Util\ConfigFileManager;
|
||||
use Friendica\Util\Profiler;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
|
@ -73,13 +73,13 @@ class DependencyCheckTest extends TestCase
|
|||
*/
|
||||
public function testConfigFileLoader()
|
||||
{
|
||||
/** @var ConfigFileLoader $configFileLoader */
|
||||
$configFileLoader = $this->dice->create(ConfigFileLoader::class);
|
||||
/** @var ConfigFileManager $configFileManager */
|
||||
$configFileManager = $this->dice->create(ConfigFileManager::class);
|
||||
|
||||
self::assertInstanceOf(ConfigFileLoader::class, $configFileLoader);
|
||||
self::assertInstanceOf(ConfigFileManager::class, $configFileManager);
|
||||
|
||||
$configCache = new Cache();
|
||||
$configFileLoader->setupCache($configCache);
|
||||
$configFileManager->setupCache($configCache);
|
||||
|
||||
self::assertNotEmpty($configCache->getAll());
|
||||
self::assertArrayHasKey('database', $configCache->getAll());
|
||||
|
|
@ -150,7 +150,6 @@ class DependencyCheckTest extends TestCase
|
|||
|
||||
self::assertTrue($mode->has(App\Mode::LOCALCONFIGPRESENT), 'No local config present');
|
||||
self::assertTrue($mode->has(App\Mode::DBAVAILABLE), 'Database is not available');
|
||||
self::assertTrue($mode->has(App\Mode::DBCONFIGAVAILABLE), 'Database config is not available');
|
||||
self::assertTrue($mode->has(App\Mode::MAINTENANCEDISABLED), 'In maintenance mode');
|
||||
|
||||
self::assertTrue($mode->isNormal(), 'Not in normal mode');
|
||||
|
|
|
|||
|
|
@ -102,29 +102,11 @@ class ModeTest extends MockedTest
|
|||
self::assertFalse($mode->has(Mode::DBAVAILABLE));
|
||||
}
|
||||
|
||||
public function testWithoutDatabaseSetup()
|
||||
{
|
||||
$this->basePathMock->shouldReceive('getPath')->andReturn($this->root->url())->once();
|
||||
|
||||
$this->databaseMock->shouldReceive('connected')->andReturn(true)->once();
|
||||
$this->databaseMock->shouldReceive('fetchFirst')
|
||||
->with('SHOW TABLES LIKE \'config\'')->andReturn(false)->once();
|
||||
|
||||
$mode = (new Mode())->determine($this->basePathMock, $this->databaseMock, $this->configCacheMock);
|
||||
|
||||
self::assertFalse($mode->isNormal());
|
||||
self::assertTrue($mode->isInstall());
|
||||
|
||||
self::assertTrue($mode->has(Mode::LOCALCONFIGPRESENT));
|
||||
}
|
||||
|
||||
public function testWithMaintenanceMode()
|
||||
{
|
||||
$this->basePathMock->shouldReceive('getPath')->andReturn($this->root->url())->once();
|
||||
|
||||
$this->databaseMock->shouldReceive('connected')->andReturn(true)->once();
|
||||
$this->databaseMock->shouldReceive('fetchFirst')
|
||||
->with('SHOW TABLES LIKE \'config\'')->andReturn(true)->once();
|
||||
$this->configCacheMock->shouldReceive('get')->with('system', 'maintenance')
|
||||
->andReturn(true)->once();
|
||||
|
||||
|
|
@ -133,7 +115,6 @@ class ModeTest extends MockedTest
|
|||
self::assertFalse($mode->isNormal());
|
||||
self::assertFalse($mode->isInstall());
|
||||
|
||||
self::assertTrue($mode->has(Mode::DBCONFIGAVAILABLE));
|
||||
self::assertFalse($mode->has(Mode::MAINTENANCEDISABLED));
|
||||
}
|
||||
|
||||
|
|
@ -142,20 +123,14 @@ class ModeTest extends MockedTest
|
|||
$this->basePathMock->shouldReceive('getPath')->andReturn($this->root->url())->once();
|
||||
|
||||
$this->databaseMock->shouldReceive('connected')->andReturn(true)->once();
|
||||
$this->databaseMock->shouldReceive('fetchFirst')
|
||||
->with('SHOW TABLES LIKE \'config\'')->andReturn(true)->once();
|
||||
$this->configCacheMock->shouldReceive('get')->with('system', 'maintenance')
|
||||
->andReturn(false)->once();
|
||||
$this->databaseMock->shouldReceive('selectFirst')
|
||||
->with('config', ['v'], ['cat' => 'system', 'k' => 'maintenance'])
|
||||
->andReturn(['v' => null])->once();
|
||||
|
||||
$mode = (new Mode())->determine($this->basePathMock, $this->databaseMock, $this->configCacheMock);
|
||||
|
||||
self::assertTrue($mode->isNormal());
|
||||
self::assertFalse($mode->isInstall());
|
||||
|
||||
self::assertTrue($mode->has(Mode::DBCONFIGAVAILABLE));
|
||||
self::assertTrue($mode->has(Mode::MAINTENANCEDISABLED));
|
||||
}
|
||||
|
||||
|
|
@ -167,20 +142,14 @@ class ModeTest extends MockedTest
|
|||
$this->basePathMock->shouldReceive('getPath')->andReturn($this->root->url())->once();
|
||||
|
||||
$this->databaseMock->shouldReceive('connected')->andReturn(true)->once();
|
||||
$this->databaseMock->shouldReceive('fetchFirst')
|
||||
->with('SHOW TABLES LIKE \'config\'')->andReturn(true)->once();
|
||||
$this->configCacheMock->shouldReceive('get')->with('system', 'maintenance')
|
||||
->andReturn(false)->once();
|
||||
$this->databaseMock->shouldReceive('selectFirst')
|
||||
->with('config', ['v'], ['cat' => 'system', 'k' => 'maintenance'])
|
||||
->andReturn(['v' => '0'])->once();
|
||||
|
||||
$mode = (new Mode())->determine($this->basePathMock, $this->databaseMock, $this->configCacheMock);
|
||||
|
||||
self::assertTrue($mode->isNormal());
|
||||
self::assertFalse($mode->isInstall());
|
||||
|
||||
self::assertTrue($mode->has(Mode::DBCONFIGAVAILABLE));
|
||||
self::assertTrue($mode->has(Mode::MAINTENANCEDISABLED));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,11 +54,11 @@ class DatabaseCacheTest extends CacheTest
|
|||
$profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true);
|
||||
|
||||
// load real config to avoid mocking every config-entry which is related to the Database class
|
||||
$configFactory = new Config();
|
||||
$loader = (new Config())->createConfigFileLoader($this->root->url(), []);
|
||||
$configCache = $configFactory->createCache($loader);
|
||||
$configFactory = new Config();
|
||||
$configFileManager = (new Config())->createConfigFileManager($this->root->url(), []);
|
||||
$configCache = $configFactory->createCache($configFileManager);
|
||||
|
||||
$dbaDefinition = (new DbaDefinition($configCache->get('system', 'basepath')))->load();
|
||||
$dbaDefinition = (new DbaDefinition($configCache->get('system', 'basepath')))->load();
|
||||
$viewDefinition = (new ViewDefinition($configCache->get('system', 'basepath')))->load();
|
||||
|
||||
$dba = new StaticDatabase($configCache, $profiler, $dbaDefinition, $viewDefinition);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
namespace Friendica\Test\src\Core\Config\Cache;
|
||||
|
||||
use Friendica\Core\Config\Cache;
|
||||
use Friendica\Core\Config\ValueObject\Cache;
|
||||
use Friendica\Test\MockedTest;
|
||||
use ParagonIE\HiddenString\HiddenString;
|
||||
use stdClass;
|
||||
|
|
@ -49,7 +49,7 @@ class CacheTest extends MockedTest
|
|||
];
|
||||
}
|
||||
|
||||
private function assertConfigValues($data, \Friendica\Core\Config\ValueObject\Cache $configCache)
|
||||
private function assertConfigValues($data, Cache $configCache)
|
||||
{
|
||||
foreach ($data as $cat => $values) {
|
||||
foreach ($values as $key => $value) {
|
||||
|
|
@ -64,7 +64,7 @@ class CacheTest extends MockedTest
|
|||
*/
|
||||
public function testLoadConfigArray($data)
|
||||
{
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
|
||||
$configCache = new Cache();
|
||||
$configCache->load($data);
|
||||
|
||||
self::assertConfigValues($data, $configCache);
|
||||
|
|
@ -83,27 +83,27 @@ class CacheTest extends MockedTest
|
|||
]
|
||||
];
|
||||
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
|
||||
$configCache->load($data, \Friendica\Core\Config\ValueObject\Cache::SOURCE_DB);
|
||||
$configCache = new Cache();
|
||||
$configCache->load($data, Cache::SOURCE_DATA);
|
||||
// doesn't override - Low Priority due Config file
|
||||
$configCache->load($override, \Friendica\Core\Config\ValueObject\Cache::SOURCE_FILE);
|
||||
$configCache->load($override, Cache::SOURCE_FILE);
|
||||
|
||||
self::assertConfigValues($data, $configCache);
|
||||
|
||||
// override the value - High Prio due Server Env
|
||||
$configCache->load($override, \Friendica\Core\Config\ValueObject\Cache::SOURCE_ENV);
|
||||
$configCache->load($override, Cache::SOURCE_ENV);
|
||||
|
||||
self::assertEquals($override['system']['test'], $configCache->get('system', 'test'));
|
||||
self::assertEquals($override['system']['boolTrue'], $configCache->get('system', 'boolTrue'));
|
||||
|
||||
// Don't overwrite server ENV variables - even in load mode
|
||||
$configCache->load($data, \Friendica\Core\Config\ValueObject\Cache::SOURCE_DB);
|
||||
$configCache->load($data, Cache::SOURCE_DATA);
|
||||
|
||||
self::assertEquals($override['system']['test'], $configCache->get('system', 'test'));
|
||||
self::assertEquals($override['system']['boolTrue'], $configCache->get('system', 'boolTrue'));
|
||||
|
||||
// Overwrite ENV variables with ENV variables
|
||||
$configCache->load($data, \Friendica\Core\Config\ValueObject\Cache::SOURCE_ENV);
|
||||
$configCache->load($data, Cache::SOURCE_ENV);
|
||||
|
||||
self::assertConfigValues($data, $configCache);
|
||||
self::assertNotEquals($override['system']['test'], $configCache->get('system', 'test'));
|
||||
|
|
@ -111,11 +111,11 @@ class CacheTest extends MockedTest
|
|||
}
|
||||
|
||||
/**
|
||||
* Test the loadConfigArray() method with wrong/empty datasets
|
||||
* Test the loadConfigArray() method with only a category
|
||||
*/
|
||||
public function testLoadConfigArrayWrong()
|
||||
public function testLoadConfigArrayWithOnlyCategory()
|
||||
{
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
|
||||
$configCache = new Cache();
|
||||
|
||||
// empty dataset
|
||||
$configCache->load([]);
|
||||
|
|
@ -123,9 +123,10 @@ class CacheTest extends MockedTest
|
|||
|
||||
// wrong dataset
|
||||
$configCache->load(['system' => 'not_array']);
|
||||
self::assertEmpty($configCache->getAll());
|
||||
self::assertEquals(['system' => 'not_array'], $configCache->getAll());
|
||||
|
||||
// incomplete dataset (key is integer ID of the array)
|
||||
$configCache = new Cache();
|
||||
$configCache->load(['system' => ['value']]);
|
||||
self::assertEquals('value', $configCache->get('system', 0));
|
||||
}
|
||||
|
|
@ -136,7 +137,7 @@ class CacheTest extends MockedTest
|
|||
*/
|
||||
public function testGetAll($data)
|
||||
{
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
|
||||
$configCache = new Cache();
|
||||
$configCache->load($data);
|
||||
|
||||
$all = $configCache->getAll();
|
||||
|
|
@ -151,7 +152,7 @@ class CacheTest extends MockedTest
|
|||
*/
|
||||
public function testSetGet($data)
|
||||
{
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
|
||||
$configCache = new Cache();
|
||||
|
||||
foreach ($data as $cat => $values) {
|
||||
foreach ($values as $key => $value) {
|
||||
|
|
@ -167,7 +168,7 @@ class CacheTest extends MockedTest
|
|||
*/
|
||||
public function testGetEmpty()
|
||||
{
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
|
||||
$configCache = new Cache();
|
||||
|
||||
self::assertNull($configCache->get('something', 'value'));
|
||||
}
|
||||
|
|
@ -177,7 +178,7 @@ class CacheTest extends MockedTest
|
|||
*/
|
||||
public function testGetCat()
|
||||
{
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache([
|
||||
$configCache = new Cache([
|
||||
'system' => [
|
||||
'key1' => 'value1',
|
||||
'key2' => 'value2',
|
||||
|
|
@ -205,15 +206,18 @@ class CacheTest extends MockedTest
|
|||
*/
|
||||
public function testDelete($data)
|
||||
{
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache($data);
|
||||
$configCache = new Cache($data);
|
||||
|
||||
$assertion = [];
|
||||
|
||||
foreach ($data as $cat => $values) {
|
||||
$assertion[$cat] = null;
|
||||
foreach ($values as $key => $value) {
|
||||
$configCache->delete($cat, $key);
|
||||
}
|
||||
}
|
||||
|
||||
self::assertEmpty($configCache->getAll());
|
||||
self::assertEquals($assertion, $configCache->getAll());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -222,7 +226,7 @@ class CacheTest extends MockedTest
|
|||
*/
|
||||
public function testKeyDiffWithResult($data)
|
||||
{
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache($data);
|
||||
$configCache = new Cache($data);
|
||||
|
||||
$diffConfig = [
|
||||
'fakeCat' => [
|
||||
|
|
@ -239,7 +243,7 @@ class CacheTest extends MockedTest
|
|||
*/
|
||||
public function testKeyDiffWithoutResult($data)
|
||||
{
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache($data);
|
||||
$configCache = new Cache($data);
|
||||
|
||||
$diffConfig = $configCache->getAll();
|
||||
|
||||
|
|
@ -251,7 +255,7 @@ class CacheTest extends MockedTest
|
|||
*/
|
||||
public function testPasswordHide()
|
||||
{
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache([
|
||||
$configCache = new Cache([
|
||||
'database' => [
|
||||
'password' => 'supersecure',
|
||||
'username' => 'notsecured',
|
||||
|
|
@ -268,7 +272,7 @@ class CacheTest extends MockedTest
|
|||
*/
|
||||
public function testPasswordShow()
|
||||
{
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache([
|
||||
$configCache = new Cache([
|
||||
'database' => [
|
||||
'password' => 'supersecure',
|
||||
'username' => 'notsecured',
|
||||
|
|
@ -285,7 +289,7 @@ class CacheTest extends MockedTest
|
|||
*/
|
||||
public function testEmptyPassword()
|
||||
{
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache([
|
||||
$configCache = new Cache([
|
||||
'database' => [
|
||||
'password' => '',
|
||||
'username' => '',
|
||||
|
|
@ -299,7 +303,7 @@ class CacheTest extends MockedTest
|
|||
|
||||
public function testWrongTypePassword()
|
||||
{
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache([
|
||||
$configCache = new Cache([
|
||||
'database' => [
|
||||
'password' => new stdClass(),
|
||||
'username' => '',
|
||||
|
|
@ -309,7 +313,7 @@ class CacheTest extends MockedTest
|
|||
self::assertNotEmpty($configCache->get('database', 'password'));
|
||||
self::assertEmpty($configCache->get('database', 'username'));
|
||||
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache([
|
||||
$configCache = new Cache([
|
||||
'database' => [
|
||||
'password' => 23,
|
||||
'username' => '',
|
||||
|
|
@ -327,19 +331,190 @@ class CacheTest extends MockedTest
|
|||
public function testSetOverrides($data)
|
||||
{
|
||||
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
|
||||
$configCache->load($data, \Friendica\Core\Config\ValueObject\Cache::SOURCE_DB);
|
||||
$configCache = new Cache();
|
||||
$configCache->load($data, Cache::SOURCE_DATA);
|
||||
|
||||
// test with wrong override
|
||||
self::assertFalse($configCache->set('system', 'test', '1234567', \Friendica\Core\Config\ValueObject\Cache::SOURCE_FILE));
|
||||
self::assertFalse($configCache->set('system', 'test', '1234567', Cache::SOURCE_FILE));
|
||||
self::assertEquals($data['system']['test'], $configCache->get('system', 'test'));
|
||||
|
||||
// test with override (equal)
|
||||
self::assertTrue($configCache->set('system', 'test', '8910', \Friendica\Core\Config\ValueObject\Cache::SOURCE_DB));
|
||||
self::assertTrue($configCache->set('system', 'test', '8910', Cache::SOURCE_DATA));
|
||||
self::assertEquals('8910', $configCache->get('system', 'test'));
|
||||
|
||||
// test with override (over)
|
||||
self::assertTrue($configCache->set('system', 'test', '111213', \Friendica\Core\Config\ValueObject\Cache::SOURCE_ENV));
|
||||
self::assertTrue($configCache->set('system', 'test', '111213', Cache::SOURCE_ENV));
|
||||
self::assertEquals('111213', $configCache->get('system', 'test'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataTests
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSetData($data)
|
||||
{
|
||||
$configCache = new Cache();
|
||||
$configCache->load($data, Cache::SOURCE_FILE);
|
||||
|
||||
$configCache->set('system', 'test_2','with_data', Cache::SOURCE_DATA);
|
||||
|
||||
$this->assertEquals(['system' => ['test_2' => 'with_data']], $configCache->getDataBySource(Cache::SOURCE_DATA));
|
||||
$this->assertEquals($data, $configCache->getDataBySource(Cache::SOURCE_FILE));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataTests
|
||||
*/
|
||||
public function testMerge($data)
|
||||
{
|
||||
$configCache = new Cache();
|
||||
$configCache->load($data, Cache::SOURCE_FILE);
|
||||
|
||||
$configCache->set('system', 'test_2','with_data', Cache::SOURCE_DATA);
|
||||
$configCache->set('config', 'test_override','with_another_data', Cache::SOURCE_DATA);
|
||||
$configCache->set('old_category', 'test_45','given category', Cache::SOURCE_DATA);
|
||||
|
||||
$newCache = new Cache();
|
||||
$newCache->set('config', 'test_override','override it again', Cache::SOURCE_DATA);
|
||||
$newCache->set('system', 'test_3','new value', Cache::SOURCE_DATA);
|
||||
$newCache->set('new_category', 'test_23','added category', Cache::SOURCE_DATA);
|
||||
|
||||
$mergedCache = $configCache->merge($newCache);
|
||||
|
||||
self::assertEquals('with_data', $mergedCache->get('system', 'test_2'));
|
||||
self::assertEquals('override it again', $mergedCache->get('config', 'test_override'));
|
||||
self::assertEquals('new value', $mergedCache->get('system', 'test_3'));
|
||||
self::assertEquals('given category', $mergedCache->get('old_category', 'test_45'));
|
||||
self::assertEquals('added category', $mergedCache->get('new_category', 'test_23'));
|
||||
}
|
||||
|
||||
public function dataTestCat()
|
||||
{
|
||||
return [
|
||||
'test_with_hashmap' => [
|
||||
'data' => [
|
||||
'test_with_hashmap' => [
|
||||
'notifyall' => [
|
||||
'last_update' => 1671051565,
|
||||
'admin' => true,
|
||||
],
|
||||
'blockbot' => [
|
||||
'last_update' => 1658952852,
|
||||
'admin' => true,
|
||||
],
|
||||
],
|
||||
'config' => [
|
||||
'register_policy' => 2,
|
||||
'register_text' => '',
|
||||
'sitename' => 'Friendica Social Network23',
|
||||
'hostname' => 'friendica.local',
|
||||
'private_addons' => false,
|
||||
],
|
||||
'system' => [
|
||||
'dbclean_expire_conversation' => 90,
|
||||
],
|
||||
],
|
||||
'cat' => 'test_with_hashmap',
|
||||
'assertion' => [
|
||||
'notifyall' => [
|
||||
'last_update' => 1671051565,
|
||||
'admin' => true,
|
||||
],
|
||||
'blockbot' => [
|
||||
'last_update' => 1658952852,
|
||||
'admin' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
'test_with_keys' => [
|
||||
'data' => [
|
||||
'test_with_keys' => [
|
||||
[
|
||||
'last_update' => 1671051565,
|
||||
'admin' => true,
|
||||
],
|
||||
[
|
||||
'last_update' => 1658952852,
|
||||
'admin' => true,
|
||||
],
|
||||
],
|
||||
'config' => [
|
||||
'register_policy' => 2,
|
||||
'register_text' => '',
|
||||
'sitename' => 'Friendica Social Network23',
|
||||
'hostname' => 'friendica.local',
|
||||
'private_addons' => false,
|
||||
],
|
||||
'system' => [
|
||||
'dbclean_expire_conversation' => 90,
|
||||
],
|
||||
],
|
||||
'cat' => 'test_with_keys',
|
||||
'assertion' => [
|
||||
[
|
||||
'last_update' => 1671051565,
|
||||
'admin' => true,
|
||||
],
|
||||
[
|
||||
'last_update' => 1658952852,
|
||||
'admin' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
'test_with_inner_array' => [
|
||||
'data' => [
|
||||
'test_with_inner_array' => [
|
||||
'notifyall' => [
|
||||
'last_update' => 1671051565,
|
||||
'admin' => [
|
||||
'yes' => true,
|
||||
'no' => 1.5,
|
||||
],
|
||||
],
|
||||
'blogbot' => [
|
||||
'last_update' => 1658952852,
|
||||
'admin' => true,
|
||||
],
|
||||
],
|
||||
'config' => [
|
||||
'register_policy' => 2,
|
||||
'register_text' => '',
|
||||
'sitename' => 'Friendica Social Network23',
|
||||
'hostname' => 'friendica.local',
|
||||
'private_addons' => false,
|
||||
],
|
||||
'system' => [
|
||||
'dbclean_expire_conversation' => 90,
|
||||
],
|
||||
],
|
||||
'cat' => 'test_with_inner_array',
|
||||
'assertion' => [
|
||||
'notifyall' => [
|
||||
'last_update' => 1671051565,
|
||||
'admin' => [
|
||||
'yes' => true,
|
||||
'no' => 1.5,
|
||||
],
|
||||
],
|
||||
'blogbot' => [
|
||||
'last_update' => 1658952852,
|
||||
'admin' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the Cache can return a whole category at once
|
||||
*
|
||||
* @dataProvider dataTestCat
|
||||
*/
|
||||
public function testGetCategory(array $data, string $category, array $assertion)
|
||||
{
|
||||
$cache = new Cache($data);
|
||||
|
||||
self::assertEquals($assertion, $cache->get($category));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,14 +21,14 @@
|
|||
|
||||
namespace Friendica\Test\src\Core\Config\Cache;
|
||||
|
||||
use Friendica\Core\Config\Cache;
|
||||
use Friendica\Core\Config\Factory\Config;
|
||||
use Friendica\Core\Config\ValueObject\Cache;
|
||||
use Friendica\Test\MockedTest;
|
||||
use Friendica\Test\Util\VFSTrait;
|
||||
use Friendica\Core\Config\Util\ConfigFileLoader;
|
||||
use Friendica\Core\Config\Util\ConfigFileManager;
|
||||
use org\bovigo\vfs\vfsStream;
|
||||
|
||||
class ConfigFileLoaderTest extends MockedTest
|
||||
class ConfigFileManagerTest extends MockedTest
|
||||
{
|
||||
use VFSTrait;
|
||||
|
||||
|
|
@ -46,12 +46,13 @@ class ConfigFileLoaderTest extends MockedTest
|
|||
{
|
||||
$this->delConfigFile('local.config.php');
|
||||
|
||||
$configFileLoader = new ConfigFileLoader(
|
||||
$configFileLoader = new ConfigFileManager(
|
||||
$this->root->url(),
|
||||
$this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
|
||||
$this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
|
||||
);
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
|
||||
|
||||
$configCache = new Cache();
|
||||
|
||||
$configFileLoader->setupCache($configCache);
|
||||
|
||||
|
|
@ -69,15 +70,15 @@ class ConfigFileLoaderTest extends MockedTest
|
|||
$this->delConfigFile('local.config.php');
|
||||
|
||||
vfsStream::newFile('local.config.php')
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent('<?php return true;');
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent('<?php return true;');
|
||||
|
||||
$configFileLoader = new ConfigFileLoader(
|
||||
$configFileLoader = new ConfigFileManager(
|
||||
$this->root->url(),
|
||||
$this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
|
||||
$this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
|
||||
);
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
|
||||
$configCache = new Cache();
|
||||
|
||||
$configFileLoader->setupCache($configCache);
|
||||
}
|
||||
|
|
@ -90,23 +91,23 @@ class ConfigFileLoaderTest extends MockedTest
|
|||
$this->delConfigFile('local.config.php');
|
||||
|
||||
$file = dirname(__DIR__) . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'datasets' . DIRECTORY_SEPARATOR .
|
||||
'config' . DIRECTORY_SEPARATOR .
|
||||
'A.config.php';
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'datasets' . DIRECTORY_SEPARATOR .
|
||||
'config' . DIRECTORY_SEPARATOR .
|
||||
'A.config.php';
|
||||
|
||||
vfsStream::newFile('local.config.php')
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(file_get_contents($file));
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(file_get_contents($file));
|
||||
|
||||
$configFileLoader = new ConfigFileLoader(
|
||||
$configFileLoader = new ConfigFileManager(
|
||||
$this->root->url(),
|
||||
$this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
|
||||
$this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
|
||||
);
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
|
||||
$configCache = new Cache();
|
||||
|
||||
$configFileLoader->setupCache($configCache);
|
||||
|
||||
|
|
@ -127,23 +128,23 @@ class ConfigFileLoaderTest extends MockedTest
|
|||
$this->delConfigFile('local.config.php');
|
||||
|
||||
$file = dirname(__DIR__) . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'datasets' . DIRECTORY_SEPARATOR .
|
||||
'config' . DIRECTORY_SEPARATOR .
|
||||
'A.ini.php';
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'datasets' . DIRECTORY_SEPARATOR .
|
||||
'config' . DIRECTORY_SEPARATOR .
|
||||
'A.ini.php';
|
||||
|
||||
vfsStream::newFile('local.ini.php')
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(file_get_contents($file));
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(file_get_contents($file));
|
||||
|
||||
$configFileLoader = new ConfigFileLoader(
|
||||
$configFileLoader = new ConfigFileManager(
|
||||
$this->root->url(),
|
||||
$this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
|
||||
$this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
|
||||
);
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
|
||||
$configCache = new Cache();
|
||||
|
||||
$configFileLoader->setupCache($configCache);
|
||||
|
||||
|
|
@ -163,23 +164,23 @@ class ConfigFileLoaderTest extends MockedTest
|
|||
$this->delConfigFile('local.config.php');
|
||||
|
||||
$file = dirname(__DIR__) . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'datasets' . DIRECTORY_SEPARATOR .
|
||||
'config' . DIRECTORY_SEPARATOR .
|
||||
'.htconfig.php';
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'datasets' . DIRECTORY_SEPARATOR .
|
||||
'config' . DIRECTORY_SEPARATOR .
|
||||
'.htconfig.php';
|
||||
|
||||
vfsStream::newFile('.htconfig.php')
|
||||
->at($this->root)
|
||||
->setContent(file_get_contents($file));
|
||||
->at($this->root)
|
||||
->setContent(file_get_contents($file));
|
||||
|
||||
$configFileLoader = new ConfigFileLoader(
|
||||
$configFileLoader = new ConfigFileManager(
|
||||
$this->root->url(),
|
||||
$this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
|
||||
$this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
|
||||
);
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
|
||||
$configCache = new Cache();
|
||||
|
||||
$configFileLoader->setupCache($configCache);
|
||||
|
||||
|
|
@ -217,18 +218,18 @@ class ConfigFileLoaderTest extends MockedTest
|
|||
vfsStream::create($structure, $this->root);
|
||||
|
||||
$file = dirname(__DIR__) . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'datasets' . DIRECTORY_SEPARATOR .
|
||||
'config' . DIRECTORY_SEPARATOR .
|
||||
'A.config.php';
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'datasets' . DIRECTORY_SEPARATOR .
|
||||
'config' . DIRECTORY_SEPARATOR .
|
||||
'A.config.php';
|
||||
|
||||
vfsStream::newFile('test.config.php')
|
||||
->at($this->root->getChild('addon')->getChild('test')->getChild('config'))
|
||||
->setContent(file_get_contents($file));
|
||||
->at($this->root->getChild('addon')->getChild('test')->getChild('config'))
|
||||
->setContent(file_get_contents($file));
|
||||
|
||||
$configFileLoader = new ConfigFileLoader(
|
||||
$configFileLoader = new ConfigFileManager(
|
||||
$this->root->url(),
|
||||
$this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
|
||||
$this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
|
||||
|
|
@ -252,25 +253,25 @@ class ConfigFileLoaderTest extends MockedTest
|
|||
$this->delConfigFile('local.config.php');
|
||||
|
||||
$fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'datasets' . DIRECTORY_SEPARATOR .
|
||||
'config' . DIRECTORY_SEPARATOR;
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'datasets' . DIRECTORY_SEPARATOR .
|
||||
'config' . DIRECTORY_SEPARATOR;
|
||||
|
||||
vfsStream::newFile('A.config.php')
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(file_get_contents($fileDir . 'A.config.php'));
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(file_get_contents($fileDir . 'A.config.php'));
|
||||
vfsStream::newFile('B.config.php')
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(file_get_contents($fileDir . 'B.config.php'));
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(file_get_contents($fileDir . 'B.config.php'));
|
||||
|
||||
$configFileLoader = new ConfigFileLoader(
|
||||
$configFileLoader = new ConfigFileManager(
|
||||
$this->root->url(),
|
||||
$this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
|
||||
$this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
|
||||
);
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
|
||||
$configCache = new Cache();
|
||||
|
||||
$configFileLoader->setupCache($configCache);
|
||||
|
||||
|
|
@ -286,25 +287,25 @@ class ConfigFileLoaderTest extends MockedTest
|
|||
$this->delConfigFile('local.config.php');
|
||||
|
||||
$fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'datasets' . DIRECTORY_SEPARATOR .
|
||||
'config' . DIRECTORY_SEPARATOR;
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'datasets' . DIRECTORY_SEPARATOR .
|
||||
'config' . DIRECTORY_SEPARATOR;
|
||||
|
||||
vfsStream::newFile('A.ini.php')
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(file_get_contents($fileDir . 'A.ini.php'));
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(file_get_contents($fileDir . 'A.ini.php'));
|
||||
vfsStream::newFile('B.ini.php')
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(file_get_contents($fileDir . 'B.ini.php'));
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(file_get_contents($fileDir . 'B.ini.php'));
|
||||
|
||||
$configFileLoader = new ConfigFileLoader(
|
||||
$configFileLoader = new ConfigFileManager(
|
||||
$this->root->url(),
|
||||
$this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
|
||||
$this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
|
||||
);
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
|
||||
$configCache = new Cache();
|
||||
|
||||
$configFileLoader->setupCache($configCache);
|
||||
|
||||
|
|
@ -320,25 +321,26 @@ class ConfigFileLoaderTest extends MockedTest
|
|||
$this->delConfigFile('local.config.php');
|
||||
|
||||
$fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'datasets' . DIRECTORY_SEPARATOR .
|
||||
'config' . DIRECTORY_SEPARATOR;
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'datasets' . DIRECTORY_SEPARATOR .
|
||||
'config' . DIRECTORY_SEPARATOR;
|
||||
|
||||
vfsStream::newFile('A.ini.php')
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(file_get_contents($fileDir . 'A.ini.php'));
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(file_get_contents($fileDir . 'A.ini.php'));
|
||||
vfsStream::newFile('B-sample.ini.php')
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(file_get_contents($fileDir . 'B.ini.php'));
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(file_get_contents($fileDir . 'B.ini.php'));
|
||||
|
||||
$configFileLoader = new ConfigFileLoader(
|
||||
$configFileLoader = new ConfigFileManager(
|
||||
$this->root->url(),
|
||||
$this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
|
||||
$this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
|
||||
);
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
|
||||
|
||||
$configCache = new Cache();
|
||||
|
||||
$configFileLoader->setupCache($configCache);
|
||||
|
||||
|
|
@ -353,10 +355,10 @@ class ConfigFileLoaderTest extends MockedTest
|
|||
{
|
||||
$this->delConfigFile('local.config.php');
|
||||
|
||||
$configFileLoader = (new Config())->createConfigFileLoader($this->root->url(), ['FRIENDICA_CONFIG_DIR' => '/a/wrong/dir/']);
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
|
||||
$configFileManager = (new Config())->createConfigFileManager($this->root->url(), ['FRIENDICA_CONFIG_DIR' => '/a/wrong/dir/']);
|
||||
$configCache = new Cache();
|
||||
|
||||
$configFileLoader->setupCache($configCache);
|
||||
$configFileManager->setupCache($configCache);
|
||||
|
||||
self::assertEquals($this->root->url(), $configCache->get('system', 'basepath'));
|
||||
}
|
||||
|
|
@ -379,11 +381,134 @@ class ConfigFileLoaderTest extends MockedTest
|
|||
->at($this->root->getChild('config2'))
|
||||
->setContent(file_get_contents($fileDir . 'B.config.php'));
|
||||
|
||||
$configFileLoader = (new Config())->createConfigFileLoader($this->root->url(), ['FRIENDICA_CONFIG_DIR' => $this->root->getChild('config2')->url()]);
|
||||
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
|
||||
$configFileManager = (new Config())->createConfigFileManager($this->root->url(),
|
||||
[
|
||||
'FRIENDICA_CONFIG_DIR' => $this->root->getChild('config2')->url(),
|
||||
]);
|
||||
$configCache = new Cache();
|
||||
|
||||
$configFileLoader->setupCache($configCache);
|
||||
$configFileManager->setupCache($configCache);
|
||||
|
||||
self::assertEquals('newValue', $configCache->get('system', 'newKey'));
|
||||
}
|
||||
|
||||
public function testSaveData()
|
||||
{
|
||||
$this->delConfigFile('local.config.php');
|
||||
|
||||
$fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'datasets' . DIRECTORY_SEPARATOR .
|
||||
'config' . DIRECTORY_SEPARATOR;
|
||||
|
||||
vfsStream::newFile('B.config.php')
|
||||
->at($this->root->getChild('config2'))
|
||||
->setContent(file_get_contents($fileDir . 'B.config.php'));
|
||||
|
||||
$configFileManager = (new Config())->createConfigFileManager($this->root->url(),
|
||||
[
|
||||
'FRIENDICA_CONFIG_DIR' => $this->root->getChild('config2')->url(),
|
||||
]);
|
||||
$configCache = new Cache();
|
||||
|
||||
$configFileManager->setupCache($configCache);
|
||||
|
||||
$specialChars = '!"§$%&/()(/&%$\'><?$a,;:[]}{}\\?¿¿ß';
|
||||
|
||||
// overwrite some data and save it back to the config file
|
||||
$configCache->set('system', 'test', 'it', Cache::SOURCE_DATA);
|
||||
$configCache->set('config', 'test', 'it', Cache::SOURCE_DATA);
|
||||
$configCache->set('system', 'test_2', 2, Cache::SOURCE_DATA);
|
||||
$configCache->set('special_chars', 'special', $specialChars, Cache::SOURCE_DATA);
|
||||
$configFileManager->saveData($configCache);
|
||||
|
||||
// Reload the configCache with the new values
|
||||
$configCache2 = new Cache();
|
||||
$configFileManager->setupCache($configCache2);
|
||||
|
||||
self::assertEquals($configCache, $configCache2);
|
||||
self::assertEquals([
|
||||
'system' => [
|
||||
'test' => 'it',
|
||||
'test_2' => 2
|
||||
],
|
||||
'config' => [
|
||||
'test' => 'it',
|
||||
],
|
||||
'special_chars' => [
|
||||
'special' => $specialChars,
|
||||
]], $configCache2->getDataBySource(Cache::SOURCE_DATA));
|
||||
}
|
||||
|
||||
/**
|
||||
* If we delete something with the Cache::delete() functionality, be sure to override the underlying source as well
|
||||
*/
|
||||
public function testDeleteKeyOverwrite()
|
||||
{
|
||||
$this->delConfigFile('node.config.php');
|
||||
|
||||
$fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'datasets' . DIRECTORY_SEPARATOR .
|
||||
'config' . DIRECTORY_SEPARATOR;
|
||||
|
||||
vfsStream::newFile('B.config.php')
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(file_get_contents($fileDir . 'B.config.php'));
|
||||
|
||||
$configFileManager = (new Config())->createConfigFileManager($this->root->url());
|
||||
$configCache = new Cache();
|
||||
|
||||
$configFileManager->setupCache($configCache);
|
||||
|
||||
$configCache->delete('system', 'default_timezone', Cache::SOURCE_DATA);
|
||||
|
||||
$configFileManager->saveData($configCache);
|
||||
|
||||
// assert that system.default_timezone is now null, even it's set with settings.conf.php
|
||||
$configCache = new Cache();
|
||||
|
||||
$configFileManager->setupCache($configCache);
|
||||
|
||||
self::assertNull($configCache->get('system', 'default_timezone'));
|
||||
}
|
||||
|
||||
/**
|
||||
* If we delete something with the Cache::delete() functionality, be sure to override the underlying source as well
|
||||
*/
|
||||
public function testDeleteCategoryOverwrite()
|
||||
{
|
||||
$this->delConfigFile('node.config.php');
|
||||
|
||||
$fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'..' . DIRECTORY_SEPARATOR .
|
||||
'datasets' . DIRECTORY_SEPARATOR .
|
||||
'config' . DIRECTORY_SEPARATOR;
|
||||
|
||||
vfsStream::newFile('B.config.php')
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(file_get_contents($fileDir . 'B.config.php'));
|
||||
|
||||
$configFileManager = (new Config())->createConfigFileManager($this->root->url());
|
||||
$configCache = new Cache();
|
||||
|
||||
$configFileManager->setupCache($configCache);
|
||||
|
||||
$configCache->delete('system');
|
||||
|
||||
$configFileManager->saveData($configCache);
|
||||
|
||||
// assert that system.default_timezone is now null, even it's set with settings.conf.php
|
||||
$configCache = new Cache();
|
||||
|
||||
$configFileManager->setupCache($configCache);
|
||||
|
||||
self::assertNull($configCache->get('system', 'default_timezone'));
|
||||
}
|
||||
}
|
||||
|
|
@ -23,22 +23,25 @@ namespace Friendica\Test\src\Core\Config;
|
|||
|
||||
use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\Config\Repository\Config as ConfigModel;
|
||||
use Friendica\Core\Config\Model\Config;
|
||||
use Friendica\Core\Config\Util\ConfigFileManager;
|
||||
use Friendica\Core\Config\Util\ConfigFileTransformer;
|
||||
use Friendica\Core\Config\ValueObject\Cache;
|
||||
use Friendica\Test\MockedTest;
|
||||
use Mockery\MockInterface;
|
||||
use Mockery;
|
||||
use Friendica\Test\Util\VFSTrait;
|
||||
use org\bovigo\vfs\vfsStream;
|
||||
|
||||
abstract class ConfigTest extends MockedTest
|
||||
class ConfigTest extends MockedTest
|
||||
{
|
||||
use ArraySubsetAsserts;
|
||||
|
||||
/** @var ConfigModel|MockInterface */
|
||||
protected $configModel;
|
||||
use VFSTrait;
|
||||
|
||||
/** @var Cache */
|
||||
protected $configCache;
|
||||
|
||||
/** @var ConfigFileManager */
|
||||
protected $configFileManager;
|
||||
|
||||
/** @var IManageConfigValues */
|
||||
protected $testedConfig;
|
||||
|
||||
|
|
@ -60,17 +63,22 @@ abstract class ConfigTest extends MockedTest
|
|||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->setUpVfsDir();
|
||||
|
||||
parent::setUp();
|
||||
|
||||
// Create the config model
|
||||
$this->configModel = Mockery::mock(ConfigModel::class);
|
||||
$this->configCache = new Cache();
|
||||
$this->configFileManager = new ConfigFileManager($this->root->url(), $this->root->url() . '/config/', $this->root->url() . '/static/');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return IManageConfigValues
|
||||
*/
|
||||
abstract public function getInstance();
|
||||
public function getInstance()
|
||||
{
|
||||
$this->configFileManager->setupCache($this->configCache);
|
||||
return new Config($this->configFileManager, $this->configCache);
|
||||
}
|
||||
|
||||
public function dataTests()
|
||||
{
|
||||
|
|
@ -156,12 +164,13 @@ abstract class ConfigTest extends MockedTest
|
|||
|
||||
/**
|
||||
* Test the configuration initialization
|
||||
* @dataProvider dataConfigLoad
|
||||
*/
|
||||
public function testSetUp(array $data)
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')
|
||||
->andReturn(true)
|
||||
->once();
|
||||
vfsStream::newFile(ConfigFileManager::CONFIG_DATA_FILE)
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(ConfigFileTransformer::encode($data));
|
||||
|
||||
$this->testedConfig = $this->getInstance();
|
||||
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
|
||||
|
|
@ -171,19 +180,23 @@ abstract class ConfigTest extends MockedTest
|
|||
}
|
||||
|
||||
/**
|
||||
* Test the configuration load() method
|
||||
* Test the configuration reload() method
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $load
|
||||
*
|
||||
* @dataProvider dataConfigLoad
|
||||
*/
|
||||
public function testLoad(array $data, array $load)
|
||||
public function testReload(array $data, array $load)
|
||||
{
|
||||
vfsStream::newFile(ConfigFileManager::CONFIG_DATA_FILE)
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(ConfigFileTransformer::encode($data));
|
||||
|
||||
$this->testedConfig = $this->getInstance();
|
||||
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
|
||||
|
||||
foreach ($load as $loadedCats) {
|
||||
$this->testedConfig->load($loadedCats);
|
||||
}
|
||||
$this->testedConfig->reload();
|
||||
|
||||
// Assert at least loaded cats are loaded
|
||||
foreach ($load as $loadedCats) {
|
||||
|
|
@ -256,23 +269,31 @@ abstract class ConfigTest extends MockedTest
|
|||
|
||||
/**
|
||||
* Test the configuration load() method with overwrite
|
||||
*
|
||||
* @dataProvider dataDoubleLoad
|
||||
*/
|
||||
public function testCacheLoadDouble(array $data1, array $data2, array $expect = [])
|
||||
{
|
||||
vfsStream::newFile(ConfigFileManager::CONFIG_DATA_FILE)
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(ConfigFileTransformer::encode($data1));
|
||||
|
||||
$this->testedConfig = $this->getInstance();
|
||||
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
|
||||
|
||||
foreach ($data1 as $cat => $data) {
|
||||
$this->testedConfig->load($cat);
|
||||
}
|
||||
|
||||
// Assert at least loaded cats are loaded
|
||||
foreach ($data1 as $cat => $data) {
|
||||
self::assertConfig($cat, $data);
|
||||
}
|
||||
|
||||
vfsStream::newFile(ConfigFileManager::CONFIG_DATA_FILE)
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(ConfigFileTransformer::encode($data2));
|
||||
|
||||
$this->testedConfig->reload();
|
||||
|
||||
foreach ($data2 as $cat => $data) {
|
||||
$this->testedConfig->load($cat);
|
||||
self::assertConfig($cat, $data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -281,44 +302,19 @@ abstract class ConfigTest extends MockedTest
|
|||
*/
|
||||
public function testLoadWrong()
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')->andReturn(true)->once();
|
||||
$this->configModel->shouldReceive('load')->withAnyArgs()->andReturn([])->once();
|
||||
|
||||
$this->testedConfig = $this->getInstance();
|
||||
$this->testedConfig = new Config($this->configFileManager, new Cache());
|
||||
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
|
||||
|
||||
self::assertEmpty($this->testedConfig->getCache()->getAll());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the configuration get() and set() methods without adapter
|
||||
* Test the configuration get() and set() methods
|
||||
*
|
||||
* @dataProvider dataTests
|
||||
*/
|
||||
public function testSetGetWithoutDB($data)
|
||||
public function testSetGet($data)
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')
|
||||
->andReturn(false)
|
||||
->times(3);
|
||||
|
||||
$this->testedConfig = $this->getInstance();
|
||||
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
|
||||
|
||||
self::assertTrue($this->testedConfig->set('test', 'it', $data));
|
||||
|
||||
self::assertEquals($data, $this->testedConfig->get('test', 'it'));
|
||||
self::assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the configuration get() and set() methods with a model/db
|
||||
*
|
||||
* @dataProvider dataTests
|
||||
*/
|
||||
public function testSetGetWithDB($data)
|
||||
{
|
||||
$this->configModel->shouldReceive('set')->with('test', 'it', $data)->andReturn(true)->once();
|
||||
|
||||
$this->testedConfig = $this->getInstance();
|
||||
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
|
||||
|
||||
|
|
@ -349,41 +345,16 @@ abstract class ConfigTest extends MockedTest
|
|||
self::assertEquals('default', $this->testedConfig->get('test', 'it', 'default', true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the configuration get() method with refresh
|
||||
*
|
||||
* @dataProvider dataTests
|
||||
*/
|
||||
public function testGetWithRefresh($data)
|
||||
{
|
||||
$this->configCache->load(['test' => ['it' => 'now']], Cache::SOURCE_FILE);
|
||||
|
||||
$this->testedConfig = $this->getInstance();
|
||||
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
|
||||
|
||||
// without refresh
|
||||
self::assertEquals('now', $this->testedConfig->get('test', 'it'));
|
||||
self::assertEquals('now', $this->testedConfig->getCache()->get('test', 'it'));
|
||||
|
||||
// with refresh
|
||||
self::assertEquals($data, $this->testedConfig->get('test', 'it', null, true));
|
||||
self::assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
|
||||
|
||||
// without refresh and wrong value and default
|
||||
self::assertEquals('default', $this->testedConfig->get('test', 'not', 'default'));
|
||||
self::assertNull($this->testedConfig->getCache()->get('test', 'not'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the configuration delete() method without a model/db
|
||||
*
|
||||
* @dataProvider dataTests
|
||||
*/
|
||||
public function testDeleteWithoutDB($data)
|
||||
public function testDelete($data)
|
||||
{
|
||||
$this->configCache->load(['test' => ['it' => $data]], Cache::SOURCE_FILE);
|
||||
|
||||
$this->testedConfig = $this->getInstance();
|
||||
$this->testedConfig = new Config($this->configFileManager, $this->configCache);
|
||||
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
|
||||
|
||||
self::assertEquals($data, $this->testedConfig->get('test', 'it'));
|
||||
|
|
@ -393,52 +364,7 @@ abstract class ConfigTest extends MockedTest
|
|||
self::assertNull($this->testedConfig->get('test', 'it'));
|
||||
self::assertNull($this->testedConfig->getCache()->get('test', 'it'));
|
||||
|
||||
self::assertEmpty($this->testedConfig->getCache()->getAll());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the configuration delete() method with a model/db
|
||||
*/
|
||||
public function testDeleteWithDB()
|
||||
{
|
||||
$this->configCache->load(['test' => ['it' => 'now', 'quarter' => 'true']], Cache::SOURCE_FILE);
|
||||
|
||||
$this->configModel->shouldReceive('delete')
|
||||
->with('test', 'it')
|
||||
->andReturn(false)
|
||||
->once();
|
||||
$this->configModel->shouldReceive('delete')
|
||||
->with('test', 'second')
|
||||
->andReturn(true)
|
||||
->once();
|
||||
$this->configModel->shouldReceive('delete')
|
||||
->with('test', 'third')
|
||||
->andReturn(false)
|
||||
->once();
|
||||
$this->configModel->shouldReceive('delete')
|
||||
->with('test', 'quarter')
|
||||
->andReturn(true)
|
||||
->once();
|
||||
|
||||
$this->testedConfig = $this->getInstance();
|
||||
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
|
||||
|
||||
// directly set the value to the cache
|
||||
$this->testedConfig->getCache()->set('test', 'it', 'now');
|
||||
|
||||
self::assertEquals('now', $this->testedConfig->get('test', 'it'));
|
||||
self::assertEquals('now', $this->testedConfig->getCache()->get('test', 'it'));
|
||||
|
||||
// delete from cache only
|
||||
self::assertTrue($this->testedConfig->delete('test', 'it'));
|
||||
// delete from db only
|
||||
self::assertTrue($this->testedConfig->delete('test', 'second'));
|
||||
// no delete
|
||||
self::assertFalse($this->testedConfig->delete('test', 'third'));
|
||||
// delete both
|
||||
self::assertTrue($this->testedConfig->delete('test', 'quarter'));
|
||||
|
||||
self::assertEmpty($this->testedConfig->getCache()->getAll());
|
||||
self::assertEquals(['test' => null], $this->testedConfig->getCache()->getAll());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -462,6 +388,12 @@ abstract class ConfigTest extends MockedTest
|
|||
*/
|
||||
public function testSetGetLowPrio()
|
||||
{
|
||||
vfsStream::newFile(ConfigFileManager::CONFIG_DATA_FILE)
|
||||
->at($this->root->getChild('config'))
|
||||
->setContent(ConfigFileTransformer::encode([
|
||||
'config' => ['test' => 'it'],
|
||||
]));
|
||||
|
||||
$this->testedConfig = $this->getInstance();
|
||||
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
|
||||
self::assertEquals('it', $this->testedConfig->get('config', 'test'));
|
||||
|
|
@ -471,4 +403,133 @@ abstract class ConfigTest extends MockedTest
|
|||
self::assertFalse($this->testedConfig->set('config', 'test', '123'));
|
||||
self::assertEquals('prio', $this->testedConfig->get('config', 'test', '', true));
|
||||
}
|
||||
|
||||
|
||||
public function dataTestCat()
|
||||
{
|
||||
return [
|
||||
'test_with_hashmap' => [
|
||||
'data' => [
|
||||
'test_with_hashmap' => [
|
||||
'notifyall' => [
|
||||
'last_update' => 1671051565,
|
||||
'admin' => true,
|
||||
],
|
||||
'blockbot' => [
|
||||
'last_update' => 1658952852,
|
||||
'admin' => true,
|
||||
],
|
||||
],
|
||||
'config' => [
|
||||
'register_policy' => 2,
|
||||
'register_text' => '',
|
||||
'sitename' => 'Friendica Social Network23',
|
||||
'hostname' => 'friendica.local',
|
||||
'private_addons' => false,
|
||||
],
|
||||
'system' => [
|
||||
'dbclean_expire_conversation' => 90,
|
||||
],
|
||||
],
|
||||
'cat' => 'test_with_hashmap',
|
||||
'assertion' => [
|
||||
'notifyall' => [
|
||||
'last_update' => 1671051565,
|
||||
'admin' => true,
|
||||
],
|
||||
'blockbot' => [
|
||||
'last_update' => 1658952852,
|
||||
'admin' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
'test_with_keys' => [
|
||||
'data' => [
|
||||
'test_with_keys' => [
|
||||
[
|
||||
'last_update' => 1671051565,
|
||||
'admin' => true,
|
||||
],
|
||||
[
|
||||
'last_update' => 1658952852,
|
||||
'admin' => true,
|
||||
],
|
||||
],
|
||||
'config' => [
|
||||
'register_policy' => 2,
|
||||
'register_text' => '',
|
||||
'sitename' => 'Friendica Social Network23',
|
||||
'hostname' => 'friendica.local',
|
||||
'private_addons' => false,
|
||||
],
|
||||
'system' => [
|
||||
'dbclean_expire_conversation' => 90,
|
||||
],
|
||||
],
|
||||
'cat' => 'test_with_keys',
|
||||
'assertion' => [
|
||||
[
|
||||
'last_update' => 1671051565,
|
||||
'admin' => true,
|
||||
],
|
||||
[
|
||||
'last_update' => 1658952852,
|
||||
'admin' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
'test_with_inner_array' => [
|
||||
'data' => [
|
||||
'test_with_inner_array' => [
|
||||
'notifyall' => [
|
||||
'last_update' => 1671051565,
|
||||
'admin' => [
|
||||
'yes' => true,
|
||||
'no' => 1.5,
|
||||
],
|
||||
],
|
||||
'blogbot' => [
|
||||
'last_update' => 1658952852,
|
||||
'admin' => true,
|
||||
],
|
||||
],
|
||||
'config' => [
|
||||
'register_policy' => 2,
|
||||
'register_text' => '',
|
||||
'sitename' => 'Friendica Social Network23',
|
||||
'hostname' => 'friendica.local',
|
||||
'private_addons' => false,
|
||||
],
|
||||
'system' => [
|
||||
'dbclean_expire_conversation' => 90,
|
||||
],
|
||||
],
|
||||
'cat' => 'test_with_inner_array',
|
||||
'assertion' => [
|
||||
'notifyall' => [
|
||||
'last_update' => 1671051565,
|
||||
'admin' => [
|
||||
'yes' => true,
|
||||
'no' => 1.5,
|
||||
],
|
||||
],
|
||||
'blogbot' => [
|
||||
'last_update' => 1658952852,
|
||||
'admin' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataTestCat
|
||||
*/
|
||||
public function testGetCategory(array $data, string $category, array $assertion)
|
||||
{
|
||||
$this->configCache = new Cache($data);
|
||||
$config = new Config($this->configFileManager, $this->configCache);
|
||||
|
||||
self::assertEquals($assertion, $config->get($category));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
142
tests/src/Core/Config/ConfigTransactionTest.php
Normal file
142
tests/src/Core/Config/ConfigTransactionTest.php
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Test\src\Core\Config;
|
||||
|
||||
use Friendica\Core\Config\Capability\ISetConfigValuesTransactionally;
|
||||
use Friendica\Core\Config\Model\Config;
|
||||
use Friendica\Core\Config\Model\ConfigTransaction;
|
||||
use Friendica\Core\Config\Util\ConfigFileManager;
|
||||
use Friendica\Core\Config\ValueObject\Cache;
|
||||
use Friendica\Test\MockedTest;
|
||||
use Friendica\Test\Util\VFSTrait;
|
||||
use Mockery\Exception\InvalidCountException;
|
||||
|
||||
class ConfigTransactionTest extends MockedTest
|
||||
{
|
||||
use VFSTrait;
|
||||
|
||||
/** @var ConfigFileManager */
|
||||
protected $configFileManager;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->setUpVfsDir();
|
||||
|
||||
$this->configFileManager = new ConfigFileManager($this->root->url(), $this->root->url() . '/config/', $this->root->url() . '/static/');
|
||||
}
|
||||
|
||||
public function dataTests(): array
|
||||
{
|
||||
return [
|
||||
'default' => [
|
||||
'data' => include dirname(__FILE__, 4) . '/datasets/B.node.config.php',
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function testInstance()
|
||||
{
|
||||
$config = new Config($this->configFileManager, new Cache());
|
||||
$configTransaction = new ConfigTransaction($config);
|
||||
|
||||
self::assertInstanceOf(ISetConfigValuesTransactionally::class, $configTransaction);
|
||||
self::assertInstanceOf(ConfigTransaction::class, $configTransaction);
|
||||
}
|
||||
|
||||
public function testConfigTransaction()
|
||||
{
|
||||
$config = new Config($this->configFileManager, new Cache());
|
||||
$config->set('config', 'key1', 'value1');
|
||||
$config->set('system', 'key2', 'value2');
|
||||
$config->set('system', 'keyDel', 'valueDel');
|
||||
$config->set('delete', 'keyDel', 'catDel');
|
||||
|
||||
$configTransaction = new ConfigTransaction($config);
|
||||
// the config file knows it as well immediately
|
||||
$tempData = include $this->root->url() . '/config/' . ConfigFileManager::CONFIG_DATA_FILE;
|
||||
self::assertEquals('value1', $tempData['config']['key1'] ?? null);
|
||||
self::assertEquals('value2', $tempData['system']['key2'] ?? null);
|
||||
|
||||
// new key-value
|
||||
$configTransaction->set('transaction', 'key3', 'value3');
|
||||
// overwrite key-value
|
||||
$configTransaction->set('config', 'key1', 'changedValue1');
|
||||
// delete key-value
|
||||
$configTransaction->delete('system', 'keyDel');
|
||||
// delete last key of category - so the category is gone
|
||||
$configTransaction->delete('delete', 'keyDel');
|
||||
|
||||
// The main config still doesn't know about the change
|
||||
self::assertNull($config->get('transaction', 'key3'));
|
||||
self::assertEquals('value1', $config->get('config', 'key1'));
|
||||
self::assertEquals('valueDel', $config->get('system', 'keyDel'));
|
||||
self::assertEquals('catDel', $config->get('delete', 'keyDel'));
|
||||
// The config file still doesn't know it either
|
||||
$tempData = include $this->root->url() . '/config/' . ConfigFileManager::CONFIG_DATA_FILE;
|
||||
self::assertEquals('value1', $tempData['config']['key1'] ?? null);
|
||||
self::assertEquals('value2', $tempData['system']['key2'] ?? null);
|
||||
self::assertEquals('catDel', $tempData['delete']['keyDel'] ?? null);
|
||||
self::assertNull($tempData['transaction']['key3'] ?? null);
|
||||
|
||||
// save it back!
|
||||
$configTransaction->commit();
|
||||
|
||||
// Now every config and file knows the change
|
||||
self::assertEquals('changedValue1', $config->get('config', 'key1'));
|
||||
self::assertEquals('value3', $config->get('transaction', 'key3'));
|
||||
self::assertNull($config->get('system', 'keyDel'));
|
||||
self::assertNull($config->get('delete', 'keyDel'));
|
||||
$tempData = include $this->root->url() . '/config/' . ConfigFileManager::CONFIG_DATA_FILE;
|
||||
self::assertEquals('changedValue1', $tempData['config']['key1'] ?? null);
|
||||
self::assertEquals('value2', $tempData['system']['key2'] ?? null);
|
||||
self::assertEquals('value3', $tempData['transaction']['key3'] ?? null);
|
||||
self::assertNull($tempData['system']['keyDel'] ?? null);
|
||||
self::assertNull($tempData['delete']['keyDel'] ?? null);
|
||||
// the whole category should be gone
|
||||
self::assertNull($tempData['delete'] ?? null);
|
||||
}
|
||||
|
||||
/**
|
||||
* This test asserts that in empty transactions, no saveData is called, thus no config file writing was performed
|
||||
*/
|
||||
public function testNothingToDo()
|
||||
{
|
||||
$this->configFileManager = \Mockery::spy(ConfigFileManager::class);
|
||||
|
||||
$config = new Config($this->configFileManager, new Cache());
|
||||
$configTransaction = new ConfigTransaction($config);
|
||||
|
||||
// commit empty transaction
|
||||
$configTransaction->commit();
|
||||
|
||||
try {
|
||||
$this->configFileManager->shouldNotHaveReceived('saveData');
|
||||
} catch (InvalidCountException $exception) {
|
||||
self::fail($exception);
|
||||
}
|
||||
|
||||
// If not failed, the test ends successfully :)
|
||||
self::assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,255 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Test\src\Core\Config;
|
||||
|
||||
use Friendica\Core\Config\Type\JitConfig;
|
||||
|
||||
class JitConfigTest extends ConfigTest
|
||||
{
|
||||
public function getInstance()
|
||||
{
|
||||
return new JitConfig($this->configCache, $this->configModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataConfigLoad
|
||||
*/
|
||||
public function testSetUp(array $data)
|
||||
{
|
||||
$this->configModel->shouldReceive('load')
|
||||
->with('config')
|
||||
->andReturn(['config' => $data['config']])
|
||||
->once();
|
||||
|
||||
parent::testSetUp($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataConfigLoad
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $load
|
||||
*/
|
||||
public function testLoad(array $data, array $load)
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')
|
||||
->andReturn(true)
|
||||
->times(count($load) + 1);
|
||||
|
||||
$this->configModel->shouldReceive('load')
|
||||
->with('config')
|
||||
->andReturn(['config' => $data['config']])
|
||||
->once();
|
||||
|
||||
foreach ($load as $loadCat) {
|
||||
$this->configModel->shouldReceive('load')
|
||||
->with($loadCat)
|
||||
->andReturn([$loadCat => $data[$loadCat]])
|
||||
->once();
|
||||
}
|
||||
|
||||
parent::testLoad($data, $load);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataDoubleLoad
|
||||
*/
|
||||
public function testCacheLoadDouble(array $data1, array $data2, array $expect = [])
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')
|
||||
->andReturn(true)
|
||||
->times(count($data1) + count($data2) + 1);
|
||||
|
||||
$this->configModel->shouldReceive('load')
|
||||
->with('config')
|
||||
->andReturn(['config' => $data1['config']])
|
||||
->once();
|
||||
|
||||
foreach ($data1 as $cat => $data) {
|
||||
$this->configModel->shouldReceive('load')
|
||||
->with($cat)
|
||||
->andReturn([$cat => $data])
|
||||
->once();
|
||||
}
|
||||
|
||||
|
||||
foreach ($data2 as $cat => $data) {
|
||||
$this->configModel->shouldReceive('load')
|
||||
->with($cat)
|
||||
->andReturn([$cat => $data])
|
||||
->once();
|
||||
}
|
||||
|
||||
parent::testCacheLoadDouble($data1, $data2);
|
||||
|
||||
// Assert the expected categories
|
||||
foreach ($data2 as $cat => $data) {
|
||||
self::assertConfig($cat, $expect[$cat]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataTests
|
||||
*/
|
||||
public function testSetGetWithDB($data)
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')
|
||||
->andReturn(true)
|
||||
->times(3);
|
||||
|
||||
$this->configModel->shouldReceive('load')->with('config')->andReturn(['config' => []])->once();
|
||||
|
||||
parent::testSetGetWithDB($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataTests
|
||||
*/
|
||||
public function testGetWithRefresh($data)
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')
|
||||
->andReturn(true)
|
||||
->times(4);
|
||||
|
||||
// constructor loading
|
||||
$this->configModel->shouldReceive('load')
|
||||
->with('config')
|
||||
->andReturn(['config' => []])
|
||||
->once();
|
||||
|
||||
// mocking one get without result
|
||||
$this->configModel->shouldReceive('get')
|
||||
->with('test', 'it')
|
||||
->andReturn(null)
|
||||
->once();
|
||||
|
||||
// mocking the data get
|
||||
$this->configModel->shouldReceive('get')
|
||||
->with('test', 'it')
|
||||
->andReturn($data)
|
||||
->once();
|
||||
|
||||
// mocking second get
|
||||
$this->configModel->shouldReceive('get')
|
||||
->with('test', 'not')
|
||||
->andReturn(null)
|
||||
->once();
|
||||
|
||||
parent::testGetWithRefresh($data);
|
||||
}
|
||||
|
||||
public function testGetWrongWithoutDB()
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')
|
||||
->andReturn(false)
|
||||
->times(4);
|
||||
|
||||
parent::testGetWrongWithoutDB();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataTests
|
||||
*/
|
||||
public function testDeleteWithoutDB($data)
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')
|
||||
->andReturn(false)
|
||||
->times(4);
|
||||
|
||||
parent::testDeleteWithoutDB($data);
|
||||
}
|
||||
|
||||
public function testDeleteWithDB()
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')
|
||||
->andReturn(true)
|
||||
->times(6);
|
||||
|
||||
// constructor loading
|
||||
$this->configModel->shouldReceive('load')
|
||||
->with('config')
|
||||
->andReturn(['config' => []])
|
||||
->once();
|
||||
|
||||
// mocking one get without result
|
||||
$this->configModel->shouldReceive('get')
|
||||
->with('test', 'it')
|
||||
->andReturn(null)
|
||||
->once();
|
||||
|
||||
parent::testDeleteWithDB();
|
||||
}
|
||||
|
||||
public function testSetGetHighPrio()
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')
|
||||
->andReturn(true);
|
||||
|
||||
// constructor loading
|
||||
$this->configModel->shouldReceive('load')
|
||||
->with('config')
|
||||
->andReturn(['config' => []])
|
||||
->once();
|
||||
|
||||
$this->configModel->shouldReceive('get')
|
||||
->with('config', 'test')
|
||||
->andReturn('prio')
|
||||
->once();
|
||||
|
||||
$this->configModel->shouldReceive('set')
|
||||
->with('config', 'test', '123')
|
||||
->andReturn(true)
|
||||
->once();
|
||||
|
||||
$this->configModel->shouldReceive('get')
|
||||
->with('config', 'test')
|
||||
->andReturn('123')
|
||||
->once();
|
||||
|
||||
parent::testSetGetHighPrio();
|
||||
}
|
||||
|
||||
public function testSetGetLowPrio()
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')
|
||||
->andReturn(true);
|
||||
|
||||
// constructor loading
|
||||
$this->configModel->shouldReceive('load')
|
||||
->with('config')
|
||||
->andReturn(['config' => ['test' => 'it']])
|
||||
->once();
|
||||
|
||||
$this->configModel->shouldReceive('set')
|
||||
->with('config', 'test', '123')
|
||||
->andReturn(true)
|
||||
->once();
|
||||
|
||||
// mocking one get without result
|
||||
$this->configModel->shouldReceive('get')
|
||||
->with('config', 'test')
|
||||
->andReturn('it')
|
||||
->once();
|
||||
|
||||
parent::testSetGetLowPrio();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,213 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Test\src\Core\Config;
|
||||
|
||||
use Friendica\Core\Config\Type\PreloadConfig;
|
||||
|
||||
class PreloadConfigTest extends ConfigTest
|
||||
{
|
||||
public function getInstance()
|
||||
{
|
||||
return new PreloadConfig($this->configCache, $this->configModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataConfigLoad
|
||||
*/
|
||||
public function testSetUp(array $data)
|
||||
{
|
||||
$this->configModel->shouldReceive('load')
|
||||
->andReturn($data)
|
||||
->once();
|
||||
|
||||
parent::testSetUp($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataConfigLoad
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $load
|
||||
*/
|
||||
public function testLoad(array $data, array $load)
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')
|
||||
->andReturn(true)
|
||||
->once();
|
||||
|
||||
$this->configModel->shouldReceive('load')
|
||||
->andReturn($data)
|
||||
->once();
|
||||
|
||||
parent::testLoad($data, $load);
|
||||
|
||||
// Assert that every category is loaded everytime
|
||||
foreach ($data as $cat => $values) {
|
||||
self::assertConfig($cat, $values);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataDoubleLoad
|
||||
*
|
||||
* @param array $data1
|
||||
* @param array $data2
|
||||
*/
|
||||
public function testCacheLoadDouble(array $data1, array $data2, array $expect = [])
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')
|
||||
->andReturn(true)
|
||||
->once();
|
||||
|
||||
$this->configModel->shouldReceive('load')
|
||||
->andReturn($data1)
|
||||
->once();
|
||||
|
||||
parent::testCacheLoadDouble($data1, $data2);
|
||||
|
||||
// Assert that every category is loaded everytime and is NOT overwritten
|
||||
foreach ($data1 as $cat => $values) {
|
||||
self::assertConfig($cat, $values);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataTests
|
||||
*/
|
||||
public function testSetGetWithDB($data)
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')
|
||||
->andReturn(true)
|
||||
->times(2);
|
||||
|
||||
$this->configModel->shouldReceive('load')->andReturn(['config' => []])->once();
|
||||
|
||||
parent::testSetGetWithDB($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataTests
|
||||
*/
|
||||
public function testGetWithRefresh($data)
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')
|
||||
->andReturn(true)
|
||||
->times(2);
|
||||
|
||||
// constructor loading
|
||||
$this->configModel->shouldReceive('load')
|
||||
->andReturn(['config' => []])
|
||||
->once();
|
||||
|
||||
// mocking one get
|
||||
$this->configModel->shouldReceive('get')
|
||||
->with('test', 'it')
|
||||
->andReturn($data)
|
||||
->once();
|
||||
|
||||
parent::testGetWithRefresh($data);
|
||||
}
|
||||
|
||||
|
||||
public function testGetWrongWithoutDB()
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')
|
||||
->andReturn(false)
|
||||
->times(2);
|
||||
|
||||
parent::testGetWrongWithoutDB();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataTests
|
||||
*/
|
||||
public function testDeleteWithoutDB($data)
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')
|
||||
->andReturn(false)
|
||||
->times(2);
|
||||
|
||||
parent::testDeleteWithoutDB($data);
|
||||
}
|
||||
|
||||
public function testDeleteWithDB()
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')
|
||||
->andReturn(true)
|
||||
->times(5);
|
||||
|
||||
// constructor loading
|
||||
$this->configModel->shouldReceive('load')
|
||||
->andReturn(['config' => []])
|
||||
->once();
|
||||
|
||||
parent::testDeleteWithDB();
|
||||
}
|
||||
|
||||
|
||||
public function testSetGetHighPrio()
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')
|
||||
->andReturn(true);
|
||||
|
||||
// constructor loading
|
||||
$this->configModel->shouldReceive('load')
|
||||
->andReturn(['config' => []])
|
||||
->once();
|
||||
|
||||
$this->configModel->shouldReceive('set')
|
||||
->with('config', 'test', '123')
|
||||
->andReturn(true)
|
||||
->once();
|
||||
|
||||
$this->configModel->shouldReceive('get')
|
||||
->with('config', 'test')
|
||||
->andReturn('123')
|
||||
->once();
|
||||
|
||||
parent::testSetGetHighPrio();
|
||||
}
|
||||
|
||||
public function testSetGetLowPrio()
|
||||
{
|
||||
$this->configModel->shouldReceive('isConnected')
|
||||
->andReturn(true);
|
||||
|
||||
// constructor loading
|
||||
$this->configModel->shouldReceive('load')
|
||||
->andReturn(['config' => ['test' => 'it']])
|
||||
->once();
|
||||
|
||||
$this->configModel->shouldReceive('set')
|
||||
->with('config', 'test', '123')
|
||||
->andReturn(true)
|
||||
->once();
|
||||
|
||||
// mocking one get without result
|
||||
$this->configModel->shouldReceive('get')
|
||||
->with('config', 'test')
|
||||
->andReturn('it')
|
||||
->once();
|
||||
|
||||
parent::testSetGetLowPrio();
|
||||
}
|
||||
}
|
||||
57
tests/src/Core/Config/Util/ConfigFileTransformerTest.php
Normal file
57
tests/src/Core/Config/Util/ConfigFileTransformerTest.php
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Test\src\Core\Config\Util;
|
||||
|
||||
use Friendica\Core\Config\Util\ConfigFileTransformer;
|
||||
use Friendica\Test\MockedTest;
|
||||
|
||||
class ConfigFileTransformerTest extends MockedTest
|
||||
{
|
||||
public function dataTests()
|
||||
{
|
||||
return [
|
||||
'default' => [
|
||||
'configFile' => (dirname(__DIR__, 4) . '/datasets/config/A.node.config.php'),
|
||||
],
|
||||
'extended' => [
|
||||
'configFile' => (dirname(__DIR__, 4) . '/datasets/config/B.node.config.php'),
|
||||
],
|
||||
'friendica.local' => [
|
||||
'configFile' => (dirname(__DIR__, 4) . '/datasets/config/C.node.config.php'),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the given config will be decoded into an array and encoded into the same string again
|
||||
*
|
||||
* @dataProvider dataTests
|
||||
*/
|
||||
public function testConfigFile(string $configFile)
|
||||
{
|
||||
$dataArray = include $configFile;
|
||||
|
||||
$newConfig = ConfigFileTransformer::encode($dataArray);
|
||||
|
||||
self::assertEquals(file_get_contents($configFile), $newConfig);
|
||||
}
|
||||
}
|
||||
|
|
@ -24,7 +24,10 @@ namespace Friendica\Test\src\Core\Lock;
|
|||
use Dice\Dice;
|
||||
use Friendica\App;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\Config\Model\Config;
|
||||
use Friendica\Core\Config\Type\JitConfig;
|
||||
use Friendica\Core\Config\Util\ConfigFileManager;
|
||||
use Friendica\Core\Config\ValueObject\Cache;
|
||||
use Friendica\Core\Lock\Type\SemaphoreLock;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\DI;
|
||||
|
|
@ -42,11 +45,8 @@ class SemaphoreLockTest extends LockTest
|
|||
$app->shouldReceive('getHostname')->andReturn('friendica.local');
|
||||
$dice->shouldReceive('create')->with(App::class)->andReturn($app);
|
||||
|
||||
$configMock = Mockery::mock(JitConfig::class);
|
||||
$configMock
|
||||
->shouldReceive('get')
|
||||
->with('system', 'temppath')
|
||||
->andReturn('/tmp/');
|
||||
$configCache = new Cache(['system' => ['temppath' => '/tmp']]);
|
||||
$configMock = new Config(Mockery::mock(ConfigFileManager::class), $configCache);
|
||||
$dice->shouldReceive('create')->with(IManageConfigValues::class)->andReturn($configMock);
|
||||
|
||||
// @todo Because "get_temppath()" is using static methods, we have to initialize the BaseObject
|
||||
|
|
|
|||
|
|
@ -53,11 +53,11 @@ class DatabaseStorageTest extends StorageTest
|
|||
$profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true);
|
||||
|
||||
// load real config to avoid mocking every config-entry which is related to the Database class
|
||||
$configFactory = new Config();
|
||||
$loader = (new Config())->createConfigFileLoader($this->root->url(), []);
|
||||
$configCache = $configFactory->createCache($loader);
|
||||
$configFactory = new Config();
|
||||
$configFileManager = (new Config())->createConfigFileManager($this->root->url());
|
||||
$configCache = $configFactory->createCache($configFileManager);
|
||||
|
||||
$dbaDefinition = (new DbaDefinition($configCache->get('system', 'basepath')))->load();
|
||||
$dbaDefinition = (new DbaDefinition($configCache->get('system', 'basepath')))->load();
|
||||
$viewDefinition = (new ViewDefinition($configCache->get('system', 'basepath')))->load();
|
||||
|
||||
$dba = new StaticDatabase($configCache, $profiler, $dbaDefinition, $viewDefinition);
|
||||
|
|
|
|||
|
|
@ -22,9 +22,7 @@
|
|||
namespace Friendica\Test\src\Core\Storage\Repository;
|
||||
|
||||
use Dice\Dice;
|
||||
use Friendica\App\Mode;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\Config\Type\PreloadConfig;
|
||||
use Friendica\Core\Hook;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\Session\Capability\IHandleSessions;
|
||||
|
|
@ -41,7 +39,6 @@ use Friendica\Database\Definition\DbaDefinition;
|
|||
use Friendica\Database\Definition\ViewDefinition;
|
||||
use Friendica\DI;
|
||||
use Friendica\Core\Config\Factory\Config;
|
||||
use Friendica\Core\Config\Repository;
|
||||
use Friendica\Core\Storage\Type;
|
||||
use Friendica\Test\DatabaseTest;
|
||||
use Friendica\Test\Util\Database\StaticDatabase;
|
||||
|
|
@ -55,6 +52,7 @@ use Friendica\Test\Util\SampleStorageBackend;
|
|||
class StorageManagerTest extends DatabaseTest
|
||||
{
|
||||
use VFSTrait;
|
||||
|
||||
/** @var Database */
|
||||
private $dba;
|
||||
/** @var IManageConfigValues */
|
||||
|
|
@ -80,19 +78,19 @@ class StorageManagerTest extends DatabaseTest
|
|||
$profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true);
|
||||
|
||||
// load real config to avoid mocking every config-entry which is related to the Database class
|
||||
$configFactory = new Config();
|
||||
$loader = $configFactory->createConfigFileLoader($this->root->url(), []);
|
||||
$configCache = $configFactory->createCache($loader);
|
||||
$configFactory = new Config();
|
||||
$configFileManager = $configFactory->createConfigFileManager($this->root->url());
|
||||
$configCache = $configFactory->createCache($configFileManager);
|
||||
|
||||
$dbaDefinition = (new DbaDefinition($configCache->get('system', 'basepath')))->load();
|
||||
$dbaDefinition = (new DbaDefinition($configCache->get('system', 'basepath')))->load();
|
||||
$viewDefinition = (new ViewDefinition($configCache->get('system', 'basepath')))->load();
|
||||
|
||||
$this->dba = new StaticDatabase($configCache, $profiler, $dbaDefinition, $viewDefinition);
|
||||
|
||||
$configModel = new Repository\Config($this->dba, new Mode(Mode::DBCONFIGAVAILABLE));
|
||||
$this->config = new PreloadConfig($configCache, $configModel);
|
||||
$this->config = new \Friendica\Core\Config\Model\Config($configFileManager, $configCache);
|
||||
$this->config->set('storage', 'name', 'Database');
|
||||
$this->config->set('storage', 'filesystem_path', $this->root->getChild(Type\FilesystemConfig::DEFAULT_BASE_FOLDER)->url());
|
||||
$this->config->set('storage', 'filesystem_path', $this->root->getChild(Type\FilesystemConfig::DEFAULT_BASE_FOLDER)
|
||||
->url());
|
||||
|
||||
$this->l10n = \Mockery::mock(L10n::class);
|
||||
}
|
||||
|
|
@ -117,21 +115,21 @@ class StorageManagerTest extends DatabaseTest
|
|||
public function dataStorages()
|
||||
{
|
||||
return [
|
||||
'empty' => [
|
||||
'empty' => [
|
||||
'name' => '',
|
||||
'valid' => false,
|
||||
'interface' => ICanReadFromStorage::class,
|
||||
'assert' => null,
|
||||
'assertName' => '',
|
||||
],
|
||||
'database' => [
|
||||
'database' => [
|
||||
'name' => Type\Database::NAME,
|
||||
'valid' => true,
|
||||
'interface' => ICanWriteToStorage::class,
|
||||
'assert' => Type\Database::class,
|
||||
'assertName' => Type\Database::NAME,
|
||||
],
|
||||
'filesystem' => [
|
||||
'filesystem' => [
|
||||
'name' => Filesystem::NAME,
|
||||
'valid' => true,
|
||||
'interface' => ICanWriteToStorage::class,
|
||||
|
|
@ -145,7 +143,7 @@ class StorageManagerTest extends DatabaseTest
|
|||
'assert' => SystemResource::class,
|
||||
'assertName' => SystemResource::NAME,
|
||||
],
|
||||
'invalid' => [
|
||||
'invalid' => [
|
||||
'name' => 'invalid',
|
||||
'valid' => false,
|
||||
'interface' => null,
|
||||
|
|
|
|||
|
|
@ -52,10 +52,7 @@ class DBATest extends DatabaseTest
|
|||
*/
|
||||
public function testExists() {
|
||||
|
||||
self::assertTrue(DBA::exists('config', []));
|
||||
self::assertTrue(DBA::exists('user', []));
|
||||
self::assertFalse(DBA::exists('notable', []));
|
||||
|
||||
self::assertTrue(DBA::exists('config', ['k' => 'hostname']));
|
||||
self::assertFalse(DBA::exists('config', ['k' => 'nonsense']));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,30 +44,30 @@ class DBStructureTest extends DatabaseTest
|
|||
* @small
|
||||
*/
|
||||
public function testExists() {
|
||||
self::assertTrue(DBStructure::existsTable('config'));
|
||||
self::assertTrue(DBStructure::existsTable('user'));
|
||||
self::assertFalse(DBStructure::existsTable('notatable'));
|
||||
|
||||
self::assertTrue(DBStructure::existsColumn('config', ['k']));
|
||||
self::assertFalse(DBStructure::existsColumn('config', ['nonsense']));
|
||||
self::assertFalse(DBStructure::existsColumn('config', ['k', 'nonsense']));
|
||||
self::assertTrue(DBStructure::existsColumn('user', ['uid']));
|
||||
self::assertFalse(DBStructure::existsColumn('user', ['nonsense']));
|
||||
self::assertFalse(DBStructure::existsColumn('user', ['uid', 'nonsense']));
|
||||
}
|
||||
|
||||
/**
|
||||
* @small
|
||||
*/
|
||||
public function testRename() {
|
||||
$fromColumn = 'k';
|
||||
$toColumn = 'key';
|
||||
$fromType = 'varbinary(255) not null';
|
||||
$toType = 'varbinary(255) not null comment \'Test To Type\'';
|
||||
$fromColumn = 'email';
|
||||
$toColumn = 'email_key';
|
||||
$fromType = 'varchar(255) NOT NULL DEFAULT \'\' COMMENT \'the users email address\'';
|
||||
$toType = 'varchar(255) NOT NULL DEFAULT \'\' COMMENT \'Adapted column\'';
|
||||
|
||||
self::assertTrue(DBStructure::rename('config', [ $fromColumn => [ $toColumn, $toType ]]));
|
||||
self::assertTrue(DBStructure::existsColumn('config', [ $toColumn ]));
|
||||
self::assertFalse(DBStructure::existsColumn('config', [ $fromColumn ]));
|
||||
self::assertTrue(DBStructure::rename('user', [ $fromColumn => [ $toColumn, $toType ]]));
|
||||
self::assertTrue(DBStructure::existsColumn('user', [ $toColumn ]));
|
||||
self::assertFalse(DBStructure::existsColumn('user', [ $fromColumn ]));
|
||||
|
||||
self::assertTrue(DBStructure::rename('config', [ $toColumn => [ $fromColumn, $fromType ]]));
|
||||
self::assertTrue(DBStructure::existsColumn('config', [ $fromColumn ]));
|
||||
self::assertFalse(DBStructure::existsColumn('config', [ $toColumn ]));
|
||||
self::assertTrue(DBStructure::rename('user', [ $toColumn => [ $fromColumn, $fromType ]]));
|
||||
self::assertTrue(DBStructure::existsColumn('user', [ $fromColumn ]));
|
||||
self::assertFalse(DBStructure::existsColumn('user', [ $toColumn ]));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
76
tests/src/Model/GServerTest.php
Normal file
76
tests/src/Model/GServerTest.php
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Test\src\Model;
|
||||
|
||||
use Friendica\Model\GServer;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
class GServerTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function dataCleanUri(): array
|
||||
{
|
||||
return [
|
||||
'full-monty' => [
|
||||
'expected' => new Uri('https://example.com/path'),
|
||||
'dirtyUri' => new Uri('https://user:password@example.com/path?query=string#fragment'),
|
||||
],
|
||||
'index.php' => [
|
||||
'expected' => new Uri('https://example.com'),
|
||||
'dirtyUri' => new Uri('https://example.com/index.php'),
|
||||
],
|
||||
'index.php-2' => [
|
||||
'expected' => new Uri('https://example.com/path/to/resource'),
|
||||
'dirtyUri' => new Uri('https://example.com/index.php/path/to/resource'),
|
||||
],
|
||||
'index.php-path' => [
|
||||
'expected' => new Uri('https://example.com/path/to'),
|
||||
'dirtyUri' => new Uri('https://example.com/path/to/index.php'),
|
||||
],
|
||||
'index.php-path-2' => [
|
||||
'expected' => new Uri('https://example.com/path/to/path/to/resource'),
|
||||
'dirtyUri' => new Uri('https://example.com/path/to/index.php/path/to/resource'),
|
||||
],
|
||||
'index.php-slash' => [
|
||||
'expected' => new Uri('https://example.com'),
|
||||
'dirtyUri' => new Uri('https://example.com/index.php/'),
|
||||
],
|
||||
'index.php-slash-2' => [
|
||||
'expected' => new Uri('https://example.com/path/to/resource'),
|
||||
'dirtyUri' => new Uri('https://example.com/index.php/path/to/resource/'),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataCleanUri
|
||||
*
|
||||
* @param UriInterface $expected
|
||||
* @param UriInterface $dirtyUri
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testCleanUri(UriInterface $expected, UriInterface $dirtyUri)
|
||||
{
|
||||
$this->assertEquals($expected, GServer::cleanUri($dirtyUri));
|
||||
}
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@ use Friendica\App\Router;
|
|||
use Friendica\DI;
|
||||
use Friendica\Module\Api\GNUSocial\GNUSocial\Config;
|
||||
use Friendica\Test\src\Module\Api\ApiTest;
|
||||
use Friendica\Test\Util\VFSTrait;
|
||||
|
||||
class ConfigTest extends ApiTest
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,10 +23,25 @@ namespace Friendica\Test\src\Util;
|
|||
|
||||
use Friendica\App\BaseURL;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\Config\Capability\ISetConfigValuesTransactionally;
|
||||
use Friendica\Core\Config\Model\Config;
|
||||
use Friendica\Core\Config\Model\ConfigTransaction;
|
||||
use Friendica\Core\Config\Util\ConfigFileManager;
|
||||
use Friendica\Core\Config\ValueObject\Cache;
|
||||
use Friendica\Test\MockedTest;
|
||||
use Friendica\Test\Util\VFSTrait;
|
||||
|
||||
class BaseURLTest extends MockedTest
|
||||
{
|
||||
use VFSTrait;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->setUpVfsDir();
|
||||
}
|
||||
|
||||
public function dataDefault()
|
||||
{
|
||||
return [
|
||||
|
|
@ -231,6 +246,21 @@ class BaseURLTest extends MockedTest
|
|||
public function dataSave()
|
||||
{
|
||||
return [
|
||||
'no_change' => [
|
||||
'input' => [
|
||||
'hostname' => 'friendica.local',
|
||||
'urlPath' => 'path',
|
||||
'sslPolicy' => BaseURL::SSL_POLICY_FULL,
|
||||
'url' => 'https://friendica.local/path',
|
||||
'force_ssl' => true,
|
||||
],
|
||||
'save' => [
|
||||
'hostname' => 'friendica.local',
|
||||
'urlPath' => 'path',
|
||||
'sslPolicy' => BaseURL::SSL_POLICY_FULL,
|
||||
],
|
||||
'url' => 'https://friendica.local/path',
|
||||
],
|
||||
'default' => [
|
||||
'input' => [
|
||||
'hostname' => 'friendica.old',
|
||||
|
|
@ -315,28 +345,20 @@ class BaseURLTest extends MockedTest
|
|||
*/
|
||||
public function testSave($input, $save, $url)
|
||||
{
|
||||
$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']);
|
||||
$configMock->shouldReceive('get')->with('system', 'force_ssl')->andReturn($input['force_ssl']);
|
||||
$configFileManager = new ConfigFileManager($this->root->url(), $this->root->url() . '/config/', $this->root->url() . '/static/');
|
||||
$config = new Config($configFileManager, new Cache([
|
||||
'config' => [
|
||||
'hostname' => $input['hostname'] ?? null,
|
||||
],
|
||||
'system' => [
|
||||
'urlpath' => $input['urlPath'] ?? null,
|
||||
'ssl_policy' => $input['sslPolicy'] ?? null,
|
||||
'url' => $input['url'] ?? null,
|
||||
'force_ssl' => $input['force_ssl'] ?? null,
|
||||
],
|
||||
]));
|
||||
|
||||
$baseUrl = new BaseURL($configMock, []);
|
||||
|
||||
if (isset($save['hostname'])) {
|
||||
$configMock->shouldReceive('set')->with('config', 'hostname', $save['hostname'])->andReturn(true)->once();
|
||||
}
|
||||
|
||||
if (isset($save['urlPath'])) {
|
||||
$configMock->shouldReceive('set')->with('system', 'urlpath', $save['urlPath'])->andReturn(true)->once();
|
||||
}
|
||||
|
||||
if (isset($save['sslPolicy'])) {
|
||||
$configMock->shouldReceive('set')->with('system', 'ssl_policy', $save['sslPolicy'])->andReturn(true)->once();
|
||||
}
|
||||
|
||||
$configMock->shouldReceive('set')->with('system', 'url', $url)->andReturn(true)->once();
|
||||
$baseUrl = new BaseURL($config, []);
|
||||
|
||||
$baseUrl->save($save['hostname'], $save['sslPolicy'], $save['urlPath']);
|
||||
|
||||
|
|
@ -353,28 +375,20 @@ class BaseURLTest extends MockedTest
|
|||
*/
|
||||
public function testSaveByUrl($input, $save, $url)
|
||||
{
|
||||
$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']);
|
||||
$configMock->shouldReceive('get')->with('system', 'force_ssl')->andReturn($input['force_ssl']);
|
||||
$configFileManager = new ConfigFileManager($this->root->url(), $this->root->url() . '/config/', $this->root->url() . '/static/');
|
||||
$config = new Config($configFileManager, new Cache([
|
||||
'config' => [
|
||||
'hostname' => $input['hostname'] ?? null,
|
||||
],
|
||||
'system' => [
|
||||
'urlpath' => $input['urlPath'] ?? null,
|
||||
'ssl_policy' => $input['sslPolicy'] ?? null,
|
||||
'url' => $input['url'] ?? null,
|
||||
'force_ssl' => $input['force_ssl'] ?? null,
|
||||
],
|
||||
]));
|
||||
|
||||
$baseUrl = new BaseURL($configMock, []);
|
||||
|
||||
if (isset($save['hostname'])) {
|
||||
$configMock->shouldReceive('set')->with('config', 'hostname', $save['hostname'])->andReturn(true)->once();
|
||||
}
|
||||
|
||||
if (isset($save['urlPath'])) {
|
||||
$configMock->shouldReceive('set')->with('system', 'urlpath', $save['urlPath'])->andReturn(true)->once();
|
||||
}
|
||||
|
||||
if (isset($save['sslPolicy'])) {
|
||||
$configMock->shouldReceive('set')->with('system', 'ssl_policy', $save['sslPolicy'])->andReturn(true)->once();
|
||||
}
|
||||
|
||||
$configMock->shouldReceive('set')->with('system', 'url', $url)->andReturn(true)->once();
|
||||
$baseUrl = new BaseURL($config, []);
|
||||
|
||||
$baseUrl->saveByURL($url);
|
||||
|
||||
|
|
@ -498,65 +512,4 @@ class BaseURLTest extends MockedTest
|
|||
|
||||
self::assertEquals($redirect, $baseUrl->checkRedirectHttps());
|
||||
}
|
||||
|
||||
public function dataWrongSave()
|
||||
{
|
||||
return [
|
||||
'wrongHostname' => [
|
||||
'fail' => 'hostname',
|
||||
],
|
||||
'wrongSSLPolicy' => [
|
||||
'fail' => 'sslPolicy',
|
||||
],
|
||||
'wrongURLPath' => [
|
||||
'fail' => 'urlPath',
|
||||
],
|
||||
'wrongURL' => [
|
||||
'fail' => 'url',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the save() method with wrong parameters
|
||||
* @dataProvider dataWrongSave
|
||||
*/
|
||||
public function testWrongSave($fail)
|
||||
{
|
||||
$configMock = \Mockery::mock(IManageConfigValues::class);
|
||||
$configMock->shouldReceive('get')->with('config', 'hostname')->andReturn('friendica.local');
|
||||
$configMock->shouldReceive('get')->with('system', 'urlpath')->andReturn('new/test');
|
||||
$configMock->shouldReceive('get')->with('system', 'ssl_policy')->andReturn(BaseURL::DEFAULT_SSL_SCHEME);
|
||||
$configMock->shouldReceive('get')->with('system', 'url')->andReturn('http://friendica.local/new/test');
|
||||
|
||||
switch ($fail) {
|
||||
case 'hostname':
|
||||
$configMock->shouldReceive('set')->with('config', 'hostname', \Mockery::any())->andReturn(false)->once();
|
||||
break;
|
||||
case 'sslPolicy':
|
||||
$configMock->shouldReceive('set')->with('config', 'hostname', \Mockery::any())->andReturn(true)->twice();
|
||||
$configMock->shouldReceive('set')->with('system', 'ssl_policy', \Mockery::any())->andReturn(false)->once();
|
||||
break;
|
||||
case 'urlPath':
|
||||
$configMock->shouldReceive('set')->with('config', 'hostname', \Mockery::any())->andReturn(true)->twice();
|
||||
$configMock->shouldReceive('set')->with('system', 'ssl_policy', \Mockery::any())->andReturn(true)->twice();
|
||||
$configMock->shouldReceive('set')->with('system', 'urlpath', \Mockery::any())->andReturn(false)->once();
|
||||
break;
|
||||
case 'url':
|
||||
$configMock->shouldReceive('set')->with('config', 'hostname', \Mockery::any())->andReturn(true)->twice();
|
||||
$configMock->shouldReceive('set')->with('system', 'ssl_policy', \Mockery::any())->andReturn(true)->twice();
|
||||
$configMock->shouldReceive('set')->with('system', 'urlpath', \Mockery::any())->andReturn(true)->twice();
|
||||
$configMock->shouldReceive('set')->with('system', 'url', \Mockery::any())->andReturn(false)->once();
|
||||
break;
|
||||
}
|
||||
|
||||
$baseUrl = new BaseURL($configMock, []);
|
||||
self::assertFalse($baseUrl->save('test', 10, 'nope'));
|
||||
|
||||
// nothing should have changed because we never successfully saved anything
|
||||
self::assertEquals('friendica.local', $baseUrl->getHostname());
|
||||
self::assertEquals('new/test', $baseUrl->getUrlPath());
|
||||
self::assertEquals(BaseURL::DEFAULT_SSL_SCHEME, $baseUrl->getSSLPolicy());
|
||||
self::assertEquals('http://friendica.local/new/test', $baseUrl->get());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
37
update.php
37
update.php
|
|
@ -1148,6 +1148,10 @@ function update_1502()
|
|||
|
||||
function update_1505()
|
||||
{
|
||||
if (!DBStructure::existsTable('config')) {
|
||||
return Update::SUCCESS;
|
||||
}
|
||||
|
||||
$conditions = [
|
||||
"((`cat` = ?) AND ((`k` LIKE ?) OR (`k` = ?) OR (`k` LIKE ?) OR (`k` = ?))) OR " .
|
||||
"((`cat` != ?) AND (`k` LIKE ?)) OR " .
|
||||
|
|
@ -1175,3 +1179,36 @@ function update_1505()
|
|||
|
||||
return DBA::delete('config', $conditions) ? Update::SUCCESS : Update::FAILED;
|
||||
}
|
||||
|
||||
function update_1508()
|
||||
{
|
||||
$config = DBA::selectToArray('config');
|
||||
|
||||
$newConfig = DI::config()->beginTransaction();
|
||||
|
||||
foreach ($config as $entry) {
|
||||
$newConfig->set($entry['cat'], $entry['k'], $entry['v']);
|
||||
}
|
||||
|
||||
$newConfig->commit();
|
||||
|
||||
return Update::SUCCESS;
|
||||
}
|
||||
|
||||
function update_1509()
|
||||
{
|
||||
$addons = DBA::selectToArray('addon');
|
||||
|
||||
$newConfig = DI::config()->beginTransaction();
|
||||
|
||||
foreach ($addons as $addon) {
|
||||
$newConfig->set('addons', $addon['name'], [
|
||||
'last_update' => $addon['timestamp'],
|
||||
'admin' => (bool)$addon['plugin_admin'],
|
||||
]);
|
||||
}
|
||||
|
||||
$newConfig->commit();
|
||||
|
||||
return Update::SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: 2023.03-dev\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-01-04 10:58+0000\n"
|
||||
"POT-Creation-Date: 2023-01-07 14:32+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
|
@ -23,31 +23,9 @@ msgstr ""
|
|||
msgid "Unable to locate original post."
|
||||
msgstr ""
|
||||
|
||||
#: mod/item.php:139
|
||||
msgid "Post updated."
|
||||
msgstr ""
|
||||
|
||||
#: mod/item.php:213 mod/item.php:218
|
||||
msgid "Item wasn't stored."
|
||||
msgstr ""
|
||||
|
||||
#: mod/item.php:228
|
||||
msgid "Item couldn't be fetched."
|
||||
msgstr ""
|
||||
|
||||
#: mod/item.php:273 mod/item.php:278
|
||||
msgid "Empty post discarded."
|
||||
msgstr ""
|
||||
|
||||
#: mod/item.php:414 src/Module/Admin/Themes/Details.php:39
|
||||
#: src/Module/Admin/Themes/Index.php:59 src/Module/Debug/ItemBody.php:42
|
||||
#: src/Module/Debug/ItemBody.php:57 src/Module/Item/Feed.php:80
|
||||
msgid "Item not found."
|
||||
msgstr ""
|
||||
|
||||
#: mod/item.php:438 mod/message.php:69 mod/message.php:114 mod/notes.php:44
|
||||
#: mod/photos.php:158 mod/photos.php:675 src/Model/Event.php:522
|
||||
#: src/Module/Attach.php:55 src/Module/BaseApi.php:95
|
||||
#: mod/item.php:179 mod/item.php:184 mod/item.php:855 mod/message.php:69
|
||||
#: mod/message.php:114 mod/notes.php:44 mod/photos.php:158 mod/photos.php:675
|
||||
#: src/Model/Event.php:522 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
|
||||
|
|
@ -70,7 +48,7 @@ msgstr ""
|
|||
#: src/Module/Register.php:245 src/Module/Search/Directory.php:37
|
||||
#: src/Module/Settings/Account.php:50 src/Module/Settings/Account.php:407
|
||||
#: src/Module/Settings/Delegation.php:41 src/Module/Settings/Delegation.php:69
|
||||
#: src/Module/Settings/Display.php:69 src/Module/Settings/Display.php:153
|
||||
#: src/Module/Settings/Display.php:69 src/Module/Settings/Display.php:151
|
||||
#: src/Module/Settings/Profile/Photo/Crop.php:165
|
||||
#: src/Module/Settings/Profile/Photo/Index.php:111
|
||||
#: src/Module/Settings/RemoveMe.php:117 src/Module/Settings/UserExport.php:80
|
||||
|
|
@ -292,7 +270,7 @@ msgstr ""
|
|||
msgid "Insert web link"
|
||||
msgstr ""
|
||||
|
||||
#: mod/message.php:203 mod/message.php:360 mod/photos.php:1291
|
||||
#: mod/message.php:203 mod/message.php:360 mod/photos.php:1297
|
||||
#: src/Content/Conversation.php:371 src/Content/Conversation.php:717
|
||||
#: src/Module/Item/Compose.php:204 src/Module/Post/Edit.php:142
|
||||
#: src/Module/Profile/UnkMail.php:155 src/Object/Post.php:537
|
||||
|
|
@ -300,8 +278,8 @@ msgid "Please wait"
|
|||
msgstr ""
|
||||
|
||||
#: mod/message.php:204 mod/message.php:359 mod/photos.php:708
|
||||
#: mod/photos.php:825 mod/photos.php:1097 mod/photos.php:1138
|
||||
#: mod/photos.php:1194 mod/photos.php:1268
|
||||
#: mod/photos.php:825 mod/photos.php:1103 mod/photos.php:1144
|
||||
#: mod/photos.php:1200 mod/photos.php:1274
|
||||
#: src/Module/Calendar/Event/Form.php:250 src/Module/Contact/Advanced.php:132
|
||||
#: src/Module/Contact/Profile.php:327
|
||||
#: src/Module/Debug/ActivityPubConversion.php:140
|
||||
|
|
@ -476,7 +454,7 @@ msgstr ""
|
|||
msgid "Do not show a status post for this upload"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:739 mod/photos.php:1093 src/Content/Conversation.php:373
|
||||
#: mod/photos.php:739 mod/photos.php:1099 src/Content/Conversation.php:373
|
||||
#: src/Module/Calendar/Event/Form.php:253 src/Module/Post/Edit.php:179
|
||||
msgid "Permissions"
|
||||
msgstr ""
|
||||
|
|
@ -531,98 +509,98 @@ msgstr ""
|
|||
msgid "Do you really want to delete this photo?"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:904 mod/photos.php:1098
|
||||
#: mod/photos.php:904 mod/photos.php:1104
|
||||
msgid "Delete Photo"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:996
|
||||
#: mod/photos.php:1002
|
||||
msgid "View photo"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:998
|
||||
#: mod/photos.php:1004
|
||||
msgid "Edit photo"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:999
|
||||
#: mod/photos.php:1005
|
||||
msgid "Delete photo"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1000
|
||||
#: mod/photos.php:1006
|
||||
msgid "Use as profile photo"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1007
|
||||
#: mod/photos.php:1013
|
||||
msgid "Private Photo"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1013
|
||||
#: mod/photos.php:1019
|
||||
msgid "View Full Size"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1066
|
||||
#: mod/photos.php:1072
|
||||
msgid "Tags: "
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1069
|
||||
#: mod/photos.php:1075
|
||||
msgid "[Select tags to remove]"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1084
|
||||
#: mod/photos.php:1090
|
||||
msgid "New album name"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1085
|
||||
#: mod/photos.php:1091
|
||||
msgid "Caption"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1086
|
||||
#: mod/photos.php:1092
|
||||
msgid "Add a Tag"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1086
|
||||
#: mod/photos.php:1092
|
||||
msgid "Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1087
|
||||
#: mod/photos.php:1093
|
||||
msgid "Do not rotate"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1088
|
||||
#: mod/photos.php:1094
|
||||
msgid "Rotate CW (right)"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1089
|
||||
#: mod/photos.php:1095
|
||||
msgid "Rotate CCW (left)"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1135 mod/photos.php:1191 mod/photos.php:1265
|
||||
#: mod/photos.php:1141 mod/photos.php:1197 mod/photos.php:1271
|
||||
#: src/Module/Contact.php:557 src/Module/Item/Compose.php:188
|
||||
#: src/Object/Post.php:983
|
||||
msgid "This is you"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1137 mod/photos.php:1193 mod/photos.php:1267
|
||||
#: mod/photos.php:1143 mod/photos.php:1199 mod/photos.php:1273
|
||||
#: src/Object/Post.php:531 src/Object/Post.php:985
|
||||
msgid "Comment"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1139 mod/photos.php:1195 mod/photos.php:1269
|
||||
#: mod/photos.php:1145 mod/photos.php:1201 mod/photos.php:1275
|
||||
#: src/Content/Conversation.php:386 src/Module/Calendar/Event/Form.php:248
|
||||
#: src/Module/Item/Compose.php:199 src/Module/Post/Edit.php:162
|
||||
#: src/Object/Post.php:997
|
||||
msgid "Preview"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1140 src/Content/Conversation.php:341
|
||||
#: mod/photos.php:1146 src/Content/Conversation.php:341
|
||||
#: src/Module/Post/Edit.php:127 src/Object/Post.php:987
|
||||
msgid "Loading..."
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1226 src/Content/Conversation.php:633 src/Object/Post.php:255
|
||||
#: mod/photos.php:1232 src/Content/Conversation.php:633 src/Object/Post.php:255
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1227 src/Content/Conversation.php:634
|
||||
#: mod/photos.php:1233 src/Content/Conversation.php:634
|
||||
#: src/Module/Moderation/Users/Active.php:136
|
||||
#: src/Module/Moderation/Users/Blocked.php:136
|
||||
#: src/Module/Moderation/Users/Index.php:151
|
||||
|
|
@ -630,31 +608,31 @@ msgstr ""
|
|||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1288 src/Object/Post.php:378
|
||||
#: mod/photos.php:1294 src/Object/Post.php:378
|
||||
msgid "Like"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1289 src/Object/Post.php:378
|
||||
#: mod/photos.php:1295 src/Object/Post.php:378
|
||||
msgid "I like this (toggle)"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1290 src/Object/Post.php:379
|
||||
#: mod/photos.php:1296 src/Object/Post.php:379
|
||||
msgid "Dislike"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1292 src/Object/Post.php:379
|
||||
#: mod/photos.php:1298 src/Object/Post.php:379
|
||||
msgid "I don't like this (toggle)"
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:1314
|
||||
#: mod/photos.php:1320
|
||||
msgid "Map"
|
||||
msgstr ""
|
||||
|
||||
#: src/App.php:472
|
||||
#: src/App.php:471
|
||||
msgid "No system theme config value set."
|
||||
msgstr ""
|
||||
|
||||
#: src/App.php:594
|
||||
#: src/App.php:593
|
||||
msgid "Apologies but the website is unavailable at the moment."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -1540,35 +1518,35 @@ msgstr ""
|
|||
msgid "Follow Thread"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Item.php:419 src/Model/Contact.php:1205
|
||||
#: src/Content/Item.php:387 src/Model/Contact.php:1205
|
||||
msgid "View Status"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Item.php:420 src/Content/Item.php:438 src/Model/Contact.php:1149
|
||||
#: src/Content/Item.php:388 src/Content/Item.php:406 src/Model/Contact.php:1149
|
||||
#: src/Model/Contact.php:1197 src/Model/Contact.php:1206
|
||||
#: src/Module/Directory.php:157 src/Module/Settings/Profile/Index.php:234
|
||||
msgid "View Profile"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Item.php:421 src/Model/Contact.php:1207
|
||||
#: src/Content/Item.php:389 src/Model/Contact.php:1207
|
||||
msgid "View Photos"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Item.php:422 src/Model/Contact.php:1198
|
||||
#: src/Content/Item.php:390 src/Model/Contact.php:1198
|
||||
#: src/Model/Contact.php:1208
|
||||
msgid "Network Posts"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Item.php:423 src/Model/Contact.php:1199
|
||||
#: src/Content/Item.php:391 src/Model/Contact.php:1199
|
||||
#: src/Model/Contact.php:1209
|
||||
msgid "View Contact"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Item.php:424 src/Model/Contact.php:1210
|
||||
#: src/Content/Item.php:392 src/Model/Contact.php:1210
|
||||
msgid "Send PM"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Item.php:425 src/Module/Contact.php:409
|
||||
#: src/Content/Item.php:393 src/Module/Contact.php:409
|
||||
#: src/Module/Contact/Profile.php:348 src/Module/Contact/Profile.php:467
|
||||
#: src/Module/Moderation/Blocklist/Contact.php:116
|
||||
#: src/Module/Moderation/Users/Active.php:137
|
||||
|
|
@ -1576,7 +1554,7 @@ msgstr ""
|
|||
msgid "Block"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Item.php:426 src/Module/Contact.php:410
|
||||
#: src/Content/Item.php:394 src/Module/Contact.php:410
|
||||
#: src/Module/Contact/Profile.php:349 src/Module/Contact/Profile.php:475
|
||||
#: src/Module/Notifications/Introductions.php:134
|
||||
#: src/Module/Notifications/Introductions.php:206
|
||||
|
|
@ -1588,7 +1566,7 @@ msgstr ""
|
|||
msgid "Languages"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Item.php:435 src/Content/Widget.php:80
|
||||
#: src/Content/Item.php:403 src/Content/Widget.php:80
|
||||
#: src/Model/Contact.php:1200 src/Model/Contact.php:1211
|
||||
#: src/Module/Contact/Follow.php:166 view/theme/vier/theme.php:196
|
||||
msgid "Connect/Follow"
|
||||
|
|
@ -1671,7 +1649,7 @@ msgstr ""
|
|||
#: src/Content/Nav.php:197 src/Content/Nav.php:257
|
||||
#: src/Module/BaseProfile.php:85 src/Module/BaseProfile.php:88
|
||||
#: src/Module/BaseProfile.php:96 src/Module/BaseProfile.php:99
|
||||
#: src/Module/Settings/Display.php:255 view/theme/frio/theme.php:243
|
||||
#: src/Module/Settings/Display.php:252 view/theme/frio/theme.php:243
|
||||
#: view/theme/frio/theme.php:247
|
||||
msgid "Calendar"
|
||||
msgstr ""
|
||||
|
|
@ -1921,8 +1899,8 @@ msgid ""
|
|||
"<a href=\"%1$s\" target=\"_blank\" rel=\"noopener noreferrer\">%2$s</a> %3$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Text/BBCode.php:1257 src/Model/Item.php:3556
|
||||
#: src/Model/Item.php:3562 src/Model/Item.php:3563
|
||||
#: src/Content/Text/BBCode.php:1257 src/Model/Item.php:3588
|
||||
#: src/Model/Item.php:3594 src/Model/Item.php:3595
|
||||
msgid "Link to source"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -2548,158 +2526,158 @@ msgstr ""
|
|||
msgid "Could not connect to database."
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:403 src/Model/Event.php:432
|
||||
#: src/Module/Settings/Display.php:225
|
||||
#: src/Core/L10n.php:408 src/Model/Event.php:432
|
||||
#: src/Module/Settings/Display.php:222
|
||||
msgid "Monday"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:403 src/Model/Event.php:433
|
||||
#: src/Module/Settings/Display.php:226
|
||||
#: src/Core/L10n.php:408 src/Model/Event.php:433
|
||||
#: src/Module/Settings/Display.php:223
|
||||
msgid "Tuesday"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:403 src/Model/Event.php:434
|
||||
#: src/Module/Settings/Display.php:227
|
||||
#: src/Core/L10n.php:408 src/Model/Event.php:434
|
||||
#: src/Module/Settings/Display.php:224
|
||||
msgid "Wednesday"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:403 src/Model/Event.php:435
|
||||
#: src/Module/Settings/Display.php:228
|
||||
#: src/Core/L10n.php:408 src/Model/Event.php:435
|
||||
#: src/Module/Settings/Display.php:225
|
||||
msgid "Thursday"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:403 src/Model/Event.php:436
|
||||
#: src/Module/Settings/Display.php:229
|
||||
#: src/Core/L10n.php:408 src/Model/Event.php:436
|
||||
#: src/Module/Settings/Display.php:226
|
||||
msgid "Friday"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:403 src/Model/Event.php:437
|
||||
#: src/Module/Settings/Display.php:230
|
||||
#: src/Core/L10n.php:408 src/Model/Event.php:437
|
||||
#: src/Module/Settings/Display.php:227
|
||||
msgid "Saturday"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:403 src/Model/Event.php:431
|
||||
#: src/Module/Settings/Display.php:224
|
||||
#: src/Core/L10n.php:408 src/Model/Event.php:431
|
||||
#: src/Module/Settings/Display.php:221
|
||||
msgid "Sunday"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:407 src/Model/Event.php:452
|
||||
#: src/Core/L10n.php:412 src/Model/Event.php:452
|
||||
msgid "January"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:407 src/Model/Event.php:453
|
||||
#: src/Core/L10n.php:412 src/Model/Event.php:453
|
||||
msgid "February"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:407 src/Model/Event.php:454
|
||||
#: src/Core/L10n.php:412 src/Model/Event.php:454
|
||||
msgid "March"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:407 src/Model/Event.php:455
|
||||
#: src/Core/L10n.php:412 src/Model/Event.php:455
|
||||
msgid "April"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:407 src/Core/L10n.php:426 src/Model/Event.php:443
|
||||
#: src/Core/L10n.php:412 src/Core/L10n.php:431 src/Model/Event.php:443
|
||||
msgid "May"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:407 src/Model/Event.php:456
|
||||
#: src/Core/L10n.php:412 src/Model/Event.php:456
|
||||
msgid "June"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:407 src/Model/Event.php:457
|
||||
#: src/Core/L10n.php:412 src/Model/Event.php:457
|
||||
msgid "July"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:407 src/Model/Event.php:458
|
||||
#: src/Core/L10n.php:412 src/Model/Event.php:458
|
||||
msgid "August"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:407 src/Model/Event.php:459
|
||||
#: src/Core/L10n.php:412 src/Model/Event.php:459
|
||||
msgid "September"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:407 src/Model/Event.php:460
|
||||
#: src/Core/L10n.php:412 src/Model/Event.php:460
|
||||
msgid "October"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:407 src/Model/Event.php:461
|
||||
#: src/Core/L10n.php:412 src/Model/Event.php:461
|
||||
msgid "November"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:407 src/Model/Event.php:462
|
||||
#: src/Core/L10n.php:412 src/Model/Event.php:462
|
||||
msgid "December"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:422 src/Model/Event.php:424
|
||||
#: src/Core/L10n.php:427 src/Model/Event.php:424
|
||||
msgid "Mon"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:422 src/Model/Event.php:425
|
||||
#: src/Core/L10n.php:427 src/Model/Event.php:425
|
||||
msgid "Tue"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:422 src/Model/Event.php:426
|
||||
#: src/Core/L10n.php:427 src/Model/Event.php:426
|
||||
msgid "Wed"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:422 src/Model/Event.php:427
|
||||
#: src/Core/L10n.php:427 src/Model/Event.php:427
|
||||
msgid "Thu"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:422 src/Model/Event.php:428
|
||||
#: src/Core/L10n.php:427 src/Model/Event.php:428
|
||||
msgid "Fri"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:422 src/Model/Event.php:429
|
||||
#: src/Core/L10n.php:427 src/Model/Event.php:429
|
||||
msgid "Sat"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:422 src/Model/Event.php:423
|
||||
#: src/Core/L10n.php:427 src/Model/Event.php:423
|
||||
msgid "Sun"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:426 src/Model/Event.php:439
|
||||
#: src/Core/L10n.php:431 src/Model/Event.php:439
|
||||
msgid "Jan"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:426 src/Model/Event.php:440
|
||||
#: src/Core/L10n.php:431 src/Model/Event.php:440
|
||||
msgid "Feb"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:426 src/Model/Event.php:441
|
||||
#: src/Core/L10n.php:431 src/Model/Event.php:441
|
||||
msgid "Mar"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:426 src/Model/Event.php:442
|
||||
#: src/Core/L10n.php:431 src/Model/Event.php:442
|
||||
msgid "Apr"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:426 src/Model/Event.php:444
|
||||
#: src/Core/L10n.php:431 src/Model/Event.php:444
|
||||
msgid "Jun"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:426 src/Model/Event.php:445
|
||||
#: src/Core/L10n.php:431 src/Model/Event.php:445
|
||||
msgid "Jul"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:426 src/Model/Event.php:446
|
||||
#: src/Core/L10n.php:431 src/Model/Event.php:446
|
||||
msgid "Aug"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:426
|
||||
#: src/Core/L10n.php:431
|
||||
msgid "Sep"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:426 src/Model/Event.php:448
|
||||
#: src/Core/L10n.php:431 src/Model/Event.php:448
|
||||
msgid "Oct"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:426 src/Model/Event.php:449
|
||||
#: src/Core/L10n.php:431 src/Model/Event.php:449
|
||||
msgid "Nov"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/L10n.php:426 src/Model/Event.php:450
|
||||
#: src/Core/L10n.php:431 src/Model/Event.php:450
|
||||
msgid "Dec"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -2732,36 +2710,36 @@ msgstr ""
|
|||
msgid "Enter a valid existing folder"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/Update.php:70
|
||||
#: src/Core/Update.php:80
|
||||
#, php-format
|
||||
msgid ""
|
||||
"Updates from version %s are not supported. Please update at least to version "
|
||||
"2021.01 and wait until the postupdate finished version 1383."
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/Update.php:81
|
||||
#: src/Core/Update.php:91
|
||||
#, php-format
|
||||
msgid ""
|
||||
"Updates from postupdate version %s are not supported. Please update at least "
|
||||
"to version 2021.01 and wait until the postupdate finished version 1383."
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/Update.php:156
|
||||
#: src/Core/Update.php:186
|
||||
#, php-format
|
||||
msgid "%s: executing pre update %d"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/Update.php:194
|
||||
#: src/Core/Update.php:228
|
||||
#, php-format
|
||||
msgid "%s: executing post update %d"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/Update.php:264
|
||||
#: src/Core/Update.php:302
|
||||
#, php-format
|
||||
msgid "Update %s failed. See error logs."
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/Update.php:304
|
||||
#: src/Core/Update.php:342
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
|
|
@ -2773,16 +2751,16 @@ msgid ""
|
|||
"might be invalid."
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/Update.php:310
|
||||
#: src/Core/Update.php:348
|
||||
#, php-format
|
||||
msgid "The error message is\\n[pre]%s[/pre]"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/Update.php:314 src/Core/Update.php:342
|
||||
#: src/Core/Update.php:352 src/Core/Update.php:380
|
||||
msgid "[Friendica Notify] Database update"
|
||||
msgstr ""
|
||||
|
||||
#: src/Core/Update.php:336
|
||||
#: src/Core/Update.php:374
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
|
|
@ -2827,16 +2805,16 @@ msgstr ""
|
|||
msgid "Errors encountered performing database changes: "
|
||||
msgstr ""
|
||||
|
||||
#: src/Database/DBStructure.php:219
|
||||
#: src/Database/DBStructure.php:221
|
||||
msgid "Another database update is currently running."
|
||||
msgstr ""
|
||||
|
||||
#: src/Database/DBStructure.php:223
|
||||
#: src/Database/DBStructure.php:225
|
||||
#, php-format
|
||||
msgid "%s: Database update"
|
||||
msgstr ""
|
||||
|
||||
#: src/Database/DBStructure.php:480
|
||||
#: src/Database/DBStructure.php:482
|
||||
#, php-format
|
||||
msgid "%s: updating %s table."
|
||||
msgstr ""
|
||||
|
|
@ -2974,17 +2952,17 @@ msgid "today"
|
|||
msgstr ""
|
||||
|
||||
#: src/Model/Event.php:465 src/Module/Calendar/Show.php:129
|
||||
#: src/Module/Settings/Display.php:235 src/Util/Temporal.php:353
|
||||
#: src/Module/Settings/Display.php:232 src/Util/Temporal.php:353
|
||||
msgid "month"
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Event.php:466 src/Module/Calendar/Show.php:130
|
||||
#: src/Module/Settings/Display.php:236 src/Util/Temporal.php:354
|
||||
#: src/Module/Settings/Display.php:233 src/Util/Temporal.php:354
|
||||
msgid "week"
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Event.php:467 src/Module/Calendar/Show.php:131
|
||||
#: src/Module/Settings/Display.php:237 src/Util/Temporal.php:355
|
||||
#: src/Module/Settings/Display.php:234 src/Util/Temporal.php:355
|
||||
msgid "day"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -3113,44 +3091,44 @@ msgstr ""
|
|||
msgid "Content warning: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Item.php:3468
|
||||
#: src/Model/Item.php:3500
|
||||
msgid "bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Item.php:3499
|
||||
#: src/Model/Item.php:3531
|
||||
#, php-format
|
||||
msgid "%2$s (%3$d%%, %1$d vote)"
|
||||
msgid_plural "%2$s (%3$d%%, %1$d votes)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: src/Model/Item.php:3501
|
||||
#: src/Model/Item.php:3533
|
||||
#, php-format
|
||||
msgid "%2$s (%1$d vote)"
|
||||
msgid_plural "%2$s (%1$d votes)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: src/Model/Item.php:3506
|
||||
#: src/Model/Item.php:3538
|
||||
#, php-format
|
||||
msgid "%d voter. Poll end: %s"
|
||||
msgid_plural "%d voters. Poll end: %s"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: src/Model/Item.php:3508
|
||||
#: src/Model/Item.php:3540
|
||||
#, php-format
|
||||
msgid "%d voter."
|
||||
msgid_plural "%d voters."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: src/Model/Item.php:3510
|
||||
#: src/Model/Item.php:3542
|
||||
#, php-format
|
||||
msgid "Poll end: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Item.php:3544 src/Model/Item.php:3545
|
||||
#: src/Model/Item.php:3576 src/Model/Item.php:3577
|
||||
msgid "View on separate page"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -3266,7 +3244,7 @@ msgstr ""
|
|||
msgid "Title/Description:"
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Profile.php:1023 src/Module/Admin/Summary.php:217
|
||||
#: src/Model/Profile.php:1023 src/Module/Admin/Summary.php:222
|
||||
#: src/Module/Moderation/Summary.php:77
|
||||
msgid "Summary"
|
||||
msgstr ""
|
||||
|
|
@ -3593,8 +3571,8 @@ msgstr ""
|
|||
#: src/Module/Admin/Addons/Details.php:111 src/Module/Admin/Addons/Index.php:67
|
||||
#: 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:433 src/Module/Admin/Storage.php:138
|
||||
#: src/Module/Admin/Summary.php:216 src/Module/Admin/Themes/Details.php:90
|
||||
#: 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/Themes/Index.php:111 src/Module/Admin/Tos.php:77
|
||||
#: src/Module/Moderation/Users/Create.php:61
|
||||
#: src/Module/Moderation/Users/Pending.php:96
|
||||
|
|
@ -3631,12 +3609,12 @@ msgid "Addon %s failed to install."
|
|||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Addons/Index.php:69 src/Module/Admin/Features.php:87
|
||||
#: src/Module/Admin/Logs/Settings.php:81 src/Module/Admin/Site.php:436
|
||||
#: src/Module/Admin/Logs/Settings.php:81 src/Module/Admin/Site.php:438
|
||||
#: src/Module/Admin/Themes/Index.php:113 src/Module/Admin/Tos.php:86
|
||||
#: src/Module/Settings/Account.php:560 src/Module/Settings/Addons.php:81
|
||||
#: src/Module/Settings/Connectors.php:159
|
||||
#: src/Module/Settings/Connectors.php:244
|
||||
#: src/Module/Settings/Delegation.php:169 src/Module/Settings/Display.php:250
|
||||
#: src/Module/Settings/Delegation.php:169 src/Module/Settings/Display.php:247
|
||||
#: src/Module/Settings/Features.php:76
|
||||
msgid "Save Settings"
|
||||
msgstr ""
|
||||
|
|
@ -3988,284 +3966,284 @@ msgstr ""
|
|||
msgid "%s is no valid input for maximum image size"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:342 src/Module/Settings/Display.php:171
|
||||
#: src/Module/Admin/Site.php:344 src/Module/Settings/Display.php:169
|
||||
msgid "No special theme for mobile devices"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:359 src/Module/Settings/Display.php:181
|
||||
#: src/Module/Admin/Site.php:361 src/Module/Settings/Display.php:179
|
||||
#, php-format
|
||||
msgid "%s - (Experimental)"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:371
|
||||
#: src/Module/Admin/Site.php:373
|
||||
msgid "No community page"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:372
|
||||
#: src/Module/Admin/Site.php:374
|
||||
msgid "No community page for visitors"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:373
|
||||
#: src/Module/Admin/Site.php:375
|
||||
msgid "Public postings from users of this site"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:374
|
||||
#: src/Module/Admin/Site.php:376
|
||||
msgid "Public postings from the federated network"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:375
|
||||
#: src/Module/Admin/Site.php:377
|
||||
msgid "Public postings from local users and the federated network"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:381
|
||||
#: src/Module/Admin/Site.php:383
|
||||
msgid "Multi user instance"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:404
|
||||
#: src/Module/Admin/Site.php:406
|
||||
msgid "Closed"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:405
|
||||
#: src/Module/Admin/Site.php:407
|
||||
msgid "Requires approval"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:406
|
||||
#: src/Module/Admin/Site.php:408
|
||||
msgid "Open"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:410 src/Module/Install.php:222
|
||||
#: src/Module/Admin/Site.php:412 src/Module/Install.php:222
|
||||
msgid "No SSL policy, links will track page SSL state"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:411 src/Module/Install.php:223
|
||||
#: src/Module/Admin/Site.php:413 src/Module/Install.php:223
|
||||
msgid "Force all links to use SSL"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:412 src/Module/Install.php:224
|
||||
#: src/Module/Admin/Site.php:414 src/Module/Install.php:224
|
||||
msgid "Self-signed certificate, use SSL for local links only (discouraged)"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:416
|
||||
#: src/Module/Admin/Site.php:418
|
||||
msgid "Don't check"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:417
|
||||
#: src/Module/Admin/Site.php:419
|
||||
msgid "check the stable version"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:418
|
||||
#: src/Module/Admin/Site.php:420
|
||||
msgid "check the development version"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:422
|
||||
#: src/Module/Admin/Site.php:424
|
||||
msgid "none"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:423
|
||||
#: src/Module/Admin/Site.php:425
|
||||
msgid "Local contacts"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:424
|
||||
#: src/Module/Admin/Site.php:426
|
||||
msgid "Interactors"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:434 src/Module/BaseAdmin.php:90
|
||||
#: src/Module/Admin/Site.php:436 src/Module/BaseAdmin.php:90
|
||||
msgid "Site"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:435
|
||||
#: src/Module/Admin/Site.php:437
|
||||
msgid "General Information"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:437
|
||||
#: src/Module/Admin/Site.php:439
|
||||
msgid "Republish users to directory"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:438 src/Module/Register.php:152
|
||||
#: src/Module/Admin/Site.php:440 src/Module/Register.php:152
|
||||
msgid "Registration"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:439
|
||||
#: src/Module/Admin/Site.php:441
|
||||
msgid "File upload"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:440
|
||||
#: src/Module/Admin/Site.php:442
|
||||
msgid "Policies"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:441 src/Module/Calendar/Event/Form.php:252
|
||||
#: src/Module/Admin/Site.php:443 src/Module/Calendar/Event/Form.php:252
|
||||
#: src/Module/Contact.php:485 src/Module/Profile/Profile.php:276
|
||||
msgid "Advanced"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:442
|
||||
#: src/Module/Admin/Site.php:444
|
||||
msgid "Auto Discovered Contact Directory"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:443
|
||||
#: src/Module/Admin/Site.php:445
|
||||
msgid "Performance"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:444
|
||||
#: src/Module/Admin/Site.php:446
|
||||
msgid "Worker"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:445
|
||||
#: src/Module/Admin/Site.php:447
|
||||
msgid "Message Relay"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:446
|
||||
#: src/Module/Admin/Site.php:448
|
||||
msgid ""
|
||||
"Use the command \"console relay\" in the command line to add or remove "
|
||||
"relays."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:447
|
||||
#: src/Module/Admin/Site.php:449
|
||||
msgid "The system is not subscribed to any relays at the moment."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:448
|
||||
#: src/Module/Admin/Site.php:450
|
||||
msgid "The system is currently subscribed to the following relays:"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:450
|
||||
#: src/Module/Admin/Site.php:452
|
||||
msgid "Relocate Node"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:451
|
||||
#: src/Module/Admin/Site.php:453
|
||||
msgid ""
|
||||
"Relocating your node enables you to change the DNS domain of this node and "
|
||||
"keep all the existing users and posts. This process takes a while and can "
|
||||
"only be started from the relocate console command like this:"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:452
|
||||
#: src/Module/Admin/Site.php:454
|
||||
msgid "(Friendica directory)# bin/console relocate https://newdomain.com"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:456
|
||||
#: src/Module/Admin/Site.php:458
|
||||
msgid "Site name"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:457
|
||||
#: src/Module/Admin/Site.php:459
|
||||
msgid "Sender Email"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:457
|
||||
#: src/Module/Admin/Site.php:459
|
||||
msgid ""
|
||||
"The email address your server shall use to send notification emails from."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:458
|
||||
#: src/Module/Admin/Site.php:460
|
||||
msgid "Name of the system actor"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:458
|
||||
#: src/Module/Admin/Site.php:460
|
||||
msgid ""
|
||||
"Name of the internal system account that is used to perform ActivityPub "
|
||||
"requests. This must be an unused username. If set, this can't be changed "
|
||||
"again."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:459
|
||||
#: src/Module/Admin/Site.php:461
|
||||
msgid "Banner/Logo"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:460
|
||||
#: src/Module/Admin/Site.php:462
|
||||
msgid "Email Banner/Logo"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:461
|
||||
#: src/Module/Admin/Site.php:463
|
||||
msgid "Shortcut icon"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:461
|
||||
#: src/Module/Admin/Site.php:463
|
||||
msgid "Link to an icon that will be used for browsers."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:462
|
||||
#: src/Module/Admin/Site.php:464
|
||||
msgid "Touch icon"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:462
|
||||
#: src/Module/Admin/Site.php:464
|
||||
msgid "Link to an icon that will be used for tablets and mobiles."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:463
|
||||
#: src/Module/Admin/Site.php:465
|
||||
msgid "Additional Info"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:463
|
||||
#: src/Module/Admin/Site.php:465
|
||||
#, php-format
|
||||
msgid ""
|
||||
"For public servers: you can add additional information here that will be "
|
||||
"listed at %s/servers."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:464
|
||||
#: src/Module/Admin/Site.php:466
|
||||
msgid "System language"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:465
|
||||
#: src/Module/Admin/Site.php:467
|
||||
msgid "System theme"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:465
|
||||
#: src/Module/Admin/Site.php:467
|
||||
#, php-format
|
||||
msgid ""
|
||||
"Default system theme - may be over-ridden by user profiles - <a href=\"%s\" "
|
||||
"id=\"cnftheme\">Change default theme settings</a>"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:466
|
||||
#: src/Module/Admin/Site.php:468
|
||||
msgid "Mobile system theme"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:466
|
||||
#: src/Module/Admin/Site.php:468
|
||||
msgid "Theme for mobile devices"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:467 src/Module/Install.php:232
|
||||
#: src/Module/Admin/Site.php:469 src/Module/Install.php:232
|
||||
msgid "SSL link policy"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:467 src/Module/Install.php:234
|
||||
#: src/Module/Admin/Site.php:469 src/Module/Install.php:234
|
||||
msgid "Determines whether generated links should be forced to use SSL"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:468
|
||||
#: src/Module/Admin/Site.php:470
|
||||
msgid "Force SSL"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:468
|
||||
#: src/Module/Admin/Site.php:470
|
||||
msgid ""
|
||||
"Force all Non-SSL requests to SSL - Attention: on some systems it could lead "
|
||||
"to endless loops."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:469
|
||||
#: src/Module/Admin/Site.php:471
|
||||
msgid "Show help entry from navigation menu"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:469
|
||||
#: src/Module/Admin/Site.php:471
|
||||
msgid ""
|
||||
"Displays the menu entry for the Help pages from the navigation menu. It is "
|
||||
"always accessible by calling /help directly."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:470
|
||||
#: src/Module/Admin/Site.php:472
|
||||
msgid "Single user instance"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:470
|
||||
#: src/Module/Admin/Site.php:472
|
||||
msgid "Make this instance multi-user or single-user for the named user"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:472
|
||||
#: src/Module/Admin/Site.php:474
|
||||
msgid "Maximum image size"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:472
|
||||
#: src/Module/Admin/Site.php:474
|
||||
#, php-format
|
||||
msgid ""
|
||||
"Maximum size in bytes of uploaded images. Default is 0, which means no "
|
||||
|
|
@ -4277,192 +4255,192 @@ msgid ""
|
|||
"to %s (%s byte)"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:476
|
||||
#: src/Module/Admin/Site.php:478
|
||||
msgid "Maximum image length"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:476
|
||||
#: src/Module/Admin/Site.php:478
|
||||
msgid ""
|
||||
"Maximum length in pixels of the longest side of uploaded images. Default is "
|
||||
"-1, which means no limits."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:477
|
||||
#: src/Module/Admin/Site.php:479
|
||||
msgid "JPEG image quality"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:477
|
||||
#: src/Module/Admin/Site.php:479
|
||||
msgid ""
|
||||
"Uploaded JPEGS will be saved at this quality setting [0-100]. Default is "
|
||||
"100, which is full quality."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:479
|
||||
#: src/Module/Admin/Site.php:481
|
||||
msgid "Register policy"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:480
|
||||
#: src/Module/Admin/Site.php:482
|
||||
msgid "Maximum Daily Registrations"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:480
|
||||
#: src/Module/Admin/Site.php:482
|
||||
msgid ""
|
||||
"If registration is permitted above, this sets the maximum number of new user "
|
||||
"registrations to accept per day. If register is set to closed, this setting "
|
||||
"has no effect."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:481
|
||||
#: src/Module/Admin/Site.php:483
|
||||
msgid "Register text"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:481
|
||||
#: src/Module/Admin/Site.php:483
|
||||
msgid ""
|
||||
"Will be displayed prominently on the registration page. You can use BBCode "
|
||||
"here."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:482
|
||||
#: src/Module/Admin/Site.php:484
|
||||
msgid "Forbidden Nicknames"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:482
|
||||
#: src/Module/Admin/Site.php:484
|
||||
msgid ""
|
||||
"Comma separated list of nicknames that are forbidden from registration. "
|
||||
"Preset is a list of role names according RFC 2142."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:483
|
||||
#: src/Module/Admin/Site.php:485
|
||||
msgid "Accounts abandoned after x days"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:483
|
||||
#: src/Module/Admin/Site.php:485
|
||||
msgid ""
|
||||
"Will not waste system resources polling external sites for abandonded "
|
||||
"accounts. Enter 0 for no time limit."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:484
|
||||
#: src/Module/Admin/Site.php:486
|
||||
msgid "Allowed friend domains"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:484
|
||||
#: src/Module/Admin/Site.php:486
|
||||
msgid ""
|
||||
"Comma separated list of domains which are allowed to establish friendships "
|
||||
"with this site. Wildcards are accepted. Empty to allow any domains"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:485
|
||||
#: src/Module/Admin/Site.php:487
|
||||
msgid "Allowed email domains"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:485
|
||||
#: src/Module/Admin/Site.php:487
|
||||
msgid ""
|
||||
"Comma separated list of domains which are allowed in email addresses for "
|
||||
"registrations to this site. Wildcards are accepted. Empty to allow any "
|
||||
"domains"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:486
|
||||
#: src/Module/Admin/Site.php:488
|
||||
msgid "No OEmbed rich content"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:486
|
||||
#: src/Module/Admin/Site.php:488
|
||||
msgid ""
|
||||
"Don't show the rich content (e.g. embedded PDF), except from the domains "
|
||||
"listed below."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:487
|
||||
#: src/Module/Admin/Site.php:489
|
||||
msgid "Trusted third-party domains"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:487
|
||||
#: src/Module/Admin/Site.php:489
|
||||
msgid ""
|
||||
"Comma separated list of domains from which content is allowed to be embedded "
|
||||
"in posts like with OEmbed. All sub-domains of the listed domains are allowed "
|
||||
"as well."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:488
|
||||
#: src/Module/Admin/Site.php:490
|
||||
msgid "Block public"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:488
|
||||
#: src/Module/Admin/Site.php:490
|
||||
msgid ""
|
||||
"Check to block public access to all otherwise public personal pages on this "
|
||||
"site unless you are currently logged in."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:489
|
||||
#: src/Module/Admin/Site.php:491
|
||||
msgid "Force publish"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:489
|
||||
#: src/Module/Admin/Site.php:491
|
||||
msgid ""
|
||||
"Check to force all profiles on this site to be listed in the site directory."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:489
|
||||
#: src/Module/Admin/Site.php:491
|
||||
msgid "Enabling this may violate privacy laws like the GDPR"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:490
|
||||
#: src/Module/Admin/Site.php:492
|
||||
msgid "Global directory URL"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:490
|
||||
#: src/Module/Admin/Site.php:492
|
||||
msgid ""
|
||||
"URL to the global directory. If this is not set, the global directory is "
|
||||
"completely unavailable to the application."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:491
|
||||
#: src/Module/Admin/Site.php:493
|
||||
msgid "Private posts by default for new users"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:491
|
||||
#: src/Module/Admin/Site.php:493
|
||||
msgid ""
|
||||
"Set default post permissions for all new members to the default privacy "
|
||||
"group rather than public."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:492
|
||||
#: src/Module/Admin/Site.php:494
|
||||
msgid "Don't include post content in email notifications"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:492
|
||||
#: src/Module/Admin/Site.php:494
|
||||
msgid ""
|
||||
"Don't include the content of a post/comment/private message/etc. in the "
|
||||
"email notifications that are sent out from this site, as a privacy measure."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:493
|
||||
#: src/Module/Admin/Site.php:495
|
||||
msgid "Disallow public access to addons listed in the apps menu."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:493
|
||||
#: src/Module/Admin/Site.php:495
|
||||
msgid ""
|
||||
"Checking this box will restrict addons listed in the apps menu to members "
|
||||
"only."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:494
|
||||
#: src/Module/Admin/Site.php:496
|
||||
msgid "Don't embed private images in posts"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:494
|
||||
#: src/Module/Admin/Site.php:496
|
||||
msgid ""
|
||||
"Don't replace locally-hosted private photos in posts with an embedded copy "
|
||||
"of the image. This means that contacts who receive posts containing private "
|
||||
"photos will have to authenticate and load each image, which may take a while."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:495
|
||||
#: src/Module/Admin/Site.php:497
|
||||
msgid "Explicit Content"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:495
|
||||
#: src/Module/Admin/Site.php:497
|
||||
msgid ""
|
||||
"Set this to announce that your node is used mostly for explicit content that "
|
||||
"might not be suited for minors. This information will be published in the "
|
||||
|
|
@ -4471,267 +4449,267 @@ msgid ""
|
|||
"will be shown at the user registration page."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:496
|
||||
#: src/Module/Admin/Site.php:498
|
||||
msgid "Proxify external content"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:496
|
||||
#: src/Module/Admin/Site.php:498
|
||||
msgid ""
|
||||
"Route external content via the proxy functionality. This is used for example "
|
||||
"for some OEmbed accesses and in some other rare cases."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:497
|
||||
#: src/Module/Admin/Site.php:499
|
||||
msgid "Cache contact avatars"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:497
|
||||
#: src/Module/Admin/Site.php:499
|
||||
msgid ""
|
||||
"Locally store the avatar pictures of the contacts. This uses a lot of "
|
||||
"storage space but it increases the performance."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:498
|
||||
#: src/Module/Admin/Site.php:500
|
||||
msgid "Allow Users to set remote_self"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:498
|
||||
#: src/Module/Admin/Site.php:500
|
||||
msgid ""
|
||||
"With checking this, every user is allowed to mark every contact as a "
|
||||
"remote_self in the repair contact dialog. Setting this flag on a contact "
|
||||
"causes mirroring every posting of that contact in the users stream."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:499
|
||||
#: src/Module/Admin/Site.php:501
|
||||
msgid "Enable multiple registrations"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:499
|
||||
#: src/Module/Admin/Site.php:501
|
||||
msgid "Enable users to register additional accounts for use as pages."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:500
|
||||
#: src/Module/Admin/Site.php:502
|
||||
msgid "Enable OpenID"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:500
|
||||
#: src/Module/Admin/Site.php:502
|
||||
msgid "Enable OpenID support for registration and logins."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:501
|
||||
#: src/Module/Admin/Site.php:503
|
||||
msgid "Enable Fullname check"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:501
|
||||
#: src/Module/Admin/Site.php:503
|
||||
msgid ""
|
||||
"Enable check to only allow users to register with a space between the first "
|
||||
"name and the last name in their full name."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:502
|
||||
#: src/Module/Admin/Site.php:504
|
||||
msgid "Email administrators on new registration"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:502
|
||||
#: src/Module/Admin/Site.php:504
|
||||
msgid ""
|
||||
"If enabled and the system is set to an open registration, an email for each "
|
||||
"new registration is sent to the administrators."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:503
|
||||
#: src/Module/Admin/Site.php:505
|
||||
msgid "Community pages for visitors"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:503
|
||||
#: src/Module/Admin/Site.php:505
|
||||
msgid ""
|
||||
"Which community pages should be available for visitors. Local users always "
|
||||
"see both pages."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:504
|
||||
#: src/Module/Admin/Site.php:506
|
||||
msgid "Posts per user on community page"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:504
|
||||
#: src/Module/Admin/Site.php:506
|
||||
msgid ""
|
||||
"The maximum number of posts per user on the community page. (Not valid for "
|
||||
"\"Global Community\")"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:506
|
||||
#: src/Module/Admin/Site.php:508
|
||||
msgid "Enable Mail support"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:506
|
||||
#: src/Module/Admin/Site.php:508
|
||||
msgid ""
|
||||
"Enable built-in mail support to poll IMAP folders and to reply via mail."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:507
|
||||
#: src/Module/Admin/Site.php:509
|
||||
msgid ""
|
||||
"Mail support can't be enabled because the PHP IMAP module is not installed."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:508
|
||||
#: src/Module/Admin/Site.php:510
|
||||
msgid "Enable OStatus support"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:508
|
||||
#: src/Module/Admin/Site.php:510
|
||||
msgid ""
|
||||
"Enable built-in OStatus (StatusNet, GNU Social etc.) compatibility. All "
|
||||
"communications in OStatus are public."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:510
|
||||
#: src/Module/Admin/Site.php:512
|
||||
msgid ""
|
||||
"Diaspora support can't be enabled because Friendica was installed into a sub "
|
||||
"directory."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:511
|
||||
#: src/Module/Admin/Site.php:513
|
||||
msgid "Enable Diaspora support"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:511
|
||||
#: src/Module/Admin/Site.php:513
|
||||
msgid ""
|
||||
"Enable built-in Diaspora network compatibility for communicating with "
|
||||
"diaspora servers."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:512
|
||||
#: src/Module/Admin/Site.php:514
|
||||
msgid "Verify SSL"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:512
|
||||
#: src/Module/Admin/Site.php:514
|
||||
msgid ""
|
||||
"If you wish, you can turn on strict certificate checking. This will mean you "
|
||||
"cannot connect (at all) to self-signed SSL sites."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:513
|
||||
#: src/Module/Admin/Site.php:515
|
||||
msgid "Proxy user"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:513
|
||||
#: src/Module/Admin/Site.php:515
|
||||
msgid "User name for the proxy server."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:514
|
||||
#: src/Module/Admin/Site.php:516
|
||||
msgid "Proxy URL"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:514
|
||||
#: src/Module/Admin/Site.php:516
|
||||
msgid ""
|
||||
"If you want to use a proxy server that Friendica should use to connect to "
|
||||
"the network, put the URL of the proxy here."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:515
|
||||
#: src/Module/Admin/Site.php:517
|
||||
msgid "Network timeout"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:515
|
||||
#: src/Module/Admin/Site.php:517
|
||||
msgid "Value is in seconds. Set to 0 for unlimited (not recommended)."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:516
|
||||
#: src/Module/Admin/Site.php:518
|
||||
msgid "Maximum Load Average"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:516
|
||||
#: src/Module/Admin/Site.php:518
|
||||
#, php-format
|
||||
msgid ""
|
||||
"Maximum system load before delivery and poll processes are deferred - "
|
||||
"default %d."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:517
|
||||
#: src/Module/Admin/Site.php:519
|
||||
msgid "Minimal Memory"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:517
|
||||
#: src/Module/Admin/Site.php:519
|
||||
msgid ""
|
||||
"Minimal free memory in MB for the worker. Needs access to /proc/meminfo - "
|
||||
"default 0 (deactivated)."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:518
|
||||
#: src/Module/Admin/Site.php:520
|
||||
msgid "Periodically optimize tables"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:518
|
||||
#: src/Module/Admin/Site.php:520
|
||||
msgid "Periodically optimize tables like the cache and the workerqueue"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:520
|
||||
#: src/Module/Admin/Site.php:522
|
||||
msgid "Discover followers/followings from contacts"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:520
|
||||
#: src/Module/Admin/Site.php:522
|
||||
msgid ""
|
||||
"If enabled, contacts are checked for their followers and following contacts."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:521
|
||||
#: src/Module/Admin/Site.php:523
|
||||
msgid "None - deactivated"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:522
|
||||
#: src/Module/Admin/Site.php:524
|
||||
msgid ""
|
||||
"Local contacts - contacts of our local contacts are discovered for their "
|
||||
"followers/followings."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:523
|
||||
#: src/Module/Admin/Site.php:525
|
||||
msgid ""
|
||||
"Interactors - contacts of our local contacts and contacts who interacted on "
|
||||
"locally visible postings are discovered for their followers/followings."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:525
|
||||
#: src/Module/Admin/Site.php:527
|
||||
msgid "Synchronize the contacts with the directory server"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:525
|
||||
#: src/Module/Admin/Site.php:527
|
||||
msgid ""
|
||||
"if enabled, the system will check periodically for new contacts on the "
|
||||
"defined directory server."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:527
|
||||
#: src/Module/Admin/Site.php:529
|
||||
msgid "Days between requery"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:527
|
||||
#: src/Module/Admin/Site.php:529
|
||||
msgid "Number of days after which a server is requeried for his contacts."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:528
|
||||
#: src/Module/Admin/Site.php:530
|
||||
msgid "Discover contacts from other servers"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:528
|
||||
#: src/Module/Admin/Site.php:530
|
||||
msgid ""
|
||||
"Periodically query other servers for contacts. The system queries Friendica, "
|
||||
"Mastodon and Hubzilla servers."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:529
|
||||
#: src/Module/Admin/Site.php:531
|
||||
msgid "Search the local directory"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:529
|
||||
#: src/Module/Admin/Site.php:531
|
||||
msgid ""
|
||||
"Search the local directory instead of the global directory. When searching "
|
||||
"locally, every search will be executed on the global directory in the "
|
||||
"background. This improves the search results when the search is repeated."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:531
|
||||
#: src/Module/Admin/Site.php:533
|
||||
msgid "Publish server information"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:531
|
||||
#: src/Module/Admin/Site.php:533
|
||||
msgid ""
|
||||
"If enabled, general server and usage data will be published. The data "
|
||||
"contains the name and version of the server, number of users with public "
|
||||
|
|
@ -4739,50 +4717,50 @@ msgid ""
|
|||
"href=\"http://the-federation.info/\">the-federation.info</a> for details."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:533
|
||||
#: src/Module/Admin/Site.php:535
|
||||
msgid "Check upstream version"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:533
|
||||
#: src/Module/Admin/Site.php:535
|
||||
msgid ""
|
||||
"Enables checking for new Friendica versions at github. If there is a new "
|
||||
"version, you will be informed in the admin panel overview."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:534
|
||||
#: src/Module/Admin/Site.php:536
|
||||
msgid "Suppress Tags"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:534
|
||||
#: src/Module/Admin/Site.php:536
|
||||
msgid "Suppress showing a list of hashtags at the end of the posting."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:535
|
||||
#: src/Module/Admin/Site.php:537
|
||||
msgid "Clean database"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:535
|
||||
#: src/Module/Admin/Site.php:537
|
||||
msgid ""
|
||||
"Remove old remote items, orphaned database records and old content from some "
|
||||
"other helper tables."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:536
|
||||
#: src/Module/Admin/Site.php:538
|
||||
msgid "Lifespan of remote items"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:536
|
||||
#: src/Module/Admin/Site.php:538
|
||||
msgid ""
|
||||
"When the database cleanup is enabled, this defines the days after which "
|
||||
"remote items will be deleted. Own items, and marked or filed items are "
|
||||
"always kept. 0 disables this behaviour."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:537
|
||||
#: src/Module/Admin/Site.php:539
|
||||
msgid "Lifespan of unclaimed items"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:537
|
||||
#: src/Module/Admin/Site.php:539
|
||||
msgid ""
|
||||
"When the database cleanup is enabled, this defines the days after which "
|
||||
"unclaimed remote items (mostly content from the relay) will be deleted. "
|
||||
|
|
@ -4790,144 +4768,144 @@ msgid ""
|
|||
"items if set to 0."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:538
|
||||
#: src/Module/Admin/Site.php:540
|
||||
msgid "Lifespan of raw conversation data"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:538
|
||||
#: src/Module/Admin/Site.php:540
|
||||
msgid ""
|
||||
"The conversation data is used for ActivityPub and OStatus, as well as for "
|
||||
"debug purposes. It should be safe to remove it after 14 days, default is 90 "
|
||||
"days."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:539
|
||||
#: src/Module/Admin/Site.php:541
|
||||
msgid "Maximum numbers of comments per post"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:539
|
||||
#: src/Module/Admin/Site.php:541
|
||||
msgid "How much comments should be shown for each post? Default value is 100."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:540
|
||||
#: src/Module/Admin/Site.php:542
|
||||
msgid "Maximum numbers of comments per post on the display page"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:540
|
||||
#: src/Module/Admin/Site.php:542
|
||||
msgid ""
|
||||
"How many comments should be shown on the single view for each post? Default "
|
||||
"value is 1000."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:541
|
||||
#: src/Module/Admin/Site.php:543
|
||||
msgid "Temp path"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:541
|
||||
#: src/Module/Admin/Site.php:543
|
||||
msgid ""
|
||||
"If you have a restricted system where the webserver can't access the system "
|
||||
"temp path, enter another path here."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:542
|
||||
#: src/Module/Admin/Site.php:544
|
||||
msgid "Only search in tags"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:542
|
||||
#: src/Module/Admin/Site.php:544
|
||||
msgid "On large systems the text search can slow down the system extremely."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:543
|
||||
#: src/Module/Admin/Site.php:545
|
||||
msgid "Generate counts per contact group when calculating network count"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:543
|
||||
#: src/Module/Admin/Site.php:545
|
||||
msgid ""
|
||||
"On systems with users that heavily use contact groups the query can be very "
|
||||
"expensive."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:545
|
||||
#: src/Module/Admin/Site.php:547
|
||||
msgid "Maximum number of parallel workers"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:545
|
||||
#: src/Module/Admin/Site.php:547
|
||||
#, php-format
|
||||
msgid ""
|
||||
"On shared hosters set this to %d. On larger systems, values of %d are great. "
|
||||
"Default value is %d."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:546
|
||||
#: src/Module/Admin/Site.php:548
|
||||
msgid "Enable fastlane"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:546
|
||||
#: src/Module/Admin/Site.php:548
|
||||
msgid ""
|
||||
"When enabed, the fastlane mechanism starts an additional worker if processes "
|
||||
"with higher priority are blocked by processes of lower priority."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:548
|
||||
#: src/Module/Admin/Site.php:550
|
||||
msgid "Direct relay transfer"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:548
|
||||
#: src/Module/Admin/Site.php:550
|
||||
msgid ""
|
||||
"Enables the direct transfer to other servers without using the relay servers"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:549
|
||||
#: src/Module/Admin/Site.php:551
|
||||
msgid "Relay scope"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:549
|
||||
#: src/Module/Admin/Site.php:551
|
||||
msgid ""
|
||||
"Can be \"all\" or \"tags\". \"all\" means that every public post should be "
|
||||
"received. \"tags\" means that only posts with selected tags should be "
|
||||
"received."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:549 src/Module/Contact/Profile.php:274
|
||||
#: src/Module/Admin/Site.php:551 src/Module/Contact/Profile.php:274
|
||||
#: src/Module/Settings/TwoFactor/Index.php:125
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:549
|
||||
#: src/Module/Admin/Site.php:551
|
||||
msgid "all"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:549
|
||||
#: src/Module/Admin/Site.php:551
|
||||
msgid "tags"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:550
|
||||
#: src/Module/Admin/Site.php:552
|
||||
msgid "Server tags"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:550
|
||||
#: src/Module/Admin/Site.php:552
|
||||
msgid "Comma separated list of tags for the \"tags\" subscription."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:551
|
||||
#: src/Module/Admin/Site.php:553
|
||||
msgid "Deny Server tags"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:551
|
||||
#: src/Module/Admin/Site.php:553
|
||||
msgid "Comma separated list of tags that are rejected."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:552
|
||||
#: src/Module/Admin/Site.php:554
|
||||
msgid "Allow user tags"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:552
|
||||
#: src/Module/Admin/Site.php:554
|
||||
msgid ""
|
||||
"If enabled, the tags from the saved searches will used for the \"tags\" "
|
||||
"subscription in addition to the \"relay_server_tags\"."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Site.php:555
|
||||
#: src/Module/Admin/Site.php:557
|
||||
msgid "Start Relocation"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -4977,12 +4955,12 @@ msgstr ""
|
|||
msgid "Database (legacy)"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Summary.php:56
|
||||
#: src/Module/Admin/Summary.php:57
|
||||
#, php-format
|
||||
msgid "Template engine (%s) error: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Summary.php:60
|
||||
#: src/Module/Admin/Summary.php:61
|
||||
#, php-format
|
||||
msgid ""
|
||||
"Your DB still runs with MyISAM tables. You should change the engine type to "
|
||||
|
|
@ -4993,7 +4971,7 @@ msgid ""
|
|||
"automatic conversion.<br />"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Summary.php:65
|
||||
#: src/Module/Admin/Summary.php:66
|
||||
#, php-format
|
||||
msgid ""
|
||||
"Your DB still runs with InnoDB tables in the Antelope file format. You "
|
||||
|
|
@ -5004,7 +4982,7 @@ msgid ""
|
|||
"installation for an automatic conversion.<br />"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Summary.php:75
|
||||
#: src/Module/Admin/Summary.php:76
|
||||
#, php-format
|
||||
msgid ""
|
||||
"Your table_definition_cache is too low (%d). This can lead to the database "
|
||||
|
|
@ -5012,39 +4990,39 @@ msgid ""
|
|||
"to %d. See <a href=\"%s\">here</a> for more information.<br />"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Summary.php:85
|
||||
#: src/Module/Admin/Summary.php:86
|
||||
#, 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:94
|
||||
#: src/Module/Admin/Summary.php:95
|
||||
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:98
|
||||
#: src/Module/Admin/Summary.php:99
|
||||
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:103
|
||||
#: src/Module/Admin/Summary.php:104
|
||||
msgid "The worker was never executed. Please check your database structure!"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Summary.php:105
|
||||
#: src/Module/Admin/Summary.php:106
|
||||
#, 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:110
|
||||
#: src/Module/Admin/Summary.php:111
|
||||
#, php-format
|
||||
msgid ""
|
||||
"Friendica's configuration now is stored in config/local.config.php, please "
|
||||
|
|
@ -5053,7 +5031,7 @@ msgid ""
|
|||
"with the transition."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Summary.php:114
|
||||
#: src/Module/Admin/Summary.php:115
|
||||
#, php-format
|
||||
msgid ""
|
||||
"Friendica's configuration now is stored in config/local.config.php, please "
|
||||
|
|
@ -5062,7 +5040,15 @@ msgid ""
|
|||
"with the transition."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Summary.php:120
|
||||
#: src/Module/Admin/Summary.php:119
|
||||
#, php-format
|
||||
msgid ""
|
||||
"Friendica's configuration store \"%s\" isn't writable. Until then database "
|
||||
"updates won't be applied automatically, admin settings and console "
|
||||
"configuration changes won't be saved."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Summary.php:125
|
||||
#, php-format
|
||||
msgid ""
|
||||
"<a href=\"%s\">%s</a> is not reachable on your system. This is a severe "
|
||||
|
|
@ -5070,50 +5056,50 @@ msgid ""
|
|||
"href=\"%s\">the installation page</a> for help."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Summary.php:138
|
||||
#: src/Module/Admin/Summary.php:143
|
||||
#, php-format
|
||||
msgid "The logfile '%s' is not usable. No logging possible (error: '%s')"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Summary.php:152
|
||||
#: src/Module/Admin/Summary.php:157
|
||||
#, php-format
|
||||
msgid "The debug logfile '%s' is not usable. No logging possible (error: '%s')"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Summary.php:168
|
||||
#: src/Module/Admin/Summary.php:173
|
||||
#, 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:176
|
||||
#: src/Module/Admin/Summary.php:181
|
||||
#, 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:184
|
||||
#: src/Module/Admin/Summary.php:189
|
||||
#, 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:195
|
||||
#: src/Module/Admin/Summary.php:200
|
||||
msgid "Message queues"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Summary.php:201
|
||||
#: src/Module/Admin/Summary.php:206
|
||||
msgid "Server Settings"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Summary.php:219
|
||||
#: src/Module/Admin/Summary.php:224
|
||||
msgid "Version"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Summary.php:223
|
||||
#: src/Module/Admin/Summary.php:228
|
||||
msgid "Active addons"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -5581,7 +5567,7 @@ msgstr ""
|
|||
msgid "Create New Event"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Calendar/Show.php:132 src/Module/Settings/Display.php:238
|
||||
#: src/Module/Calendar/Show.php:132 src/Module/Settings/Display.php:235
|
||||
msgid "list"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -9542,153 +9528,142 @@ msgstr ""
|
|||
msgid "No entries."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:139
|
||||
#: src/Module/Settings/Display.php:137
|
||||
msgid "The theme you chose isn't available."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:179
|
||||
#: src/Module/Settings/Display.php:177
|
||||
#, php-format
|
||||
msgid "%s - (Unsupported)"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:215
|
||||
#: src/Module/Settings/Display.php:212
|
||||
msgid "No preview"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:216
|
||||
#: src/Module/Settings/Display.php:213
|
||||
msgid "No image"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:217
|
||||
#: src/Module/Settings/Display.php:214
|
||||
msgid "Small Image"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:218
|
||||
#: src/Module/Settings/Display.php:215
|
||||
msgid "Large Image"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:249
|
||||
#: src/Module/Settings/Display.php:246
|
||||
msgid "Display Settings"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:251
|
||||
#: src/Module/Settings/Display.php:248
|
||||
msgid "General Theme Settings"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:252
|
||||
#: src/Module/Settings/Display.php:249
|
||||
msgid "Custom Theme Settings"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:253
|
||||
#: src/Module/Settings/Display.php:250
|
||||
msgid "Content Settings"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:254 view/theme/duepuntozero/config.php:86
|
||||
#: src/Module/Settings/Display.php:251 view/theme/duepuntozero/config.php:86
|
||||
#: view/theme/frio/config.php:172 view/theme/quattro/config.php:88
|
||||
#: view/theme/vier/config.php:136
|
||||
msgid "Theme settings"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:261
|
||||
#: src/Module/Settings/Display.php:258
|
||||
msgid "Display Theme:"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:262
|
||||
#: src/Module/Settings/Display.php:259
|
||||
msgid "Mobile Theme:"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:265
|
||||
#: src/Module/Settings/Display.php:262
|
||||
msgid "Number of items to display per page:"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:265 src/Module/Settings/Display.php:266
|
||||
#: src/Module/Settings/Display.php:262 src/Module/Settings/Display.php:263
|
||||
msgid "Maximum of 100 items"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:266
|
||||
#: src/Module/Settings/Display.php:263
|
||||
msgid "Number of items to display per page when viewed from mobile device:"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:267
|
||||
#: src/Module/Settings/Display.php:264
|
||||
msgid "Update browser every xx seconds"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:267
|
||||
#: src/Module/Settings/Display.php:264
|
||||
msgid "Minimum of 10 seconds. Enter -1 to disable it."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:268
|
||||
msgid "Automatic updates only at the top of the post stream pages"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:268
|
||||
msgid ""
|
||||
"Auto update may add new posts at the top of the post stream pages, which can "
|
||||
"affect the scroll position and perturb normal reading if it happens anywhere "
|
||||
"else the top of the page."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:269
|
||||
#: src/Module/Settings/Display.php:265
|
||||
msgid "Display emoticons"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:269
|
||||
#: src/Module/Settings/Display.php:265
|
||||
msgid "When enabled, emoticons are replaced with matching symbols."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:270
|
||||
#: src/Module/Settings/Display.php:266
|
||||
msgid "Infinite scroll"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:270
|
||||
#: src/Module/Settings/Display.php:266
|
||||
msgid "Automatic fetch new items when reaching the page end."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:271
|
||||
#: src/Module/Settings/Display.php:267
|
||||
msgid "Enable Smart Threading"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:271
|
||||
#: src/Module/Settings/Display.php:267
|
||||
msgid "Enable the automatic suppression of extraneous thread indentation."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:272
|
||||
#: src/Module/Settings/Display.php:268
|
||||
msgid "Display the Dislike feature"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:272
|
||||
#: src/Module/Settings/Display.php:268
|
||||
msgid "Display the Dislike button and dislike reactions on posts and comments."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:273
|
||||
#: src/Module/Settings/Display.php:269
|
||||
msgid "Display the resharer"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:273
|
||||
#: src/Module/Settings/Display.php:269
|
||||
msgid "Display the first resharer as icon and text on a reshared item."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:274
|
||||
#: src/Module/Settings/Display.php:270
|
||||
msgid "Stay local"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:274
|
||||
#: src/Module/Settings/Display.php:270
|
||||
msgid "Don't go to a remote system when following a contact link."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:275
|
||||
#: src/Module/Settings/Display.php:271
|
||||
msgid "Link preview mode"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:275
|
||||
#: src/Module/Settings/Display.php:271
|
||||
msgid "Appearance of the link preview that is added to each post with a link."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:277
|
||||
#: src/Module/Settings/Display.php:273
|
||||
msgid "Beginning of week:"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Settings/Display.php:278
|
||||
#: src/Module/Settings/Display.php:274
|
||||
msgid "Default calendar view:"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
|
||||
{{include file="field_input.tpl" field=$itemspage_mobile_network}}
|
||||
{{include file="field_input.tpl" field=$ajaxint}}
|
||||
{{include file="field_checkbox.tpl" field=$no_auto_update}}
|
||||
{{include file="field_checkbox.tpl" field=$enable_smile}}
|
||||
{{include file="field_checkbox.tpl" field=$infinite_scroll}}
|
||||
{{include file="field_checkbox.tpl" field=$enable_smart_threading}}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ $login_bg_color = '';
|
|||
$modified = time();
|
||||
|
||||
if (DI::mode()->has(\Friendica\App\Mode::MAINTENANCEDISABLED)) {
|
||||
DI::config()->load('frio');
|
||||
DI::config()->reload();
|
||||
|
||||
// Default to hard-coded values for empty settings
|
||||
$scheme = DI::config()->get('frio', 'scheme', DI::config()->get('frio', 'schema'));
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
{{* Template for singele photo view *}}
|
||||
{{* Template for single photo view *}}
|
||||
|
||||
{{* "live-photos" is needed for js autoupdate *}}
|
||||
<div id="live-photos"></div>
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@
|
|||
{{include file="field_input.tpl" field=$itemspage_network}}
|
||||
{{include file="field_input.tpl" field=$itemspage_mobile_network}}
|
||||
{{include file="field_input.tpl" field=$ajaxint}}
|
||||
{{include file="field_checkbox.tpl" field=$no_auto_update}}
|
||||
{{include file="field_checkbox.tpl" field=$enable_smile}}
|
||||
{{include file="field_checkbox.tpl" field=$infinite_scroll}}
|
||||
{{include file="field_checkbox.tpl" field=$enable_smart_threading}}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue