Merge pull request #12605 from nupplaphil/feat/addons_load

Move table `addons` into `node.config.php`
This commit is contained in:
Hypolite Petovan 2023-01-04 17:13:52 -05:00 committed by GitHub
commit 92301c6464
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 317 additions and 43 deletions

View file

@ -1,6 +1,6 @@
-- ------------------------------------------
-- Friendica 2023.03-dev (Giant Rhubarb)
-- DB_UPDATE_VERSION 1508
-- DB_UPDATE_VERSION 1509
-- ------------------------------------------

View file

@ -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;

View file

@ -47,8 +47,8 @@ interface IManageConfigValues
*
* Get a particular config value from the given category ($cat)
*
* @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
*
* @return mixed Stored value or null if it does not exist
@ -56,7 +56,7 @@ interface IManageConfigValues
* @throws ConfigPersistenceException In case the persistence layer throws errors
*
*/
public function get(string $cat, string $key, $default_value = null);
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

View file

@ -102,7 +102,7 @@ class Config implements IManageConfigValues
}
/** {@inheritDoc} */
public function get(string $cat, string $key, $default_value = null)
public function get(string $cat, string $key = null, $default_value = null)
{
return $this->configCache->get($cat, $key) ?? $default_value;
}

View file

@ -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";
}

View file

@ -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', 'config'];
'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']);

View file

@ -55,7 +55,7 @@
use Friendica\Database\DBA;
if (!defined('DB_UPDATE_VERSION')) {
define('DB_UPDATE_VERSION', 1508);
define('DB_UPDATE_VERSION', 1509);
}
return [

View file

@ -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,

View file

@ -410,4 +410,133 @@ class CacheTest extends MockedTest
// the newCache entry wasn't set, because we Diff
self::assertNull($mergedCache->get('system', 'test_3'));
}
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));
}
}

View file

@ -403,4 +403,133 @@ 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));
}
}

View file

@ -1192,5 +1192,23 @@ function update_1508()
$newConfig->commit();
DBA::e("TRUNCATE TABLE `config`");
return DBA::e("TRUNCATE TABLE `config`") ? Update::SUCCESS : Update::FAILED;
}
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 DBA::e("TRUNCATE TABLE `addon`") ? Update::SUCCESS : Update::FAILED;
}