diff --git a/bin/daemon.php b/bin/daemon.php index d5ef02a8ec..b7085a490a 100755 --- a/bin/daemon.php +++ b/bin/daemon.php @@ -115,7 +115,7 @@ if (is_readable($pidfile)) { } if (empty($pid) && in_array($mode, ['stop', 'status'])) { - DI::config()->set('system', 'worker_daemon_mode', false); + DI::keyValue()->set('worker_daemon_mode', false); die("Pidfile wasn't found. Is the daemon running?\n"); } @@ -137,7 +137,7 @@ if ($mode == 'stop') { Logger::notice('Worker daemon process was killed', ['pid' => $pid]); - DI::config()->set('system', 'worker_daemon_mode', false); + DI::keyValue()->set('worker_daemon_mode', false); die("Worker daemon process $pid was killed.\n"); } @@ -181,7 +181,7 @@ if (!$foreground) { DBA::connect(); } -DI::config()->set('system', 'worker_daemon_mode', true); +DI::keyValue()->set('worker_daemon_mode', true); // Just to be sure that this script really runs endlessly set_time_limit(0); diff --git a/database.sql b/database.sql index 7eb756cf2a..2ae33689c1 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2023.03-dev (Giant Rhubarb) --- DB_UPDATE_VERSION 1504 +-- DB_UPDATE_VERSION 1505 -- ------------------------------------------ @@ -839,6 +839,16 @@ CREATE TABLE IF NOT EXISTS `intro` ( FOREIGN KEY (`suggest-cid`) REFERENCES `contact` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE ) DEFAULT COLLATE utf8mb4_general_ci COMMENT=''; +-- +-- TABLE key-value +-- +CREATE TABLE IF NOT EXISTS `key-value` ( + `k` varbinary(50) NOT NULL COMMENT '', + `v` mediumtext COMMENT '', + `updated_at` int unsigned NOT NULL COMMENT 'timestamp of the last update', + PRIMARY KEY(`k`) +) DEFAULT COLLATE utf8mb4_general_ci COMMENT='A key value storage'; + -- -- TABLE locks -- diff --git a/doc/database.md b/doc/database.md index 9fa438c8d2..5759d29ec7 100644 --- a/doc/database.md +++ b/doc/database.md @@ -40,6 +40,7 @@ Database Tables | [inbox-status](help/database/db_inbox-status) | Status of ActivityPub inboxes | | [intro](help/database/db_intro) | | | [item-uri](help/database/db_item-uri) | URI and GUID for items | +| [key-value](help/database/db_key-value) | A key value storage | | [locks](help/database/db_locks) | | | [mail](help/database/db_mail) | private messages | | [mailacct](help/database/db_mailacct) | Mail account data for fetching mails | diff --git a/doc/database/db_key-value.md b/doc/database/db_key-value.md new file mode 100644 index 0000000000..2ed3baa48c --- /dev/null +++ b/doc/database/db_key-value.md @@ -0,0 +1,23 @@ +Table key-value +=========== + +A key value storage + +Fields +------ + +| Field | Description | Type | Null | Key | Default | Extra | +| ---------- | ---------------------------- | ------------- | ---- | --- | ------- | ----- | +| k | | varbinary(50) | NO | PRI | NULL | | +| v | | mediumtext | YES | | NULL | | +| updated_at | timestamp of the last update | int unsigned | NO | | NULL | | + +Indexes +------------ + +| Name | Fields | +| ------- | ------ | +| PRIMARY | k | + + +Return to [database documentation](help/database) diff --git a/doc/tools.md b/doc/tools.md index 1c3b8e119c..fac1f4b392 100644 --- a/doc/tools.md +++ b/doc/tools.md @@ -51,7 +51,7 @@ In */etc/fail2ban/jail.local* create a section for Friendica: bantime = 900 filter = friendica port = http,https - logpath = /var/log/friend.log + logpath = /var/log/friendica.log logencoding = utf-8 And create a filter definition in */etc/fail2ban/filter.d/friendica.conf*: diff --git a/doc/translations.md b/doc/translations.md index 23ac4a62d7..8b7077b6b1 100644 --- a/doc/translations.md +++ b/doc/translations.md @@ -24,6 +24,16 @@ For addons, we add support for a language when if we already support the languag ## Add new translation strings +### Supported gettext version + +We currently support the gettext version 0.19.8.1 and actively check new translation strings with this version. + +If you don't use this version, it's possible that our checks fail (f.e. because of tiny differences at linebreaks). +In case you do have a Docker environment, you can easily update the translations with the following command: +```shell +docker run --rm -v $PWD:/data -w /data friendicaci/transifex bin/run_xgettext.sh +``` + ### Core Once you have added new translation strings in your code changes, please run `bin/run_xgettext.sh` from the base Friendica directory and commit the updated `view/lang/C/messages.po` to your branch. diff --git a/src/Console/Contact.php b/src/Console/Contact.php index 37f3f056e4..d5f3c9923f 100644 --- a/src/Console/Contact.php +++ b/src/Console/Contact.php @@ -157,7 +157,7 @@ HELP; $url = Probe::cleanURI($url); - $contact = ContactModel::getByURLForUser($url, $user['uid']); + $contact = ContactModel::getByURL($url, null, [], $user['uid']); if (!empty($contact)) { throw new RuntimeException('Contact already exists'); } diff --git a/src/Console/PostUpdate.php b/src/Console/PostUpdate.php index 8bec14e276..702b127109 100644 --- a/src/Console/PostUpdate.php +++ b/src/Console/PostUpdate.php @@ -22,7 +22,7 @@ namespace Friendica\Console; use Friendica\App; -use Friendica\Core\Config\Capability\IManageConfigValues; +use Friendica\Core\KeyValueStorage\Capabilities\IManageKeyValuePairs; use Friendica\Core\L10n; use Friendica\Core\Update; @@ -38,9 +38,9 @@ class PostUpdate extends \Asika\SimpleConsole\Console */ private $appMode; /** - * @var IManageConfigValues + * @var IManageKeyValuePairs */ - private $config; + private $keyValue; /** * @var L10n */ @@ -60,13 +60,13 @@ HELP; return $help; } - public function __construct(App\Mode $appMode, IManageConfigValues $config, L10n $l10n, array $argv = null) + public function __construct(App\Mode $appMode, IManageKeyValuePairs $keyValue, L10n $l10n, array $argv = null) { parent::__construct($argv); - $this->appMode = $appMode; - $this->config = $config; - $this->l10n = $l10n; + $this->appMode = $appMode; + $this->keyValue = $keyValue; + $this->l10n = $l10n; } protected function doExecute(): int @@ -83,7 +83,7 @@ HELP; $this->out($this->getHelp()); return 0; } elseif ($reset_version) { - $this->config->set('system', 'post_update_version', $reset_version); + $this->keyValue->set('post_update_version', $reset_version); echo $this->l10n->t('Post update version number has been set to %s.', $reset_version) . "\n"; return 0; } diff --git a/src/Core/KeyValueStorage/Capabilities/IManageKeyValuePairs.php b/src/Core/KeyValueStorage/Capabilities/IManageKeyValuePairs.php new file mode 100644 index 0000000000..64b317bf1a --- /dev/null +++ b/src/Core/KeyValueStorage/Capabilities/IManageKeyValuePairs.php @@ -0,0 +1,64 @@ +. + * + */ + +namespace Friendica\Core\KeyValueStorage\Capabilities; + +use Friendica\Core\KeyValueStorage\Exceptions\KeyValueStoragePersistenceException; + +/** + * Interface for Friendica specific Key-Value pair storage + */ +interface IManageKeyValuePairs extends \ArrayAccess +{ + /** + * Get a particular value from the KeyValue Storage + * + * @param string $key The key to query + * + * @return mixed Stored value or null if it does not exist + * + * @throws KeyValueStoragePersistenceException In case the persistence layer throws errors + * + */ + public function get(string $key); + + /** + * Sets a value for a given key + * + * Note: Please do not store booleans - convert to 0/1 integer values! + * + * @param string $key The configuration key to set + * @param mixed $value The value to store + * + * @throws KeyValueStoragePersistenceException In case the persistence layer throws errors + */ + public function set(string $key, $value): void; + + /** + * Deletes the given key. + * + * @param string $key The configuration key to delete + * + * @throws KeyValueStoragePersistenceException In case the persistence layer throws errors + * + */ + public function delete(string $key): void; +} diff --git a/src/Core/KeyValueStorage/Exceptions/KeyValueStoragePersistenceException.php b/src/Core/KeyValueStorage/Exceptions/KeyValueStoragePersistenceException.php new file mode 100644 index 0000000000..ad04c33aea --- /dev/null +++ b/src/Core/KeyValueStorage/Exceptions/KeyValueStoragePersistenceException.php @@ -0,0 +1,30 @@ +. + * + */ + +namespace Friendica\Core\KeyValueStorage\Exceptions; + +class KeyValueStoragePersistenceException extends \RuntimeException +{ + public function __construct($message = "", \Throwable $previous = null) + { + parent::__construct($message, 500, $previous); + } +} diff --git a/src/Core/KeyValueStorage/Type/AbstractKeyValueStorage.php b/src/Core/KeyValueStorage/Type/AbstractKeyValueStorage.php new file mode 100644 index 0000000000..169d27f69b --- /dev/null +++ b/src/Core/KeyValueStorage/Type/AbstractKeyValueStorage.php @@ -0,0 +1,48 @@ +. + * + */ + +namespace Friendica\Core\KeyValueStorage\Type; + +use Friendica\Core\KeyValueStorage\Capabilities\IManageKeyValuePairs; + +/** + * An abstract helper class for Key-Value storage classes + */ +abstract class AbstractKeyValueStorage implements IManageKeyValuePairs +{ + /** {@inheritDoc} */ + public function get(string $key) + { + return $this->offsetGet($key); + } + + /** {@inheritDoc} */ + public function set(string $key, $value): void + { + $this->offsetSet($key, $value); + } + + /** {@inheritDoc} */ + public function delete(string $key): void + { + $this->offsetUnset($key); + } +} diff --git a/src/Core/KeyValueStorage/Type/DBKeyValueStorage.php b/src/Core/KeyValueStorage/Type/DBKeyValueStorage.php new file mode 100644 index 0000000000..de8320c5ef --- /dev/null +++ b/src/Core/KeyValueStorage/Type/DBKeyValueStorage.php @@ -0,0 +1,117 @@ +. + * + */ + +namespace Friendica\Core\KeyValueStorage\Type; + +use Friendica\Core\Config\Util\ValueConversion; +use Friendica\Core\KeyValueStorage\Exceptions\KeyValueStoragePersistenceException; +use Friendica\Database\Database; + +/** + * A Key-Value storage provider with DB as persistence layer + */ +class DBKeyValueStorage extends AbstractKeyValueStorage +{ + const DB_KEY_VALUE_TABLE = 'key-value'; + + /** @var Database */ + protected $database; + + public function __construct(Database $database) + { + $this->database = $database; + } + + /** {@inheritDoc} */ + public function offsetExists($offset): bool + { + try { + return $this->database->exists(self::DB_KEY_VALUE_TABLE, ['k' => $offset]); + } catch (\Exception $exception) { + throw new KeyValueStoragePersistenceException(sprintf('Cannot check storage with key %s', $offset), $exception); + } + } + + /** {@inheritDoc} */ + #[\ReturnTypeWillChange] + public function offsetGet($offset) + { + try { + $result = $this->database->selectFirst(self::DB_KEY_VALUE_TABLE, ['v'], ['k' => $offset]); + + if ($this->database->isResult($result)) { + $value = ValueConversion::toConfigValue($result['v']); + + // just return it in case it is set + if (isset($value)) { + return $value; + } + } + } catch (\Exception $exception) { + throw new KeyValueStoragePersistenceException(sprintf('Cannot get value for key %s', $offset), $exception); + } + + return null; + } + + /** {@inheritDoc} */ + #[\ReturnTypeWillChange] + public function offsetSet($offset, $value) + { + try { + // 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($offset); + + if (isset($stored_value) && ($stored_value === $compare_value)) { + return; + } + + $dbValue = ValueConversion::toDbValue($value); + + $return = $this->database->update(self::DB_KEY_VALUE_TABLE, [ + 'v' => $dbValue, + 'updated_at' => time() + ], ['k' => $offset], true); + + if (!$return) { + throw new \Exception(sprintf('database update failed: %s', $this->database->errorMessage())); + } + } catch (\Exception $exception) { + throw new KeyValueStoragePersistenceException(sprintf('Cannot set value for %s for key %s', $value, $offset), $exception); + } + } + + /** {@inheritDoc} */ + #[\ReturnTypeWillChange] + public function offsetUnset($offset) + { + try { + if (!$this->database->delete(self::DB_KEY_VALUE_TABLE, ['k' => $offset])) { + throw new \Exception(sprintf('database deletion failed: %s', $this->database->errorMessage())); + } + } catch (\Exception $exception) { + throw new KeyValueStoragePersistenceException(sprintf('Cannot delete value with key %s', $offset), $exception); + } + } +} diff --git a/src/Core/Update.php b/src/Core/Update.php index 8ec96dc989..9e05c1b5bc 100644 --- a/src/Core/Update.php +++ b/src/Core/Update.php @@ -76,7 +76,7 @@ class Update } // The postupdate has to completed version 1288 for the new post views to take over - $postupdate = DI::config()->get('system', 'post_update_version', self::NEW_TABLE_STRUCTURE_VERSION); + $postupdate = DI::keyValue()->get('post_update_version') ?? self::NEW_TABLE_STRUCTURE_VERSION; if ($postupdate < self::NEW_TABLE_STRUCTURE_VERSION) { $error = DI::l10n()->t('Updates from postupdate version %s are not supported. Please update at least to version 2021.01 and wait until the postupdate finished version 1383.', $postupdate); if (DI::mode()->getExecutor() == Mode::INDEX) { diff --git a/src/Core/Worker.php b/src/Core/Worker.php index d6f97eed21..cbe6645294 100644 --- a/src/Core/Worker.php +++ b/src/Core/Worker.php @@ -89,9 +89,9 @@ class Worker self::$process = $process; // Kill stale processes every 5 minutes - $last_cleanup = DI::config()->get('system', 'worker_last_cleaned', 0); + $last_cleanup = DI::keyValue()->get('worker_last_cleaned') ?? 0; if (time() > ($last_cleanup + 300)) { - DI::config()->set('system', 'worker_last_cleaned', time()); + DI::keyValue()->set( 'worker_last_cleaned', time()); Worker\Cron::killStaleWorkers(); } @@ -388,7 +388,7 @@ class Worker $stamp = (float)microtime(true); $condition = ["`id` = ? AND `next_try` < ?", $queue['id'], DateTimeFormat::utcNow()]; if (DBA::update('workerqueue', ['done' => true], $condition)) { - DI::config()->set('system', 'last_worker_execution', DateTimeFormat::utcNow()); + DI::keyValue()->set('last_worker_execution', DateTimeFormat::utcNow()); } self::$db_duration = (microtime(true) - $stamp); self::$db_duration_write += (microtime(true) - $stamp); @@ -429,7 +429,7 @@ class Worker $stamp = (float)microtime(true); if (DBA::update('workerqueue', ['done' => true], ['id' => $queue['id']])) { - DI::config()->set('system', 'last_worker_execution', DateTimeFormat::utcNow()); + DI::keyValue()->set('last_worker_execution', DateTimeFormat::utcNow()); } self::$db_duration = (microtime(true) - $stamp); self::$db_duration_write += (microtime(true) - $stamp); @@ -1422,7 +1422,7 @@ class Worker $duration = max($start, $end) - min($start, $end); // Quit when the last cron execution had been after the previous window - $last_cron = DI::config()->get('system', 'last_cron_daily'); + $last_cron = DI::keyValue()->get('last_cron_daily'); if ($last_cron + $duration > time()) { Logger::info('The Daily cron had been executed recently', ['last' => date(DateTimeFormat::MYSQL, $last_cron), 'start' => date('H:i:s', $start), 'end' => date('H:i:s', $end)]); return false; diff --git a/src/Core/Worker/Daemon.php b/src/Core/Worker/Daemon.php index 6fd64e4f59..7b4c358f1b 100644 --- a/src/Core/Worker/Daemon.php +++ b/src/Core/Worker/Daemon.php @@ -47,7 +47,7 @@ class Daemon return true; } - $daemon_mode = DI::config()->get('system', 'worker_daemon_mode', false, true); + $daemon_mode = DI::keyValue()->get('worker_daemon_mode') ?? false; if ($daemon_mode) { return $daemon_mode; } @@ -93,11 +93,11 @@ class Daemon } // Check every minute if the daemon is running - if (DI::config()->get('system', 'last_daemon_check', 0) + 60 > time()) { + if ((DI::keyValue()->get('last_daemon_check') ?? 0) + 60 > time()) { return; } - DI::config()->set('system', 'last_daemon_check', time()); + DI::keyValue()->set('last_daemon_check', time()); $pidfile = DI::config()->get('system', 'pidfile'); if (empty($pidfile)) { diff --git a/src/DI.php b/src/DI.php index bf2b5a2371..ecdf92530c 100644 --- a/src/DI.php +++ b/src/DI.php @@ -181,6 +181,11 @@ abstract class DI return self::$dice->create(Core\Config\Capability\IManageConfigValues::class); } + public static function keyValue(): Core\KeyValueStorage\Capabilities\IManageKeyValuePairs + { + return self::$dice->create(Core\KeyValueStorage\Capabilities\IManageKeyValuePairs::class); + } + /** * @return Core\PConfig\Capability\IManagePersonalConfigValues */ diff --git a/src/Database/DBStructure.php b/src/Database/DBStructure.php index cdb5d4ef98..7de6799cfd 100644 --- a/src/Database/DBStructure.php +++ b/src/Database/DBStructure.php @@ -53,7 +53,7 @@ class DBStructure throw new \Asika\SimpleConsole\CommandArgsException('The version number must be numeric'); } - DI::config()->set('system', 'build', $version); + DI::keyValue()->set('build', $version); echo DI::l10n()->t('The database version had been set to %s.', $version); } @@ -65,7 +65,7 @@ class DBStructure */ public static function dropTables(bool $execute) { - $postupdate = DI::config()->get('system', 'post_update_version', PostUpdate::VERSION); + $postupdate = DI::keyValue()->get('post_update_version') ?? PostUpdate::VERSION; if ($postupdate < PostUpdate::VERSION) { echo DI::l10n()->t('The post update is at version %d, it has to be at %d to safely drop the tables.', $postupdate, PostUpdate::VERSION); return; diff --git a/src/Database/PostUpdate.php b/src/Database/PostUpdate.php index e57d92ceb7..d54c3f2217 100644 --- a/src/Database/PostUpdate.php +++ b/src/Database/PostUpdate.php @@ -129,12 +129,12 @@ class PostUpdate private static function update1297() { // Was the script completed? - if (DI::config()->get('system', 'post_update_version') >= 1297) { + if (DI::keyValue()->get('post_update_version') >= 1297) { return true; } if (!DBStructure::existsTable('item-delivery-data')) { - DI::config()->set('system', 'post_update_version', 1297); + DI::keyValue()->set('post_update_version', 1297); return true; } @@ -154,7 +154,7 @@ class PostUpdate Logger::info('Processed rows: ' . DBA::affectedRows()); - DI::config()->set('system', 'post_update_version', 1297); + DI::keyValue()->set('post_update_version', 1297); Logger::info('Done'); @@ -169,7 +169,7 @@ class PostUpdate private static function update1322() { // Was the script completed? - if (DI::config()->get('system', 'post_update_version') >= 1322) { + if (DI::keyValue()->get('post_update_version') >= 1322) { return true; } @@ -188,7 +188,7 @@ class PostUpdate } DBA::close($contact); - DI::config()->set('system', 'post_update_version', 1322); + DI::keyValue()->set('post_update_version', 1322); Logger::info('Done'); @@ -204,16 +204,16 @@ class PostUpdate private static function update1329() { // Was the script completed? - if (DI::config()->get('system', 'post_update_version') >= 1329) { + if (DI::keyValue()->get('post_update_version') >= 1329) { return true; } if (!DBStructure::existsTable('item')) { - DI::config()->set('system', 'post_update_version', 1329); + DI::keyValue()->set('post_update_version', 1329); return true; } - $id = DI::config()->get('system', 'post_update_version_1329_id', 0); + $id = DI::keyValue()->get('post_update_version_1329_id') ?? 0; Logger::info('Start', ['item' => $id]); @@ -237,12 +237,12 @@ class PostUpdate } DBA::close($items); - DI::config()->set('system', 'post_update_version_1329_id', $id); + DI::keyValue()->set('post_update_version_1329_id', $id); Logger::info('Processed', ['rows' => $rows, 'last' => $id]); if ($start_id == $id) { - DI::config()->set('system', 'post_update_version', 1329); + DI::keyValue()->set('post_update_version', 1329); Logger::info('Done'); return true; } @@ -259,16 +259,16 @@ class PostUpdate private static function update1341() { // Was the script completed? - if (DI::config()->get('system', 'post_update_version') >= 1341) { + if (DI::keyValue()->get('post_update_version') >= 1341) { return true; } if (!DBStructure::existsTable('item-content')) { - DI::config()->set('system', 'post_update_version', 1342); + DI::keyValue()->set('post_update_version', 1342); return true; } - $id = DI::config()->get('system', 'post_update_version_1341_id', 0); + $id = DI::keyValue()->get('post_update_version_1341_id') ?? 0; Logger::info('Start', ['item' => $id]); @@ -288,19 +288,19 @@ class PostUpdate $id = $item['uri-id']; ++$rows; if ($rows % 1000 == 0) { - DI::config()->set('system', 'post_update_version_1341_id', $id); + DI::keyValue()->set('post_update_version_1341_id', $id); } } DBA::close($items); - DI::config()->set('system', 'post_update_version_1341_id', $id); + DI::keyValue()->set('post_update_version_1341_id', $id); Logger::info('Processed', ['rows' => $rows, 'last' => $id]); // When there are less than 1,000 items processed this means that we reached the end // The other entries will then be processed with the regular functionality if ($rows < 1000) { - DI::config()->set('system', 'post_update_version', 1341); + DI::keyValue()->set('post_update_version', 1341); Logger::info('Done'); return true; } @@ -317,16 +317,16 @@ class PostUpdate private static function update1342() { // Was the script completed? - if (DI::config()->get('system', 'post_update_version') >= 1342) { + if (DI::keyValue()->get('post_update_version') >= 1342) { return true; } if (!DBStructure::existsTable('term') || !DBStructure::existsTable('item-content')) { - DI::config()->set('system', 'post_update_version', 1342); + DI::keyValue()->set('post_update_version', 1342); return true; } - $id = DI::config()->get('system', 'post_update_version_1342_id', 0); + $id = DI::keyValue()->get('post_update_version_1342_id') ?? 0; Logger::info('Start', ['item' => $id]); @@ -364,19 +364,19 @@ class PostUpdate $id = $term['tid']; ++$rows; if ($rows % 1000 == 0) { - DI::config()->set('system', 'post_update_version_1342_id', $id); + DI::keyValue()->set('post_update_version_1342_id', $id); } } DBA::close($terms); - DI::config()->set('system', 'post_update_version_1342_id', $id); + DI::keyValue()->set('post_update_version_1342_id', $id); Logger::info('Processed', ['rows' => $rows, 'last' => $id]); // When there are less than 1,000 items processed this means that we reached the end // The other entries will then be processed with the regular functionality if ($rows < 1000) { - DI::config()->set('system', 'post_update_version', 1342); + DI::keyValue()->set('post_update_version', 1342); Logger::info('Done'); return true; } @@ -393,16 +393,16 @@ class PostUpdate private static function update1345() { // Was the script completed? - if (DI::config()->get('system', 'post_update_version') >= 1345) { + if (DI::keyValue()->get('post_update_version') >= 1345) { return true; } if (!DBStructure::existsTable('item-delivery-data')) { - DI::config()->set('system', 'post_update_version', 1345); + DI::keyValue()->set('post_update_version', 1345); return true; } - $id = DI::config()->get('system', 'post_update_version_1345_id', 0); + $id = DI::keyValue()->get('post_update_version_1345_id') ?? 0; Logger::info('Start', ['item' => $id]); @@ -427,14 +427,14 @@ class PostUpdate } DBA::close($deliveries); - DI::config()->set('system', 'post_update_version_1345_id', $id); + DI::keyValue()->set('post_update_version_1345_id', $id); Logger::info('Processed', ['rows' => $rows, 'last' => $id]); // When there are less than 100 items processed this means that we reached the end // The other entries will then be processed with the regular functionality if ($rows < 100) { - DI::config()->set('system', 'post_update_version', 1345); + DI::keyValue()->set('post_update_version', 1345); Logger::info('Done'); return true; } @@ -476,16 +476,16 @@ class PostUpdate private static function update1346() { // Was the script completed? - if (DI::config()->get('system', 'post_update_version') >= 1346) { + if (DI::keyValue()->get('post_update_version') >= 1346) { return true; } if (!DBStructure::existsTable('term')) { - DI::config()->set('system', 'post_update_version', 1346); + DI::keyValue()->set('post_update_version', 1346); return true; } - $id = DI::config()->get('system', 'post_update_version_1346_id', 0); + $id = DI::keyValue()->get('post_update_version_1346_id') ?? 0; Logger::info('Start', ['item' => $id]); @@ -514,19 +514,19 @@ class PostUpdate $id = $term['oid']; ++$rows; if ($rows % 100 == 0) { - DI::config()->set('system', 'post_update_version_1346_id', $id); + DI::keyValue()->set('post_update_version_1346_id', $id); } } DBA::close($terms); - DI::config()->set('system', 'post_update_version_1346_id', $id); + DI::keyValue()->set('post_update_version_1346_id', $id); Logger::info('Processed', ['rows' => $rows, 'last' => $id]); // When there are less than 10 items processed this means that we reached the end // The other entries will then be processed with the regular functionality if ($rows < 10) { - DI::config()->set('system', 'post_update_version', 1346); + DI::keyValue()->set('post_update_version', 1346); Logger::info('Done'); return true; } @@ -544,16 +544,16 @@ class PostUpdate private static function update1347() { // Was the script completed? - if (DI::config()->get('system', 'post_update_version') >= 1347) { + if (DI::keyValue()->get('post_update_version') >= 1347) { return true; } if (!DBStructure::existsTable('item-activity') || !DBStructure::existsTable('item')) { - DI::config()->set('system', 'post_update_version', 1347); + DI::keyValue()->set('post_update_version', 1347); return true; } - $id = DI::config()->get('system', 'post_update_version_1347_id', 0); + $id = DI::keyValue()->get('post_update_version_1347_id') ?? 0; Logger::info('Start', ['item' => $id]); @@ -588,12 +588,12 @@ class PostUpdate } DBA::close($items); - DI::config()->set('system', 'post_update_version_1347_id', $id); + DI::keyValue()->set('post_update_version_1347_id', $id); Logger::info('Processed', ['rows' => $rows, 'last' => $id]); if ($start_id == $id) { - DI::config()->set('system', 'post_update_version', 1347); + DI::keyValue()->set('post_update_version', 1347); Logger::info('Done'); return true; } @@ -611,11 +611,11 @@ class PostUpdate private static function update1348() { // Was the script completed? - if (DI::config()->get('system', 'post_update_version') >= 1348) { + if (DI::keyValue()->get('post_update_version') >= 1348) { return true; } - $id = DI::config()->get('system', 'post_update_version_1348_id', 0); + $id = DI::keyValue()->get('post_update_version_1348_id') ?? 0; Logger::info('Start', ['contact' => $id]); @@ -641,12 +641,12 @@ class PostUpdate } DBA::close($contacts); - DI::config()->set('system', 'post_update_version_1348_id', $id); + DI::keyValue()->set('post_update_version_1348_id', $id); Logger::info('Processed', ['rows' => $rows, 'last' => $id]); if ($start_id == $id) { - DI::config()->set('system', 'post_update_version', 1348); + DI::keyValue()->set('post_update_version', 1348); Logger::info('Done'); return true; } @@ -664,11 +664,11 @@ class PostUpdate private static function update1349() { // Was the script completed? - if (DI::config()->get('system', 'post_update_version') >= 1349) { + if (DI::keyValue()->get('post_update_version') >= 1349) { return true; } - $id = DI::config()->get('system', 'post_update_version_1349_id', ''); + $id = DI::keyValue()->get('post_update_version_1349_id') ?? ''; Logger::info('Start', ['apcontact' => $id]); @@ -694,12 +694,12 @@ class PostUpdate } DBA::close($apcontacts); - DI::config()->set('system', 'post_update_version_1349_id', $id); + DI::keyValue()->set('post_update_version_1349_id', $id); Logger::info('Processed', ['rows' => $rows, 'last' => $id]); if ($start_id == $id) { - DI::config()->set('system', 'post_update_version', 1349); + DI::keyValue()->set('post_update_version', 1349); Logger::info('Done'); return true; } @@ -717,7 +717,7 @@ class PostUpdate private static function update1383() { // Was the script completed? - if (DI::config()->get('system', 'post_update_version') >= 1383) { + if (DI::keyValue()->get('post_update_version') >= 1383) { return true; } @@ -743,7 +743,7 @@ class PostUpdate } DBA::close($photos); - DI::config()->set('system', 'post_update_version', 1383); + DI::keyValue()->set('post_update_version', 1383); Logger::info('Done', ['deleted' => $deleted]); return true; } @@ -758,7 +758,7 @@ class PostUpdate private static function update1384() { // Was the script completed? - if (DI::config()->get('system', 'post_update_version') >= 1384) { + if (DI::keyValue()->get('post_update_version') >= 1384) { return true; } @@ -788,7 +788,7 @@ class PostUpdate Logger::info('Processed', ['rows' => $rows]); if ($rows <= 100) { - DI::config()->set('system', 'post_update_version', 1384); + DI::keyValue()->set('post_update_version', 1384); Logger::info('Done'); return true; } @@ -806,12 +806,12 @@ class PostUpdate private static function update1400() { // Was the script completed? - if (DI::config()->get('system', 'post_update_version') >= 1400) { + if (DI::keyValue()->get('post_update_version') >= 1400) { return true; } if (!DBStructure::existsTable('item')) { - DI::config()->set('system', 'post_update_version', 1400); + DI::keyValue()->set('post_update_version', 1400); return true; } @@ -835,7 +835,7 @@ class PostUpdate Logger::info('Processed', ['rows' => $rows]); if ($rows <= 100) { - DI::config()->set('system', 'post_update_version', 1400); + DI::keyValue()->set('post_update_version', 1400); Logger::info('Done'); return true; } @@ -853,7 +853,7 @@ class PostUpdate private static function update1424() { // Was the script completed? - if (DI::config()->get('system', 'post_update_version') >= 1424) { + if (DI::keyValue()->get('post_update_version') >= 1424) { return true; } @@ -877,7 +877,7 @@ class PostUpdate Logger::info('Processed', ['rows' => $rows]); if ($rows <= 100) { - DI::config()->set('system', 'post_update_version', 1424); + DI::keyValue()->set('post_update_version', 1424); Logger::info('Done'); return true; } @@ -895,12 +895,12 @@ class PostUpdate private static function update1425() { // Was the script completed? - if (DI::config()->get('system', 'post_update_version') >= 1425) { + if (DI::keyValue()->get('post_update_version') >= 1425) { return true; } if (!DBStructure::existsTable('fcontact')) { - DI::config()->set('system', 'post_update_version', 1425); + DI::keyValue()->set('post_update_version', 1425); return true; } @@ -929,7 +929,7 @@ class PostUpdate Logger::info('Processed', ['rows' => $rows]); if ($rows <= 100) { - DI::config()->set('system', 'post_update_version', 1425); + DI::keyValue()->set('post_update_version', 1425); Logger::info('Done'); return true; } @@ -947,7 +947,7 @@ class PostUpdate private static function update1426() { // Was the script completed? - if (DI::config()->get('system', 'post_update_version') >= 1426) { + if (DI::keyValue()->get('post_update_version') >= 1426) { return true; } @@ -976,7 +976,7 @@ class PostUpdate Logger::info('Processed', ['rows' => $rows]); if ($rows <= 100) { - DI::config()->set('system', 'post_update_version', 1426); + DI::keyValue()->set('post_update_version', 1426); Logger::info('Done'); return true; } @@ -994,7 +994,7 @@ class PostUpdate private static function update1427() { // Was the script completed? - if (DI::config()->get('system', 'post_update_version') >= 1427) { + if (DI::keyValue()->get('post_update_version') >= 1427) { return true; } @@ -1023,7 +1023,7 @@ class PostUpdate Logger::info('Processed', ['rows' => $rows]); if ($rows <= 100) { - DI::config()->set('system', 'post_update_version', 1427); + DI::keyValue()->set('post_update_version', 1427); Logger::info('Done'); return true; } @@ -1041,16 +1041,16 @@ class PostUpdate private static function update1452() { // Was the script completed? - if (DI::config()->get('system', 'post_update_version') >= 1452) { + if (DI::keyValue()->get('post_update_version') >= 1452) { return true; } if (!DBStructure::existsTable('conversation')) { - DI::config()->set('system', 'post_update_version', 1452); + DI::keyValue()->set('post_update_version', 1452); return true; } - $id = DI::config()->get('system', 'post_update_version_1452_id', 0); + $id = DI::keyValue()->get('post_update_version_1452_id') ?? 0; Logger::info('Start', ['uri-id' => $id]); @@ -1089,12 +1089,12 @@ class PostUpdate DBA::close($conversations); - DI::config()->set('system', 'post_update_version_1452_id', $id); + DI::keyValue()->set('post_update_version_1452_id', $id); Logger::info('Processed', ['rows' => $rows, 'last' => $id, 'last-received' => $received]); if ($rows <= 100) { - DI::config()->set('system', 'post_update_version', 1452); + DI::keyValue()->set('post_update_version', 1452); Logger::info('Done'); return true; } @@ -1113,7 +1113,7 @@ class PostUpdate private static function update1483() { // Was the script completed? - if (DI::config()->get('system', 'post_update_version') >= 1483) { + if (DI::keyValue()->get('post_update_version') >= 1483) { return true; } @@ -1129,7 +1129,7 @@ class PostUpdate } DBA::close($posts); - DI::config()->set('system', 'post_update_version', 1483); + DI::keyValue()->set('post_update_version', 1483); Logger::info('Done'); return true; } @@ -1144,11 +1144,11 @@ class PostUpdate private static function update1484() { // Was the script completed? - if (DI::config()->get('system', 'post_update_version') >= 1484) { + if (DI::keyValue()->get('post_update_version') >= 1484) { return true; } - $id = DI::config()->get('system', 'post_update_version_1484_id', 0); + $id = DI::keyValue()->get('post_update_version_1484_id') ?? 0; Logger::info('Start', ['id' => $id]); @@ -1172,12 +1172,12 @@ class PostUpdate } DBA::close($contacts); - DI::config()->set('system', 'post_update_version_1484_id', $id); + DI::keyValue()->set('post_update_version_1484_id', $id); Logger::info('Processed', ['rows' => $rows, 'last' => $id]); if ($rows <= 100) { - DI::config()->set('system', 'post_update_version', 1484); + DI::keyValue()->set('post_update_version', 1484); Logger::info('Done'); return true; } diff --git a/src/Model/Contact.php b/src/Model/Contact.php index e928df7f63..1bf2f17910 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -624,7 +624,7 @@ class Contact public static function getPublicAndUserContactID(int $cid, int $uid): array { // We have to use the legacy function as long as the post update hasn't finished - if (DI::config()->get('system', 'post_update_version') < 1427) { + if (DI::keyValue()->get('post_update_version') < 1427) { return self::legacyGetPublicAndUserContactID($cid, $uid); } @@ -2953,7 +2953,7 @@ class Contact } if (($network != '') && ($ret['network'] != $network)) { - Logger::notice('Expected network ' . $network . ' does not match actual network ' . $ret['network']); + $result['message'] = DI::l10n()->t('Expected network %s does not match actual network %s', $network, $ret['network']); return $result; } diff --git a/src/Model/GServer.php b/src/Model/GServer.php index b0a9dd5c9a..6945fab3e0 100644 --- a/src/Model/GServer.php +++ b/src/Model/GServer.php @@ -2145,7 +2145,7 @@ class GServer */ private static function discoverFederation() { - $last = DI::config()->get('poco', 'last_federation_discovery'); + $last = DI::keyValue()->get('poco_last_federation_discovery'); if ($last) { $next = $last + (24 * 60 * 60); @@ -2189,7 +2189,7 @@ class GServer } } - DI::config()->set('poco', 'last_federation_discovery', time()); + DI::keyValue()->set('poco_last_federation_discovery', time()); } /** diff --git a/src/Model/Item.php b/src/Model/Item.php index bb4400a860..753b3d6dac 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -3016,6 +3016,8 @@ class Item $item['hashtags'] = $tags['hashtags']; $item['mentions'] = $tags['mentions']; + $item['body'] = preg_replace("#\s*\[attachment .*?].*?\[/attachment]\s*#ism", "\n", $item['body']); + if (!$is_preview) { $item['body'] = Post\Media::removeFromEndOfBody($item['body'] ?? ''); } @@ -3065,8 +3067,6 @@ class Item $attachments = Post\Media::splitAttachments($item['uri-id'], $shared_links, $item['has-media'] ?? false); $item['body'] = self::replaceVisualAttachments($attachments, $item['body'] ?? ''); - $item['body'] = preg_replace("/\s*\[attachment .*?\].*?\[\/attachment\]\s*/ism", "\n", $item['body']); - self::putInCache($item); $item['body'] = $body; $s = $item["rendered-html"]; @@ -3166,7 +3166,7 @@ class Item ], ]); } - + /** * Check if the body contains a link diff --git a/src/Module/Admin/DBSync.php b/src/Module/Admin/DBSync.php index bb1fa90330..70d835fcd3 100644 --- a/src/Module/Admin/DBSync.php +++ b/src/Module/Admin/DBSync.php @@ -42,7 +42,7 @@ class DBSync extends BaseAdmin switch ($action) { case 'mark': if ($update) { - DI::config()->set('database', 'update_' . $update, 'success'); + DI::keyValue()->set('database_update_' . $update, 'success'); $curr = DI::config()->get('system', 'build'); if (intval($curr) == $update) { DI::config()->set('system', 'build', intval($curr) + 1); @@ -76,13 +76,13 @@ class DBSync extends BaseAdmin $o = DI::l10n()->t("Executing %s failed with error: %s", $func, $retval); } elseif ($retval === Update::SUCCESS) { $o = DI::l10n()->t('Update %s was successfully applied.', $func); - DI::config()->set('database', $func, 'success'); + DI::keyValue()->set(sprintf('database_%s', $func), 'success'); } else { $o = DI::l10n()->t('Update %s did not return a status. Unknown if it succeeded.', $func); } } else { $o = DI::l10n()->t('There was no additional update function %s that needed to be called.', $func) . "
"; - DI::config()->set('database', $func, 'success'); + DI::keyValue()->set(sprintf('database_%s', $func), 'success'); } return $o; diff --git a/src/Module/Admin/Summary.php b/src/Module/Admin/Summary.php index d27a9b011b..46f9d440bd 100644 --- a/src/Module/Admin/Summary.php +++ b/src/Module/Admin/Summary.php @@ -98,7 +98,7 @@ class Summary extends BaseAdmin $warningtext[] = DI::l10n()->t('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.)'); } - $last_worker_call = DI::config()->get('system', 'last_worker_execution', false); + $last_worker_call = DI::keyValue()->get('last_worker_execution'); if (!$last_worker_call) { $warningtext[] = DI::l10n()->t('The worker was never executed. Please check your database structure!'); } elseif ((strtotime(DateTimeFormat::utcNow()) - strtotime($last_worker_call)) > 60 * 60) { diff --git a/src/Module/Friendica.php b/src/Module/Friendica.php index 37bd69da49..f21b85fc45 100644 --- a/src/Module/Friendica.php +++ b/src/Module/Friendica.php @@ -42,6 +42,7 @@ class Friendica extends BaseModule protected function content(array $request = []): string { $config = DI::config(); + $keyValue = DI::keyValue(); $visibleAddonList = Addon::getVisibleList(); if (!empty($visibleAddonList)) { @@ -100,7 +101,7 @@ class Friendica extends BaseModule '' . App::VERSION . '', DI::baseUrl()->get(), '' . $config->get('system', 'build') . '/' . DB_UPDATE_VERSION . '', - '' . $config->get('system', 'post_update_version') . '/' . PostUpdate::VERSION . ''), + '' . $keyValue->get('post_update_version') . '/' . PostUpdate::VERSION . ''), 'friendica' => DI::l10n()->t('Please visit Friendi.ca to learn more about the Friendica project.'), 'bugs' => DI::l10n()->t('Bug reports and issues: please visit') . ' ' . '' . DI::l10n()->t('the bugtracker at github') . '', 'info' => DI::l10n()->t('Suggestions, praise, etc. - please email "info" at "friendi - dot - ca'), diff --git a/src/Network/HTTPClient/Client/HttpClient.php b/src/Network/HTTPClient/Client/HttpClient.php index 32a1a22fc2..76af184975 100644 --- a/src/Network/HTTPClient/Client/HttpClient.php +++ b/src/Network/HTTPClient/Client/HttpClient.php @@ -69,7 +69,7 @@ class HttpClient implements ICanSendHttpRequests $this->logger->debug('Request start.', ['url' => $url, 'method' => $method]); $host = parse_url($url, PHP_URL_HOST); - if(!filter_var($host, FILTER_VALIDATE_IP) && !@dns_get_record($host . '.', DNS_A + DNS_AAAA)) { + if(!filter_var($host, FILTER_VALIDATE_IP) && !@dns_get_record($host . '.', DNS_A + DNS_AAAA) && !gethostbyname($host)) { $this->logger->debug('URL cannot be resolved.', ['url' => $url, 'callstack' => System::callstack(20)]); $this->profiler->stopRecording(); return CurlResult::createErrorCurl($url); diff --git a/src/Worker/Cron.php b/src/Worker/Cron.php index 94f002805b..055a9b4354 100644 --- a/src/Worker/Cron.php +++ b/src/Worker/Cron.php @@ -37,7 +37,7 @@ class Cron { $a = DI::app(); - $last = DI::config()->get('system', 'last_cron'); + $last = DI::keyValue()->get('last_cron'); $poll_interval = intval(DI::config()->get('system', 'cron_interval')); @@ -84,7 +84,7 @@ class Cron Worker::add(Worker::PRIORITY_LOW, 'PostUpdate'); // Hourly cron calls - if (DI::config()->get('system', 'last_cron_hourly', 0) + 3600 < time()) { + if ((DI::keyValue()->get('last_cron_hourly') ?? 0) + 3600 < time()) { // Update trending tags cache for the community page @@ -105,7 +105,7 @@ class Cron // Clear cache entries Worker::add(Worker::PRIORITY_LOW, 'ClearCache'); - DI::config()->set('system', 'last_cron_hourly', time()); + DI::keyValue()->set('last_cron_hourly', time()); } // Daily maintenance cron calls @@ -145,12 +145,12 @@ class Cron // Resubscribe to relay servers Relay::reSubscribe(); - DI::config()->set('system', 'last_cron_daily', time()); + DI::keyValue()->set('last_cron_daily', time()); } Logger::notice('end'); - DI::config()->set('system', 'last_cron', time()); + DI::keyValue()->set('last_cron', time()); } /** diff --git a/src/Worker/PullDirectory.php b/src/Worker/PullDirectory.php index 8a22e504c0..d174d11f3e 100644 --- a/src/Worker/PullDirectory.php +++ b/src/Worker/PullDirectory.php @@ -45,7 +45,7 @@ class PullDirectory return; } - $now = (int)DI::config()->get('system', 'last-directory-sync', 0); + $now = (int)(DI::keyValue()->get('last-directory-sync') ?? 0); Logger::info('Synchronization started.', ['now' => $now, 'directory' => $directory]); @@ -64,7 +64,7 @@ class PullDirectory $result = Contact::addByUrls($contacts['results']); $now = $contacts['now'] ?? 0; - DI::config()->set('system', 'last-directory-sync', $now); + DI::keyValue()->set('last-directory-sync', $now); Logger::info('Synchronization ended', ['now' => $now, 'count' => $result['count'], 'added' => $result['added'], 'updated' => $result['updated'], 'unchanged' => $result['unchanged'], 'directory' => $directory]); } diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index 1d573fa87e..25e416d508 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -55,7 +55,7 @@ use Friendica\Database\DBA; if (!defined('DB_UPDATE_VERSION')) { - define('DB_UPDATE_VERSION', 1504); + define('DB_UPDATE_VERSION', 1505); } return [ @@ -889,6 +889,17 @@ return [ "uid" => ["uid"], ] ], + "key-value" => [ + "comment" => "A key value storage", + "fields" => [ + "k" => ["type" => "varbinary(50)", "not null" => "1", "primary" => "1", "comment" => ""], + "v" => ["type" => "mediumtext", "comment" => ""], + "updated_at" => ["type" => "int unsigned", "not null" => "1", "comment" => "timestamp of the last update"], + ], + "indexes" => [ + "PRIMARY" => ["k"], + ], + ], "locks" => [ "comment" => "", "fields" => [ diff --git a/static/dependencies.config.php b/static/dependencies.config.php index a4c52e0043..116874445b 100644 --- a/static/dependencies.config.php +++ b/static/dependencies.config.php @@ -245,6 +245,9 @@ return [ ['getBackend', [], Dice::CHAIN_CALL], ], ], + \Friendica\Core\KeyValueStorage\Capabilities\IManageKeyValuePairs::class => [ + 'instanceOf' => \Friendica\Core\KeyValueStorage\Type\DBKeyValueStorage::class, + ], Network\HTTPClient\Capability\ICanSendHttpRequests::class => [ 'instanceOf' => Network\HTTPClient\Factory\HttpClient::class, 'call' => [ diff --git a/tests/src/Core/KeyValueStorage/DBKeyValueStorageTest.php b/tests/src/Core/KeyValueStorage/DBKeyValueStorageTest.php new file mode 100644 index 0000000000..1492c3de51 --- /dev/null +++ b/tests/src/Core/KeyValueStorage/DBKeyValueStorageTest.php @@ -0,0 +1,96 @@ +. + * + */ + +namespace Friendica\Test\src\Core\KeyValueStorage; + +use Friendica\Core\Config\ValueObject\Cache; +use Friendica\Core\KeyValueStorage\Capabilities\IManageKeyValuePairs; +use Friendica\Core\KeyValueStorage\Type\DBKeyValueStorage; +use Friendica\Database\Database; +use Friendica\Database\Definition\DbaDefinition; +use Friendica\Database\Definition\ViewDefinition; +use Friendica\Test\DatabaseTestTrait; +use Friendica\Test\Util\Database\StaticDatabase; +use Friendica\Util\BasePath; +use Friendica\Util\Profiler; + +class DBKeyValueStorageTest extends KeyValueStorageTest +{ + use DatabaseTestTrait; + + /** @var Database */ + protected $database; + + protected function setUp(): void + { + parent::setUp(); + + $this->setUpDb(); + } + + protected function tearDown(): void + { + parent::tearDown(); + + $this->tearDownDb(); + } + + public function getInstance(): IManageKeyValuePairs + { + $cache = new Cache(); + $cache->set('database', 'disable_pdo', true); + + $basePath = new BasePath(dirname(__FILE__, 5), $_SERVER); + + $this->database = new StaticDatabase($cache, new Profiler($cache), (new DbaDefinition($basePath->getPath()))->load(), (new ViewDefinition($basePath->getPath()))->load()); + $this->database->setTestmode(true); + + return new DBKeyValueStorage($this->database); + } + + /** @dataProvider dataTests */ + public function testUpdatedAt($k, $v) + { + $instance = $this->getInstance(); + + $instance->set($k, $v); + + self::assertEquals($v, $instance->get($k)); + self::assertEquals($v, $instance[$k]); + + $entry = $this->database->selectFirst(DBKeyValueStorage::DB_KEY_VALUE_TABLE, ['updated_at'], ['k' => $k]); + self::assertNotEmpty($entry); + + $updateAt = $entry['updated_at']; + + $instance->set($k, 'another_value'); + + self::assertEquals('another_value', $instance->get($k)); + self::assertEquals('another_value', $instance[$k]); + + $entry = $this->database->selectFirst(DBKeyValueStorage::DB_KEY_VALUE_TABLE, ['updated_at'], ['k' => $k]); + self::assertNotEmpty($entry); + + $updateAtAfter = $entry['updated_at']; + + self::assertLessThanOrEqual($updateAt, $updateAtAfter); + } +} diff --git a/tests/src/Core/KeyValueStorage/KeyValueStorageTest.php b/tests/src/Core/KeyValueStorage/KeyValueStorageTest.php new file mode 100644 index 0000000000..b3aee20f59 --- /dev/null +++ b/tests/src/Core/KeyValueStorage/KeyValueStorageTest.php @@ -0,0 +1,105 @@ +. + * + */ + +namespace Friendica\Test\src\Core\KeyValueStorage; + +use Friendica\Core\KeyValueStorage\Capabilities\IManageKeyValuePairs; +use Friendica\Test\MockedTest; + +abstract class KeyValueStorageTest extends MockedTest +{ + abstract public function getInstance(): IManageKeyValuePairs; + + public function testInstance() + { + $instance = $this->getInstance(); + + self::assertInstanceOf(IManageKeyValuePairs::class, $instance); + } + + public function dataTests(): array + { + return [ + 'string' => ['k' => 'data', 'v' => 'it'], + 'boolTrue' => ['k' => 'data', 'v' => true], + 'boolFalse' => ['k' => 'data', 'v' => false], + 'integer' => ['k' => 'data', 'v' => 235], + 'decimal' => ['k' => 'data', 'v' => 2.456], + 'array' => ['k' => 'data', 'v' => ['1', 2, '3', true, false]], + 'boolIntTrue' => ['k' => 'data', 'v' => 1], + 'boolIntFalse' => ['k' => 'data', 'v' => 0], + ]; + } + + /** + * @dataProvider dataTests + */ + public function testGetSetDelete($k, $v) + { + $instance = $this->getInstance(); + + $instance->set($k, $v); + + self::assertEquals($v, $instance->get($k)); + self::assertEquals($v, $instance[$k]); + + $instance->delete($k); + + self::assertNull($instance->get($k)); + self::assertNull($instance[$k]); + } + + /** + * @dataProvider dataTests + */ + public function testSetOverride($k, $v) + { + $instance = $this->getInstance(); + + $instance->set($k, $v); + + self::assertEquals($v, $instance->get($k)); + self::assertEquals($v, $instance[$k]); + + $instance->set($k, 'another_value'); + + self::assertEquals('another_value', $instance->get($k)); + self::assertEquals('another_value', $instance[$k]); + } + + /** + * @dataProvider dataTests + */ + public function testOffsetSetDelete($k, $v) + { + $instance = $this->getInstance(); + + $instance[$k] = $v; + + self::assertEquals($v, $instance->get($k)); + self::assertEquals($v, $instance[$k]); + + unset($instance[$k]); + + self::assertNull($instance->get($k)); + self::assertNull($instance[$k]); + } +} diff --git a/tests/src/Core/Lock/DatabaseLockDriverTest.php b/tests/src/Core/Lock/DatabaseLockDriverTest.php index bd4cb9cc9b..70c5f37643 100644 --- a/tests/src/Core/Lock/DatabaseLockDriverTest.php +++ b/tests/src/Core/Lock/DatabaseLockDriverTest.php @@ -21,15 +21,16 @@ namespace Friendica\Test\src\Core\Lock; +use Friendica\Core\Config\ValueObject\Cache; use Friendica\Core\Lock\Type\DatabaseLock; -use Friendica\Core\Config\Factory\Config; -use Friendica\DI; +use Friendica\Database\Database; +use Friendica\Database\Definition\DbaDefinition; +use Friendica\Database\Definition\ViewDefinition; use Friendica\Test\DatabaseTestTrait; use Friendica\Test\Util\Database\StaticDatabase; use Friendica\Test\Util\VFSTrait; +use Friendica\Util\BasePath; use Friendica\Util\Profiler; -use Mockery; -use Psr\Log\NullLogger; class DatabaseLockDriverTest extends LockTest { @@ -38,6 +39,9 @@ class DatabaseLockDriverTest extends LockTest protected $pid = 123; + /** @var Database */ + protected $database; + protected function setUp(): void { $this->setUpVfsDir(); @@ -49,7 +53,15 @@ class DatabaseLockDriverTest extends LockTest protected function getInstance() { - return new DatabaseLock(DI::dba(), $this->pid); + $cache = new Cache(); + $cache->set('database', 'disable_pdo', true); + + $basePath = new BasePath(dirname(__FILE__, 5), $_SERVER); + + $this->database = new StaticDatabase($cache, new Profiler($cache), (new DbaDefinition($basePath->getPath()))->load(), (new ViewDefinition($basePath->getPath()))->load()); + $this->database->setTestmode(true); + + return new DatabaseLock($this->database, $this->pid); } protected function tearDown(): void diff --git a/update.php b/update.php index d963546e4b..f8697554f5 100644 --- a/update.php +++ b/update.php @@ -982,7 +982,7 @@ function update_1429() return Update::FAILED; } - DI::config()->set('system', 'post_update_version', 1423); + DI::keyValue()->set('post_update_version', 1423); return Update::SUCCESS; } @@ -1145,3 +1145,33 @@ function update_1502() DBA::e("UPDATE `pconfig` SET `cat` = 'calendar' WHERE `k` = 'first_day_of_week'"); return Update::SUCCESS; } + +function update_1505() +{ + $conditions = [ + "((`cat` = ?) AND ((`k` LIKE ?) OR (`k` = ?) OR (`k` LIKE ?) OR (`k` = ?))) OR " . + "((`cat` != ?) AND (`k` LIKE ?)) OR " . + "((`cat` = ?) AND (`k` LIKE ?))", + "system", + "post_update_%", + "worker_last_cleaned", + "last%", + "worker_daemon_mode", + "system", + "last_%", + "database", + "update_%", + ]; + + $postUpdateEntries = DBA::selectToArray('config', ['cat', 'k', 'v'], $conditions); + + foreach ($postUpdateEntries as $postUpdateEntry) { + if ($postUpdateEntry['cat'] === 'system') { + DI::keyValue()->set($postUpdateEntry['k'], $postUpdateEntry['v']); + } else { + DI::keyValue()->set(sprintf('%s_%s', $postUpdateEntry['cat'], $postUpdateEntry['k']), $postUpdateEntry['v']); + } + } + + return DBA::delete('config', $conditions) ? Update::SUCCESS : Update::FAILED; +} diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index b8748488f2..1872ad586d 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 2023.03-dev\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-12-30 21:30+0000\n" +"POT-Creation-Date: 2022-12-29 20:29+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -2898,6 +2898,11 @@ msgid "" "credentials in your Settings -> Social Networks page." msgstr "" +#: src/Model/Contact.php:2956 +#, php-format +msgid "Expected network %s does not match actual network %s" +msgstr "" + #: src/Model/Contact.php:2973 msgid "The profile address specified does not provide adequate information." msgstr "" diff --git a/view/lang/ja/messages.po b/view/lang/ja/messages.po index 2b3ecfe4ed..d98e4d959e 100644 --- a/view/lang/ja/messages.po +++ b/view/lang/ja/messages.po @@ -3030,7 +3030,7 @@ msgstr "フォロワー" #: src/BaseModule.php:219 src/Content/Widget.php:239 #: src/Module/Contact.php:861 msgid "Following" -msgstr "以下" +msgstr "フォロー中" #: src/BaseModule.php:224 src/Content/Widget.php:240 #: src/Module/Contact.php:862 @@ -3810,7 +3810,7 @@ msgstr "" #: src/Content/Widget/CalendarExport.php:54 msgid "Export" -msgstr "輸出する" +msgstr "エクスポート" #: src/Content/Widget/CalendarExport.php:55 msgid "Export calendar as ical" diff --git a/view/lang/ja/strings.php b/view/lang/ja/strings.php index 454b3bbf5d..a1d2803e12 100644 --- a/view/lang/ja/strings.php +++ b/view/lang/ja/strings.php @@ -675,7 +675,7 @@ $a->strings['Page not found.'] = 'ページが見つかりません。'; $a->strings['The form security token was not correct. This probably happened because the form has been opened for too long (>3 hours) before submitting it.'] = 'フォームセキュリティトークンが正しくありませんでした。これは、フォームを送信する前にフォームが長時間(3時間以上)開かれたために発生した可能性があります。'; $a->strings['All contacts'] = 'すべてのコンタクト'; $a->strings['Followers'] = 'フォロワー'; -$a->strings['Following'] = '以下'; +$a->strings['Following'] = 'フォロー中'; $a->strings['Mutual friends'] = '共通の友人'; $a->strings['Could not find any unarchived contact entry for this URL (%s)'] = 'このURL( %s )のアーカイブされていないコンタクトエントリが見つかりませんでした'; $a->strings['The contact entries have been archived'] = 'コンタクトエントリがアーカイブされました'; @@ -837,7 +837,7 @@ $a->strings['%d contact in common'] = [ ]; $a->strings['Archives'] = 'アーカイブ'; $a->strings['News'] = 'ニュース'; -$a->strings['Export'] = '輸出する'; +$a->strings['Export'] = 'エクスポート'; $a->strings['Export calendar as ical'] = 'カレンダーをicalとしてエクスポート'; $a->strings['Export calendar as csv'] = 'カレンダーをcsvとしてエクスポート'; $a->strings['No contacts'] = 'コンタクトなし'; diff --git a/view/theme/frio/templates/mail_list.tpl b/view/theme/frio/templates/mail_list.tpl index bfc21aabaf..264c689c90 100644 --- a/view/theme/frio/templates/mail_list.tpl +++ b/view/theme/frio/templates/mail_list.tpl @@ -11,7 +11,15 @@
{{$ago}}
-

{{$from_name}}

+

+ {{if !$seen}} + + {{/if}} + {{$from_name}} + {{if !$seen}} + + {{/if}} +

+ +