diff --git a/mod/photos.php b/mod/photos.php index c2831270ab..1294406761 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -11,7 +11,6 @@ use Friendica\Content\Nav; use Friendica\Content\Pager; use Friendica\Content\Text\BBCode; use Friendica\Core\ACL; -use Friendica\Core\Addon; use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\Core\System; @@ -1067,6 +1066,7 @@ function photos_content() $cmnt_tpl = Renderer::getMarkupTemplate('comment_item.tpl'); $tpl = Renderer::getMarkupTemplate('photo_item.tpl'); $return_path = DI::args()->getCommand(); + $addonHelper = DI::addonHelper(); if (!DBA::isResult($items)) { if (($can_post || Security::canWriteToUserWall($owner_uid))) { @@ -1075,7 +1075,7 @@ function photos_content() * This should be better if done by a hook */ $qcomment = null; - if (Addon::isEnabled('qcomment')) { + if ($addonHelper->isAddonEnabled('qcomment')) { $words = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'qcomment', 'words'); $qcomment = $words ? explode("\n", $words) : []; } @@ -1131,7 +1131,7 @@ function photos_content() * This should be better if done by a hook */ $qcomment = null; - if (Addon::isEnabled('qcomment')) { + if ($addonHelper->isAddonEnabled('qcomment')) { $words = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'qcomment', 'words'); $qcomment = $words ? explode("\n", $words) : []; } @@ -1211,7 +1211,7 @@ function photos_content() * This should be better if done by a hook */ $qcomment = null; - if (Addon::isEnabled('qcomment')) { + if ($addonHelper->isAddonEnabled('qcomment')) { $words = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'qcomment', 'words'); $qcomment = $words ? explode("\n", $words) : []; } diff --git a/src/App.php b/src/App.php index 7f8e03b5e8..d42f63436c 100644 --- a/src/App.php +++ b/src/App.php @@ -17,6 +17,7 @@ use Friendica\App\Router; use Friendica\Capabilities\ICanCreateResponses; use Friendica\Capabilities\ICanHandleRequests; use Friendica\Content\Nav; +use Friendica\Core\Addon\AddonHelper; use Friendica\Core\Addon\Capability\ICanLoadAddons; use Friendica\Core\Config\Factory\Config; use Friendica\Core\Container; @@ -171,6 +172,8 @@ class App $this->session = $this->container->create(IHandleUserSessions::class); $this->appHelper = $this->container->create(AppHelper::class); + $addonHelper = $this->container->create(AddonHelper::class); + $this->load( $request->getServerParams(), $this->container->create(DbaDefinition::class), @@ -180,6 +183,7 @@ class App $this->profiler, $this->container->create(EventDispatcherInterface::class), $this->appHelper, + $addonHelper, ); $this->registerTemplateEngine(); @@ -189,6 +193,7 @@ class App $this->container->create(IManagePersonalConfigValues::class), $this->container->create(Page::class), $this->container->create(Nav::class), + $addonHelper, $this->container->create(ModuleHTTPException::class), $start_time, $request @@ -221,6 +226,7 @@ class App $this->container->create(Profiler::class), $this->container->create(EventDispatcherInterface::class), $this->container->create(AppHelper::class), + $this->container->create(AddonHelper::class), ); $this->registerTemplateEngine(); @@ -252,6 +258,7 @@ class App $this->container->create(Profiler::class), $this->container->create(EventDispatcherInterface::class), $this->container->create(AppHelper::class), + $this->container->create(AddonHelper::class), ); /** @var BasePath */ @@ -341,7 +348,8 @@ class App IManageConfigValues $config, Profiler $profiler, EventDispatcherInterface $eventDispatcher, - AppHelper $appHelper + AppHelper $appHelper, + AddonHelper $addonHelper ): void { if ($config->get('system', 'ini_max_execution_time') !== false) { set_time_limit((int) $config->get('system', 'ini_max_execution_time')); @@ -363,7 +371,7 @@ class App if ($mode->has(Mode::DBAVAILABLE)) { Core\Hook::loadHooks(); - $loader = (new Config())->createConfigFileManager($appHelper->getBasePath(), $serverParams); + $loader = (new Config())->createConfigFileManager($appHelper->getBasePath(), $addonHelper->getAddonPath(), $serverParams); $eventDispatcher->dispatch(new ConfigLoadedEvent(ConfigLoadedEvent::CONFIG_LOADED, $loader)); @@ -415,6 +423,7 @@ class App IManagePersonalConfigValues $pconfig, Page $page, Nav $nav, + AddonHelper $addonHelper, ModuleHTTPException $httpException, float $start_time, ServerRequestInterface $request @@ -503,12 +512,12 @@ class App // but we need "view" module for stylesheet if ($this->mode->isInstall() && $moduleName !== 'install') { $this->baseURL->redirect('install'); - } else { - Core\Update::check($this->appHelper->getBasePath(), false); - Core\Addon::loadAddons(); - Core\Hook::loadHooks(); } + Core\Update::check($this->appHelper->getBasePath(), false); + $addonHelper->loadAddons(); + Core\Hook::loadHooks(); + // Compatibility with Hubzilla if ($moduleName == 'rpost') { $this->baseURL->redirect('compose'); diff --git a/src/App/Router.php b/src/App/Router.php index deb0155cf0..c5abd56c5c 100644 --- a/src/App/Router.php +++ b/src/App/Router.php @@ -7,13 +7,11 @@ namespace Friendica\App; -use Dice\Dice; use FastRoute\DataGenerator\GroupCountBased; use FastRoute\Dispatcher; use FastRoute\RouteCollector; use FastRoute\RouteParser\Std; -use Friendica\Capabilities\ICanHandleRequests; -use Friendica\Core\Addon; +use Friendica\Core\Addon\AddonHelper; use Friendica\Core\Cache\Enum\Duration; use Friendica\Core\Cache\Capability\ICanCache; use Friendica\Core\Config\Capability\IManageConfigValues; @@ -86,6 +84,8 @@ class Router /** @var LoggerInterface */ private $logger; + private AddonHelper $addonHelper; + /** @var bool */ private $isLocalUser; @@ -110,17 +110,18 @@ class Router * @param IHandleUserSessions $userSession * @param RouteCollector|null $routeCollector */ - public function __construct(array $server, string $baseRoutesFilepath, L10n $l10n, ICanCache $cache, ICanLock $lock, IManageConfigValues $config, Arguments $args, LoggerInterface $logger, IHandleUserSessions $userSession, RouteCollector $routeCollector = null) + public function __construct(array $server, string $baseRoutesFilepath, L10n $l10n, ICanCache $cache, ICanLock $lock, IManageConfigValues $config, Arguments $args, LoggerInterface $logger, AddonHelper $addonHelper, IHandleUserSessions $userSession, RouteCollector $routeCollector = null) { - $this->baseRoutesFilepath = $baseRoutesFilepath; - $this->l10n = $l10n; - $this->cache = $cache; - $this->lock = $lock; - $this->args = $args; - $this->config = $config; - $this->server = $server; - $this->logger = $logger; - $this->isLocalUser = !empty($userSession->getLocalUserId()); + $this->baseRoutesFilepath = $baseRoutesFilepath; + $this->l10n = $l10n; + $this->cache = $cache; + $this->lock = $lock; + $this->args = $args; + $this->config = $config; + $this->server = $server; + $this->logger = $logger; + $this->addonHelper = $addonHelper; + $this->isLocalUser = !empty($userSession->getLocalUserId()); $this->routeCollector = $routeCollector ?? new RouteCollector(new Std(), new GroupCountBased()); @@ -275,14 +276,14 @@ class Router try { // Check if the HTTP method is OPTIONS and return the special Options Module with the possible HTTP methods if ($this->args->getMethod() === static::OPTIONS) { - $this->moduleClass = Options::class; + $this->moduleClass = Options::class; $this->parameters[] = ['AllowedMethods' => $dispatcher->getOptions($cmd)]; } else { $routeInfo = $dispatcher->dispatch($this->args->getMethod(), $cmd); if ($routeInfo[0] === Dispatcher::FOUND) { - $this->moduleClass = $routeInfo[1]; + $this->moduleClass = $routeInfo[1]; $this->parameters[] = $routeInfo[2]; - } else if ($routeInfo[0] === Dispatcher::METHOD_NOT_ALLOWED) { + } elseif ($routeInfo[0] === Dispatcher::METHOD_NOT_ALLOWED) { throw new HTTPException\MethodNotAllowedException($this->l10n->t('Method not allowed for this module. Allowed method(s): %s', implode(', ', $routeInfo[1]))); } else { throw new HTTPException\NotFoundException($this->l10n->t('Page not found.')); @@ -293,7 +294,7 @@ class Router } catch (NotFoundException $e) { $moduleName = $this->args->getModuleName(); // Then we try addon-provided modules that we wrap in the LegacyModule class - if (Addon::isEnabled($moduleName) && file_exists("addon/{$moduleName}/{$moduleName}.php")) { + if ($this->addonHelper->isAddonEnabled($moduleName) && file_exists("addon/{$moduleName}/{$moduleName}.php")) { //Check if module is an app and if public access to apps is allowed or not $privateapps = $this->config->get('config', 'private_addons', false); if (!$this->isLocalUser && Hook::isAddonApp($moduleName) && $privateapps) { diff --git a/src/Console/Addon.php b/src/Console/Addon.php index e4bdeb052b..c279ef2976 100644 --- a/src/Console/Addon.php +++ b/src/Console/Addon.php @@ -10,7 +10,7 @@ namespace Friendica\Console; use Console_Table; use Friendica\App\Mode; use Friendica\Core\L10n; -use Friendica\Core\Addon as AddonCore; +use Friendica\Core\Addon\AddonHelper; use Friendica\Database\Database; use Friendica\Util\Strings; use RuntimeException; @@ -34,6 +34,7 @@ class Addon extends \Asika\SimpleConsole\Console * @var Database */ private $dba; + private AddonHelper $addonHelper; protected function getHelp() { @@ -56,15 +57,16 @@ HELP; return $help; } - public function __construct(Mode $appMode, L10n $l10n, Database $dba, array $argv = null) + public function __construct(Mode $appMode, L10n $l10n, Database $dba, AddonHelper $addonHelper, array $argv = null) { parent::__construct($argv); - $this->appMode = $appMode; - $this->l10n = $l10n; - $this->dba = $dba; + $this->appMode = $appMode; + $this->l10n = $l10n; + $this->dba = $dba; + $this->addonHelper = $addonHelper; - AddonCore::loadAddons(); + $this->addonHelper->loadAddons(); } protected function doExecute(): int @@ -122,23 +124,22 @@ HELP; return false; } - foreach (AddonCore::getAvailableList() as $addon) { - $addon_name = $addon[0]; - $enabled = AddonCore::isEnabled($addon_name); + foreach ($this->addonHelper->getAvailableAddons() as $addonId) { + $enabled = $this->addonHelper->isAddonEnabled($addonId); if ($subCmd === 'all') { - $table->addRow([$addon_name, $enabled ? 'enabled' : 'disabled']); + $table->addRow([$addonId, $enabled ? 'enabled' : 'disabled']); continue; } if ($subCmd === 'enabled' && $enabled === true) { - $table->addRow([$addon_name]); + $table->addRow([$addonId]); continue; } if ($subCmd === 'disabled' && $enabled === false) { - $table->addRow([$addon_name]); + $table->addRow([$addonId]); continue; } } @@ -163,11 +164,11 @@ HELP; throw new RuntimeException($this->l10n->t('Addon not found')); } - if (AddonCore::isEnabled($addon)) { + if ($this->addonHelper->isAddonEnabled($addon)) { throw new RuntimeException($this->l10n->t('Addon already enabled')); } - AddonCore::install($addon); + $this->addonHelper->installAddon($addon); return 0; } @@ -187,11 +188,11 @@ HELP; throw new RuntimeException($this->l10n->t('Addon not found')); } - if (!AddonCore::isEnabled($addon)) { + if (!$this->addonHelper->isAddonEnabled($addon)) { throw new RuntimeException($this->l10n->t('Addon already disabled')); } - AddonCore::uninstall($addon); + $this->addonHelper->uninstallAddon($addon); return 0; } diff --git a/src/Console/JetstreamDaemon.php b/src/Console/JetstreamDaemon.php index 8bb1e7e106..365c26ebce 100644 --- a/src/Console/JetstreamDaemon.php +++ b/src/Console/JetstreamDaemon.php @@ -11,7 +11,7 @@ namespace Friendica\Console; use Asika\SimpleConsole\Console; use Friendica\App\Mode; -use Friendica\Core\Addon; +use Friendica\Core\Addon\AddonHelper; use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Hook; use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs; @@ -29,6 +29,7 @@ final class JetstreamDaemon extends Console private IManageKeyValuePairs $keyValue; private SysDaemon $daemon; private Jetstream $jetstream; + private AddonHelper $addonHelper; /** * @param Mode $mode @@ -38,15 +39,16 @@ final class JetstreamDaemon extends Console * @param Jetstream $jetstream * @param array|null $argv */ - public function __construct(Mode $mode, IManageConfigValues $config, IManageKeyValuePairs $keyValue, SysDaemon $daemon, Jetstream $jetstream, array $argv = null) + public function __construct(Mode $mode, IManageConfigValues $config, IManageKeyValuePairs $keyValue, SysDaemon $daemon, Jetstream $jetstream, AddonHelper $addonHelper, array $argv = null) { parent::__construct($argv); - $this->mode = $mode; - $this->config = $config; - $this->keyValue = $keyValue; - $this->jetstream = $jetstream; - $this->daemon = $daemon; + $this->mode = $mode; + $this->config = $config; + $this->keyValue = $keyValue; + $this->jetstream = $jetstream; + $this->daemon = $daemon; + $this->addonHelper = $addonHelper; } protected function getHelp(): string @@ -95,10 +97,10 @@ HELP; ); } - Addon::loadAddons(); + $this->addonHelper->loadAddons(); Hook::loadHooks(); - if (!Addon::isEnabled('bluesky')) { + if (!$this->addonHelper->isAddonEnabled('bluesky')) { throw new RuntimeException("Bluesky has to be enabled.\n"); } diff --git a/src/Content/Conversation.php b/src/Content/Conversation.php index 3b3610956f..3394b3c798 100644 --- a/src/Content/Conversation.php +++ b/src/Content/Conversation.php @@ -207,7 +207,7 @@ class Conversation if ($total === 0) { throw new InternalServerErrorException(sprintf('There has to be at least one Liker for verb "%s"', $verb)); - } else if ($total === 1) { + } elseif ($total === 1) { $likerString = $likers[0]; } else { if ($total < $this->config->get('system', 'max_likers')) { @@ -976,8 +976,8 @@ class Conversation } foreach ($items as $key => $row) { - $items[$key]['emojis'] = $emojis[$key] ?? []; - $items[$key]['counts'] = $counts[$key] ?? 0; + $items[$key]['emojis'] = $emojis[$key] ?? []; + $items[$key]['counts'] = $counts[$key] ?? 0; $items[$key]['quoteshares'] = $quoteshares[$key] ?? []; $always_display = in_array($mode, [self::MODE_CONTACTS, self::MODE_CONTACT_POSTS]); @@ -1431,7 +1431,7 @@ class Conversation public function getContextLessThreadList(array $items, string $mode, bool $preview, bool $pagedrop, string $formSecurityToken): array { $threads = []; - $uriids = []; + $uriids = []; foreach ($items as $item) { if (in_array($item['uri-id'], $uriids)) { @@ -1456,7 +1456,7 @@ class Conversation $tags = Tag::populateFromItem($item); - $author = [ + $author = [ 'uid' => 0, 'id' => $item['author-id'], 'network' => $item['author-network'], @@ -1501,7 +1501,7 @@ class Conversation $body_html = ItemModel::prepareBody($item, true, $preview); - [$categories, $folders] = $this->item->determineCategoriesTerms($item, $this->session->getLocalUserId()); + list($categories, $folders) = $this->item->determineCategoriesTerms($item, $this->session->getLocalUserId()); if (!empty($item['featured'])) { $pinned = $this->l10n->t('Pinned item'); diff --git a/src/Content/Widget.php b/src/Content/Widget.php index 0c73df9091..b86b3e9b1c 100644 --- a/src/Content/Widget.php +++ b/src/Content/Widget.php @@ -7,7 +7,6 @@ namespace Friendica\Content; -use Friendica\Core\Addon; use Friendica\Core\Cache\Enum\Duration; use Friendica\Core\Protocol; use Friendica\Core\Renderer; @@ -33,13 +32,13 @@ class Widget */ public static function follow(string $value = ''): string { - return Renderer::replaceMacros(Renderer::getMarkupTemplate('widget/follow.tpl'), array( + return Renderer::replaceMacros(Renderer::getMarkupTemplate('widget/follow.tpl'), [ '$connect' => DI::l10n()->t('Add New Contact'), - '$desc' => DI::l10n()->t('Enter address or web location'), - '$hint' => DI::l10n()->t('Example: bob@example.com, http://example.com/barbara'), - '$value' => $value, - '$follow' => DI::l10n()->t('Connect') - )); + '$desc' => DI::l10n()->t('Enter address or web location'), + '$hint' => DI::l10n()->t('Example: bob@example.com, http://example.com/barbara'), + '$value' => $value, + '$follow' => DI::l10n()->t('Connect') + ]); } /** @@ -60,21 +59,21 @@ class Widget } } - $nv = []; - $nv['findpeople'] = DI::l10n()->t('Find People'); - $nv['desc'] = DI::l10n()->t('Enter name or interest'); - $nv['label'] = DI::l10n()->t('Connect/Follow'); - $nv['hint'] = DI::l10n()->t('Examples: Robert Morgenstein, Fishing'); - $nv['findthem'] = DI::l10n()->t('Find'); - $nv['suggest'] = DI::l10n()->t('Friend Suggestions'); - $nv['similar'] = DI::l10n()->t('Similar Interests'); - $nv['random'] = DI::l10n()->t('Random Profile'); - $nv['inv'] = DI::l10n()->t('Invite Friends'); - $nv['directory'] = DI::l10n()->t('Global Directory'); - $nv['global_dir'] = OpenWebAuth::getZrlUrl($global_dir, true); + $nv = []; + $nv['findpeople'] = DI::l10n()->t('Find People'); + $nv['desc'] = DI::l10n()->t('Enter name or interest'); + $nv['label'] = DI::l10n()->t('Connect/Follow'); + $nv['hint'] = DI::l10n()->t('Examples: Robert Morgenstein, Fishing'); + $nv['findthem'] = DI::l10n()->t('Find'); + $nv['suggest'] = DI::l10n()->t('Friend Suggestions'); + $nv['similar'] = DI::l10n()->t('Similar Interests'); + $nv['random'] = DI::l10n()->t('Random Profile'); + $nv['inv'] = DI::l10n()->t('Invite Friends'); + $nv['directory'] = DI::l10n()->t('Global Directory'); + $nv['global_dir'] = OpenWebAuth::getZrlUrl($global_dir, true); $nv['local_directory'] = DI::l10n()->t('Local Directory'); - $aside = []; + $aside = []; $aside['$nv'] = $nv; return Renderer::replaceMacros(Renderer::getMarkupTemplate('widget/peoplefind.tpl'), $aside); @@ -87,19 +86,21 @@ class Widget */ public static function unavailableNetworks(): array { + $addonHelper = DI::addonHelper(); + // Always hide content from these networks $networks = [Protocol::PHANTOM, Protocol::FACEBOOK, Protocol::APPNET, Protocol::TWITTER, Protocol::ZOT, Protocol::OSTATUS, Protocol::STATUSNET]; - Addon::loadAddons(); + $addonHelper->loadAddons(); - if (!Addon::isEnabled('discourse')) { + if (!$addonHelper->isAddonEnabled('discourse')) { $networks[] = Protocol::DISCOURSE; } - if (!Addon::isEnabled('pumpio')) { + if (!$addonHelper->isAddonEnabled('pumpio')) { $networks[] = Protocol::PUMPIO; } - if (!Addon::isEnabled('tumblr')) { + if (!$addonHelper->isAddonEnabled('tumblr')) { $networks[] = Protocol::TUMBLR; } @@ -107,7 +108,7 @@ class Widget $networks[] = Protocol::DIASPORA; } - if (!Addon::isEnabled('pnut')) { + if (!$addonHelper->isAddonEnabled('pnut')) { $networks[] = Protocol::PNUT; } return $networks; @@ -120,18 +121,20 @@ class Widget */ public static function availableNetworks(): array { - $networks = [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::FEED]; - Addon::loadAddons(); + $addonHelper = DI::addonHelper(); - if (Addon::isEnabled('discourse')) { + $networks = [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::FEED]; + $addonHelper->loadAddons(); + + if ($addonHelper->isAddonEnabled('discourse')) { $networks[] = Protocol::DISCOURSE; } - if (Addon::isEnabled('pumpio')) { + if ($addonHelper->isAddonEnabled('pumpio')) { $networks[] = Protocol::PUMPIO; } - if (Addon::isEnabled('tumblr')) { + if ($addonHelper->isAddonEnabled('tumblr')) { $networks[] = Protocol::TUMBLR; } @@ -143,7 +146,7 @@ class Widget $networks[] = Protocol::MAIL; } - if (Addon::isEnabled('pnut')) { + if ($addonHelper->isAddonEnabled('pnut')) { $networks[] = Protocol::PNUT; } return $networks; @@ -174,7 +177,7 @@ class Widget private static function filter(string $type, string $title, string $desc, string $all, string $baseUrl, array $options, string $selected = null): string { $queryString = parse_url($baseUrl, PHP_URL_QUERY); - $queryArray = []; + $queryArray = []; if ($queryString) { parse_str($queryString, $queryArray); @@ -282,8 +285,8 @@ class Widget return ''; } - $networks = self::unavailableNetworks(); - $query = "`uid` = ? AND NOT `deleted` AND `network` != '' AND NOT `network` IN (" . substr(str_repeat("?, ", count($networks)), 0, -2) . ")"; + $networks = self::unavailableNetworks(); + $query = "`uid` = ? AND NOT `deleted` AND `network` != '' AND NOT `network` IN (" . substr(str_repeat("?, ", count($networks)), 0, -2) . ")"; $condition = array_merge([$query], array_merge([DI::userSession()->getLocalUserId()], $networks)); $r = DBA::select('contact', ['network'], $condition, ['group_by' => ['network'], 'order' => ['network']]); @@ -473,7 +476,7 @@ class Widget $ret = []; $cachekey = 'Widget::postedByYear' . $uid . '-' . (int)$wall; - $dthen = DI::cache()->get($cachekey); + $dthen = DI::cache()->get($cachekey); if (empty($dthen)) { $dthen = Item::firstPostDate($uid, $wall); DI::cache()->set($cachekey, $dthen, Duration::HOUR); @@ -486,30 +489,30 @@ class Widget if ($dthen) { // Set the start and end date to the beginning of the month $cutoffday = $dthen; - $thisday = substr($dnow, 4); - $nextday = date('Y-m-d', strtotime($dnow . ' + 1 day')); - $nextday = substr($nextday, 4); - $dnow = substr($dnow, 0, 8) . '01'; - $dthen = substr($dthen, 0, 8) . '01'; + $thisday = substr($dnow, 4); + $nextday = date('Y-m-d', strtotime($dnow . ' + 1 day')); + $nextday = substr($nextday, 4); + $dnow = substr($dnow, 0, 8) . '01'; + $dthen = substr($dthen, 0, 8) . '01'; /* * Starting with the current month, get the first and last days of every * month down to and including the month of the first post */ while (substr($dnow, 0, 7) >= substr($dthen, 0, 7)) { - $dyear = intval(substr($dnow, 0, 4)); - $dstart = substr($dnow, 0, 8) . '01'; - $dend = substr($dnow, 0, 8) . Temporal::getDaysInMonth(intval($dnow), intval(substr($dnow, 5))); + $dyear = intval(substr($dnow, 0, 4)); + $dstart = substr($dnow, 0, 8) . '01'; + $dend = substr($dnow, 0, 8) . Temporal::getDaysInMonth(intval($dnow), intval(substr($dnow, 5))); $start_month = DateTimeFormat::utc($dstart, 'Y-m-d'); - $end_month = DateTimeFormat::utc($dend, 'Y-m-d'); - $str = DI::l10n()->getDay(DateTimeFormat::utc($dnow, 'F')); + $end_month = DateTimeFormat::utc($dend, 'Y-m-d'); + $str = DI::l10n()->getDay(DateTimeFormat::utc($dnow, 'F')); if (empty($ret[$dyear])) { $ret[$dyear] = []; } $ret[$dyear][] = [$str, $end_month, $start_month]; - $dnow = DateTimeFormat::utc($dnow . ' -1 month', 'Y-m-d'); + $dnow = DateTimeFormat::utc($dnow . ' -1 month', 'Y-m-d'); } } @@ -518,21 +521,21 @@ class Widget } $cutoff_year = intval(DateTimeFormat::localNow('Y')) - $visible_years; - $cutoff = array_key_exists($cutoff_year, $ret); + $cutoff = array_key_exists($cutoff_year, $ret); $o = Renderer::replaceMacros(Renderer::getMarkupTemplate('widget/posted_date.tpl'), [ - '$title' => DI::l10n()->t('Archives'), - '$size' => $visible_years, + '$title' => DI::l10n()->t('Archives'), + '$size' => $visible_years, '$cutoff_year' => $cutoff_year, - '$cutoff' => $cutoff, - '$url' => $url, - '$dates' => $ret, - '$showless' => DI::l10n()->t('show less'), - '$showmore' => DI::l10n()->t('show more'), - '$onthisdate' => DI::l10n()->t('On this date'), - '$thisday' => $thisday, - '$nextday' => $nextday, - '$cutoffday' => $cutoffday + '$cutoff' => $cutoff, + '$url' => $url, + '$dates' => $ret, + '$showless' => DI::l10n()->t('show less'), + '$showmore' => DI::l10n()->t('show more'), + '$onthisdate' => DI::l10n()->t('On this date'), + '$thisday' => $thisday, + '$nextday' => $nextday, + '$cutoffday' => $cutoffday ]); return $o; diff --git a/src/Core/Addon.php b/src/Core/Addon.php index 5b162fd986..39a1737946 100644 --- a/src/Core/Addon.php +++ b/src/Core/Addon.php @@ -18,6 +18,9 @@ class Addon { /** * The addon sub-directory + * + * @deprecated 2025.02 Use `Friendica\Core\Addon\AddonHelper::getAddonPath()` instead + * * @var string */ const DIRECTORY = 'addon'; @@ -34,6 +37,8 @@ class Addon * This list is made from scanning the addon/ folder. * Unsupported addons are excluded unless they already are enabled or system.show_unsupported_addon is set. * + * @deprecated 2025.02 Use `Friendica\Core\Addon\AddonHelper::getAvailableAddons()` instead + * * @return array * @throws \Exception */ @@ -64,6 +69,8 @@ class Addon * Returns a list of addons that can be configured at the node level. * The list is formatted for display in the admin panel aside. * + * @deprecated 2025.02 Use `Friendica\Core\Addon\AddonHelper::getEnabledAddonsWithAdminSettings()` instead + * * @return array * @throws \Exception */ @@ -88,7 +95,6 @@ class Addon return $addons_admin; } - /** * Synchronize addons: * @@ -100,6 +106,7 @@ class Addon * Then go through the config list and if we have a addon that isn't installed, * call the install procedure and add it to the database. * + * @deprecated 2025.02 Use `Friendica\Core\Addon\AddonHelper::loadAddons()` instead */ public static function loadAddons() { @@ -109,6 +116,8 @@ class Addon /** * uninstalls an addon. * + * @deprecated 2025.02 Use `Friendica\Core\Addon\AddonHelper::uninstallAddon()` instead + * * @param string $addon name of the addon * @return void * @throws \Exception @@ -135,6 +144,8 @@ class Addon /** * installs an addon. * + * @deprecated 2025.02 Use `Friendica\Core\Addon\AddonHelper::installAddon()` instead + * * @param string $addon name of the addon * @return bool * @throws \Exception @@ -173,6 +184,8 @@ class Addon /** * reload all updated addons * + * @deprecated 2025.02 Use `Friendica\Core\Addon\AddonHelper::reloadAddons()` instead + * * @return void * @throws \Exception * @@ -209,6 +222,9 @@ class Addon * * Maintainer: Jess * * * *\endcode + * + * @deprecated 2025.02 Use `Friendica\Core\Addon\AddonHelper::getAddonInfo()` instead + * * @param string $addon the name of the addon * @return array with the addon information * @throws \Exception @@ -275,6 +291,8 @@ class Addon /** * Checks if the provided addon is enabled * + * @deprecated 2025.02 Use `Friendica\Core\Addon\AddonHelper::isAddonEnabled()` instead + * * @param string $addon * @return boolean */ @@ -286,6 +304,8 @@ class Addon /** * Returns a list of the enabled addon names * + * @deprecated 2025.02 Use `Friendica\Core\Addon\AddonHelper::getEnabledAddons()` instead + * * @return array */ public static function getEnabledList(): array @@ -296,6 +316,8 @@ class Addon /** * Returns the list of non-hidden enabled addon names * + * @deprecated 2025.02 Use `Friendica\Core\Addon\AddonHelper::getVisibleEnabledAddons()` instead + * * @return array * @throws \Exception */ diff --git a/src/Core/Addon/AddonHelper.php b/src/Core/Addon/AddonHelper.php new file mode 100644 index 0000000000..84b0c5f89d --- /dev/null +++ b/src/Core/Addon/AddonHelper.php @@ -0,0 +1,92 @@ + (string) $entry['name'], + ]; + + if (array_key_exists('link', $entry)) { + $contributor['link'] = (string) $entry['link']; + } + + $contributors[] = $contributor; + } + + return $contributors; + } + + private string $id = ''; + + private string $name = ''; + + private string $description = ''; + + private array $authors = []; + + private array $maintainers = []; + + private string $version = ''; + + private string $status = ''; + + private function __construct( + string $id, + string $name, + string $description, + array $authors, + array $maintainers, + string $version, + string $status + ) { + $this->id = $id; + $this->name = $name; + $this->description = $description; + $this->authors = $authors; + $this->maintainers = $maintainers; + $this->version = $version; + $this->status = $status; + } + + public function getId(): string + { + return $this->id; + } + + public function getName(): string + { + return $this->name; + } + + public function getDescription(): string + { + return $this->description; + } + + public function getAuthors(): array + { + return $this->authors; + } + + public function getMaintainers(): array + { + return $this->maintainers; + } + + public function getVersion(): string + { + return $this->version; + } + + public function getStatus(): string + { + return $this->status; + } +} diff --git a/src/Core/Addon/AddonProxy.php b/src/Core/Addon/AddonProxy.php new file mode 100644 index 0000000000..c3f7e583d8 --- /dev/null +++ b/src/Core/Addon/AddonProxy.php @@ -0,0 +1,154 @@ +addonPath = $addonPath; + } + + /** + * Returns the absolute path to the addon folder + * + * e.g. `/var/www/html/addon` + */ + public function getAddonPath(): string + { + return $this->addonPath; + } + + /** + * Returns the list of available addons. + * + * This list is made from scanning the addon/ folder. + * Unsupported addons are excluded unless they already are enabled or system.show_unsupported_addon is set. + * + * @return string[] + */ + public function getAvailableAddons(): array + { + return array_map( + function (array $item) { + return $item[0]; + }, + Addon::getAvailableList() + ); + } + + /** + * Installs an addon. + * + * @param string $addonId name of the addon + * + * @return bool true on success or false on failure + */ + public function installAddon(string $addonId): bool + { + return Addon::install($addonId); + } + + /** + * Uninstalls an addon. + * + * @param string $addonId name of the addon + */ + public function uninstallAddon(string $addonId): void + { + Addon::uninstall($addonId); + } + + /** + * Load addons. + * + * @internal + */ + public function loadAddons(): void + { + Addon::loadAddons(); + } + + /** + * Reload (uninstall and install) all updated addons. + */ + public function reloadAddons(): void + { + Addon::reload(); + } + + /** + * Get the comment block of an addon as value object. + */ + public function getAddonInfo(string $addonId): AddonInfo + { + $data = Addon::getInfo($addonId); + + // add addon ID + $data['id'] = $addonId; + + // rename author to authors + $data['authors'] = $data['author']; + unset($data['author']); + + // rename maintainer to maintainers + $data['maintainers'] = $data['maintainer']; + unset($data['maintainer']); + + return AddonInfo::fromArray($data); + } + + /** + * Checks if the provided addon is enabled + */ + public function isAddonEnabled(string $addonId): bool + { + return Addon::isEnabled($addonId); + } + + /** + * Returns a list with the IDs of the enabled addons + * + * @return string[] + */ + public function getEnabledAddons(): array + { + return Addon::getEnabledList(); + } + + /** + * Returns a list with the IDs of the non-hidden enabled addons + * + * @return string[] + */ + public function getVisibleEnabledAddons(): array + { + return Addon::getVisibleList(); + } + + /** + * Returns a list with the IDs of the enabled addons that provides admin settings. + * + * @return string[] + */ + public function getEnabledAddonsWithAdminSettings(): array + { + return array_keys(Addon::getAdminList()); + } +} diff --git a/src/Core/Config/Factory/Config.php b/src/Core/Config/Factory/Config.php index da9daa572d..30d3e597c6 100644 --- a/src/Core/Config/Factory/Config.php +++ b/src/Core/Config/Factory/Config.php @@ -42,7 +42,7 @@ class Config * * @return Util\ConfigFileManager */ - public function createConfigFileManager(string $basePath, array $server = []): Util\ConfigFileManager + public function createConfigFileManager(string $basePath, string $addonPath, array $server = []): Util\ConfigFileManager { if (!empty($server[self::CONFIG_DIR_ENV]) && is_dir($server[self::CONFIG_DIR_ENV])) { $configDir = $server[self::CONFIG_DIR_ENV]; @@ -51,7 +51,7 @@ class Config } $staticDir = $basePath . DIRECTORY_SEPARATOR . self::STATIC_DIR; - return new Util\ConfigFileManager($basePath, $configDir, $staticDir, $server); + return new Util\ConfigFileManager($basePath, $addonPath, $configDir, $staticDir, $server); } /** diff --git a/src/Core/Config/Util/ConfigFileManager.php b/src/Core/Config/Util/ConfigFileManager.php index ecb06a7cc8..d76e3e53cd 100644 --- a/src/Core/Config/Util/ConfigFileManager.php +++ b/src/Core/Config/Util/ConfigFileManager.php @@ -7,7 +7,6 @@ namespace Friendica\Core\Config\Util; -use Friendica\Core\Addon; use Friendica\Core\Config\Exception\ConfigFileException; use Friendica\Core\Config\ValueObject\Cache; @@ -46,6 +45,7 @@ class ConfigFileManager * @var string */ private $baseDir; + private string $addonDir; /** * @var string */ @@ -65,9 +65,10 @@ class ConfigFileManager * @param string $configDir * @param string $staticDir */ - public function __construct(string $baseDir, string $configDir, string $staticDir, array $server = []) + public function __construct(string $baseDir, string $addonDir, string $configDir, string $staticDir, array $server = []) { $this->baseDir = $baseDir; + $this->addonDir = $addonDir; $this->configDir = $configDir; $this->staticDir = $staticDir; $this->server = $server; @@ -122,7 +123,7 @@ class ConfigFileManager if (file_exists($configName)) { return $this->loadConfigFile($configName); - } else if (file_exists($iniName)) { + } elseif (file_exists($iniName)) { return $this->loadINIConfigFile($iniName); } else { return []; @@ -160,17 +161,16 @@ class ConfigFileManager */ public function loadAddonConfig(string $name): array { - $filepath = $this->baseDir . DIRECTORY_SEPARATOR . // /var/www/html/ - Addon::DIRECTORY . DIRECTORY_SEPARATOR . // addon/ - $name . DIRECTORY_SEPARATOR . // openstreetmap/ - 'config' . DIRECTORY_SEPARATOR . // config/ - $name . ".config.php"; // openstreetmap.config.php + $filepath = $this->addonDir . DIRECTORY_SEPARATOR . // /var/www/html/addon/ + $name . DIRECTORY_SEPARATOR . // openstreetmap/ + 'config' . DIRECTORY_SEPARATOR . // config/ + $name . ".config.php"; // openstreetmap.config.php - if (file_exists($filepath)) { - return $this->loadConfigFile($filepath); - } else { + if (!file_exists($filepath)) { return []; } + + return $this->loadConfigFile($filepath); } /** diff --git a/src/Core/Storage/Repository/StorageManager.php b/src/Core/Storage/Repository/StorageManager.php index 47b3bcca55..bbd9e13f14 100644 --- a/src/Core/Storage/Repository/StorageManager.php +++ b/src/Core/Storage/Repository/StorageManager.php @@ -8,7 +8,6 @@ namespace Friendica\Core\Storage\Repository; use Exception; -use Friendica\Core\Addon; use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Hook; use Friendica\Core\L10n; @@ -20,6 +19,7 @@ use Friendica\Core\Storage\Capability\ICanConfigureStorage; use Friendica\Core\Storage\Capability\ICanWriteToStorage; use Friendica\Database\Database; use Friendica\Core\Storage\Type; +use Friendica\DI; use Friendica\Network\HTTPException\InternalServerErrorException; use Psr\Log\LoggerInterface; @@ -84,7 +84,7 @@ class StorageManager /// @fixme Loading the addons & hooks here is really bad practice, but solves https://github.com/friendica/friendica/issues/11178 /// clean solution = Making Addon & Hook dynamic and load them inside the constructor, so there's no custom load logic necessary anymore if ($includeAddon) { - Addon::loadAddons(); + DI::addonHelper()->loadAddons(); Hook::loadHooks(); } @@ -138,7 +138,7 @@ class StorageManager // Try the filesystem backend case Type\Filesystem::getName(): return new Type\FilesystemConfig($this->config, $this->l10n); - // try the database backend + // try the database backend case Type\Database::getName(): return false; default: @@ -185,11 +185,11 @@ class StorageManager $storageConfig = new Type\FilesystemConfig($this->config, $this->l10n); $this->backendInstances[$name] = new Type\Filesystem($storageConfig->getStoragePath()); break; - // try the database backend + // try the database backend case Type\Database::getName(): $this->backendInstances[$name] = new Type\Database($this->dba); break; - // at least, try if there's an addon for the backend + // at least, try if there's an addon for the backend case Type\SystemResource::getName(): $this->backendInstances[$name] = new Type\SystemResource(); break; @@ -228,11 +228,13 @@ class StorageManager */ public function isValidBackend(string $name = null, array $validBackends = null): bool { - $validBackends = $validBackends ?? array_merge($this->validBackends, - [ - Type\SystemResource::getName(), - Type\ExternalResource::getName(), - ]); + $validBackends = $validBackends ?? array_merge( + $this->validBackends, + [ + Type\SystemResource::getName(), + Type\ExternalResource::getName(), + ] + ); return in_array($name, $validBackends); } diff --git a/src/DI.php b/src/DI.php index 43a60dae0b..bcbc17651b 100644 --- a/src/DI.php +++ b/src/DI.php @@ -8,6 +8,7 @@ namespace Friendica; use Dice\Dice; +use Friendica\Core\Addon\AddonHelper; use Friendica\Core\Logger\Capability\ICheckLoggerSettings; use Friendica\Core\Logger\LoggerManager; use Friendica\Core\Logger\Util\LoggerSettingsCheck; @@ -280,6 +281,11 @@ abstract class DI return self::$dice->create(Core\Storage\Repository\StorageManager::class); } + public static function addonHelper(): AddonHelper + { + return self::$dice->create(AddonHelper::class); + } + /** * @return \Friendica\Core\System */ diff --git a/src/Module/Admin/Addons/Details.php b/src/Module/Admin/Addons/Details.php index 9eb1c0cf40..a102f4d269 100644 --- a/src/Module/Admin/Addons/Details.php +++ b/src/Module/Admin/Addons/Details.php @@ -8,7 +8,6 @@ namespace Friendica\Module\Admin\Addons; use Friendica\Content\Text\Markdown; -use Friendica\Core\Addon; use Friendica\Core\Renderer; use Friendica\DI; use Friendica\Module\BaseAdmin; @@ -42,12 +41,12 @@ class Details extends BaseAdmin { parent::content(); - $addons_admin = Addon::getAdminList(); + $addonHelper = DI::addonHelper(); $addon = Strings::sanitizeFilePathItem($this->parameters['addon']); if (!is_file("addon/$addon/$addon.php")) { DI::sysmsg()->addNotice(DI::l10n()->t('Addon not found.')); - Addon::uninstall($addon); + $addonHelper->uninstallAddon($addon); DI::baseUrl()->redirect('admin/addons'); } @@ -55,11 +54,11 @@ class Details extends BaseAdmin self::checkFormSecurityTokenRedirectOnError('/admin/addons', 'admin_addons_details', 't'); // Toggle addon status - if (Addon::isEnabled($addon)) { - Addon::uninstall($addon); + if ($addonHelper->isAddonEnabled($addon)) { + $addonHelper->uninstallAddon($addon); DI::sysmsg()->addInfo(DI::l10n()->t('Addon %s disabled.', $addon)); } else { - Addon::install($addon); + $addonHelper->installAddon($addon); DI::sysmsg()->addInfo(DI::l10n()->t('Addon %s enabled.', $addon)); } @@ -67,7 +66,7 @@ class Details extends BaseAdmin } // display addon details - if (Addon::isEnabled($addon)) { + if ($addonHelper->isAddonEnabled($addon)) { $status = 'on'; $action = DI::l10n()->t('Disable'); } else { @@ -82,32 +81,42 @@ class Details extends BaseAdmin $readme = '
' . file_get_contents("addon/$addon/README") . '
'; } + $addons_admin = $addonHelper->getEnabledAddonsWithAdminSettings(); + $admin_form = ''; - if (array_key_exists($addon, $addons_admin)) { + if (in_array($addon, $addons_admin)) { require_once "addon/$addon/$addon.php"; $func = $addon . '_addon_admin'; $func($admin_form); } + $addonInfo = $addonHelper->getAddonInfo($addon); + $t = Renderer::getMarkupTemplate('admin/addons/details.tpl'); return Renderer::replaceMacros($t, [ - '$title' => DI::l10n()->t('Administration'), - '$page' => DI::l10n()->t('Addons'), - '$toggle' => DI::l10n()->t('Toggle'), + '$title' => DI::l10n()->t('Administration'), + '$page' => DI::l10n()->t('Addons'), + '$toggle' => DI::l10n()->t('Toggle'), '$settings' => DI::l10n()->t('Settings'), - '$addon' => $addon, + '$addon' => $addon, '$status' => $status, '$action' => $action, - '$info' => Addon::getInfo($addon), - '$str_author' => DI::l10n()->t('Author: '), + '$info' => [ + 'name' => $addonInfo->getName(), + 'version' => $addonInfo->getVersion(), + 'description' => $addonInfo->getDescription(), + 'author' => $addonInfo->getAuthors(), + 'maintainer' => $addonInfo->getMaintainers(), + ], + '$str_author' => DI::l10n()->t('Author: '), '$str_maintainer' => DI::l10n()->t('Maintainer: '), '$admin_form' => $admin_form, - '$function' => 'addons', + '$function' => 'addons', '$screenshot' => '', - '$readme' => $readme, + '$readme' => $readme, '$form_security_token' => self::getFormSecurityToken('admin_addons_details'), ]); diff --git a/src/Module/Admin/Addons/Index.php b/src/Module/Admin/Addons/Index.php index 8ebf1f918d..6038373018 100644 --- a/src/Module/Admin/Addons/Index.php +++ b/src/Module/Admin/Addons/Index.php @@ -7,7 +7,6 @@ namespace Friendica\Module\Admin\Addons; -use Friendica\Core\Addon; use Friendica\Core\Renderer; use Friendica\DI; use Friendica\Module\BaseAdmin; @@ -24,22 +23,25 @@ class Index extends BaseAdmin { parent::content(); + $addonHelper = DI::addonHelper(); + // reload active themes if (!empty($_GET['action'])) { self::checkFormSecurityTokenRedirectOnError('/admin/addons', 'admin_addons', 't'); switch ($_GET['action']) { case 'reload': - Addon::reload(); + $addonHelper->reloadAddons(); DI::sysmsg()->addInfo(DI::l10n()->t('Addons reloaded')); break; - case 'toggle' : + case 'toggle': $addon = $_GET['addon'] ?? ''; - if (Addon::isEnabled($addon)) { - Addon::uninstall($addon); + + if ($addonHelper->isAddonEnabled($addon)) { + $addonHelper->uninstallAddon($addon); DI::sysmsg()->addInfo(DI::l10n()->t('Addon %s disabled.', $addon)); - } elseif (Addon::install($addon)) { + } elseif ($addonHelper->installAddon($addon)) { DI::sysmsg()->addInfo(DI::l10n()->t('Addon %s enabled.', $addon)); } else { DI::sysmsg()->addNotice(DI::l10n()->t('Addon %s failed to install.', $addon)); @@ -52,18 +54,34 @@ class Index extends BaseAdmin DI::baseUrl()->redirect('admin/addons'); } - $addons = Addon::getAvailableList(); + $addons = []; + + foreach ($addonHelper->getAvailableAddons() as $addonId) { + $addonInfo = $addonHelper->getAddonInfo($addonId); + + $info = [ + 'name' => $addonInfo->getName(), + 'description' => $addonInfo->getDescription(), + 'version' => $addonInfo->getVersion(), + ]; + + $addons[] = [ + $addonId, + ($addonHelper->isAddonEnabled($addonId) ? 'on' : 'off'), + $info, + ]; + } $t = Renderer::getMarkupTemplate('admin/addons/index.tpl'); return Renderer::replaceMacros($t, [ - '$title' => DI::l10n()->t('Administration'), - '$page' => DI::l10n()->t('Addons'), - '$submit' => DI::l10n()->t('Save Settings'), - '$reload' => DI::l10n()->t('Reload active addons'), - '$function' => 'addons', - '$addons' => $addons, - '$pcount' => count($addons), - '$noplugshint' => DI::l10n()->t('There are currently no addons available on your node. You can find the official addon repository at %1$s.', 'https://git.friendi.ca/friendica/friendica-addons'), + '$title' => DI::l10n()->t('Administration'), + '$page' => DI::l10n()->t('Addons'), + '$submit' => DI::l10n()->t('Save Settings'), + '$reload' => DI::l10n()->t('Reload active addons'), + '$function' => 'addons', + '$addons' => $addons, + '$pcount' => count($addons), + '$noplugshint' => DI::l10n()->t('There are currently no addons available on your node. You can find the official addon repository at %1$s.', 'https://git.friendi.ca/friendica/friendica-addons'), '$form_security_token' => self::getFormSecurityToken('admin_addons'), ]); } diff --git a/src/Module/Admin/Summary.php b/src/Module/Admin/Summary.php index f07e9720cb..282c15e4bc 100644 --- a/src/Module/Admin/Summary.php +++ b/src/Module/Admin/Summary.php @@ -8,7 +8,6 @@ namespace Friendica\Module\Admin; use Friendica\App; -use Friendica\Core\Addon; use Friendica\Core\Config\ValueObject\Cache; use Friendica\Core\Renderer; use Friendica\Core\Update; @@ -27,13 +26,14 @@ class Summary extends BaseAdmin { parent::content(); - $basePath = DI::appHelper()->getBasePath(); + $basePath = DI::appHelper()->getBasePath(); + $addonPath = DI::addonHelper()->getAddonPath(); // are there MyISAM tables in the DB? If so, trigger a warning message $warningtext = []; $templateEngine = Renderer::getTemplateEngine(); - $errors = []; + $errors = []; $templateEngine->testInstall($errors); foreach ($errors as $error) { $warningtext[] = DI::l10n()->t('Template engine (%s) error: %s', $templateEngine::$name, $error); @@ -51,7 +51,7 @@ class Summary extends BaseAdmin // Avoid the database error 1615 "Prepared statement needs to be re-prepared", see https://github.com/friendica/friendica/issues/8550 if (!DI::config()->get('database', 'pdo_emulate_prepares')) { $table_definition_cache = DBA::getVariable('table_definition_cache'); - $table_open_cache = DBA::getVariable('table_open_cache'); + $table_open_cache = DBA::getVariable('table_open_cache'); if (!empty($table_definition_cache) && !empty($table_open_cache)) { $suggested_definition_cache = min(400 + round((int) $table_open_cache / 2, 1), 2000); if ($suggested_definition_cache > $table_definition_cache) { @@ -100,9 +100,13 @@ class Summary extends BaseAdmin // Check server vitality if (!self::checkSelfHostMeta()) { - $well_known = DI::baseUrl() . Probe::HOST_META; - $warningtext[] = DI::l10n()->t('%s is not reachable on your system. This is a severe configuration issue that prevents server to server communication. See the installation page for help.', - $well_known, $well_known, DI::baseUrl() . '/help/Install'); + $well_known = DI::baseUrl() . Probe::HOST_META; + $warningtext[] = DI::l10n()->t( + '%s is not reachable on your system. This is a severe configuration issue that prevents server to server communication. See the installation page for help.', + $well_known, + $well_known, + DI::baseUrl() . '/help/Install' + ); } // Check logfile permission @@ -114,8 +118,8 @@ class Summary extends BaseAdmin } // check legacy basepath settings - $configLoader = (new Config())->createConfigFileManager($basePath, $_SERVER); - $configCache = new Cache(); + $configLoader = (new Config())->createConfigFileManager($basePath, $addonPath, $_SERVER); + $configCache = new Cache(); $configLoader->setupCache($configCache); $confBasepath = $configCache->get('system', 'basepath'); $currBasepath = DI::config()->get('system', 'basepath'); @@ -125,25 +129,31 @@ class Summary extends BaseAdmin 'from' => $currBasepath, 'to' => $confBasepath, ]); - $warningtext[] = DI::l10n()->t('Friendica\'s system.basepath was updated from \'%s\' to \'%s\'. Please remove the system.basepath from your db to avoid differences.', + $warningtext[] = DI::l10n()->t( + 'Friendica\'s system.basepath was updated from \'%s\' to \'%s\'. Please remove the system.basepath from your db to avoid differences.', $currBasepath, - $confBasepath); + $confBasepath + ); } elseif (!is_dir($currBasepath)) { DI::logger()->alert('Friendica\'s system.basepath is wrong.', [ 'from' => $currBasepath, 'to' => $confBasepath, ]); - $warningtext[] = DI::l10n()->t('Friendica\'s current system.basepath \'%s\' is wrong and the config file \'%s\' isn\'t used.', + $warningtext[] = DI::l10n()->t( + 'Friendica\'s current system.basepath \'%s\' is wrong and the config file \'%s\' isn\'t used.', $currBasepath, - $confBasepath); + $confBasepath + ); } else { DI::logger()->alert('Friendica\'s system.basepath is wrong.', [ 'from' => $currBasepath, 'to' => $confBasepath, ]); - $warningtext[] = DI::l10n()->t('Friendica\'s current system.basepath \'%s\' is not equal to the config file \'%s\'. Please fix your configuration.', + $warningtext[] = DI::l10n()->t( + 'Friendica\'s current system.basepath \'%s\' is not equal to the config file \'%s\'. Please fix your configuration.', $currBasepath, - $confBasepath); + $confBasepath + ); } } @@ -177,7 +187,7 @@ class Summary extends BaseAdmin '$platform' => App::PLATFORM, '$codename' => App::CODENAME, '$build' => DI::config()->get('system', 'build'), - '$addons' => [DI::l10n()->t('Active addons'), Addon::getEnabledList()], + '$addons' => [DI::l10n()->t('Active addons'), DI::addonHelper()->getEnabledAddons()], '$serversettings' => $server_settings, '$warningtext' => $warningtext, ]); diff --git a/src/Module/BaseAdmin.php b/src/Module/BaseAdmin.php index 3d1188395f..ea03efd2a9 100644 --- a/src/Module/BaseAdmin.php +++ b/src/Module/BaseAdmin.php @@ -8,7 +8,6 @@ namespace Friendica\Module; use Friendica\BaseModule; -use Friendica\Core\Addon; use Friendica\Core\Renderer; use Friendica\DI; use Friendica\Network\HTTPException; @@ -69,43 +68,53 @@ abstract class BaseAdmin extends BaseModule // not part of $aside to make the template more adjustable $aside_sub = [ 'information' => [DI::l10n()->t('Information'), [ - 'overview' => ['admin' , DI::l10n()->t('Overview') , 'overview'], - 'federation' => ['admin/federation' , DI::l10n()->t('Federation Statistics') , 'federation'] + 'overview' => ['admin' , DI::l10n()->t('Overview') , 'overview'], + 'federation' => ['admin/federation' , DI::l10n()->t('Federation Statistics') , 'federation'] ]], 'configuration' => [DI::l10n()->t('Configuration'), [ - 'site' => ['admin/site' , DI::l10n()->t('Site') , 'site'], - 'storage' => ['admin/storage' , DI::l10n()->t('Storage') , 'storage'], - 'addons' => ['admin/addons' , DI::l10n()->t('Addons') , 'addons'], - 'themes' => ['admin/themes' , DI::l10n()->t('Themes') , 'themes'], - 'features' => ['admin/features' , DI::l10n()->t('Additional features') , 'features'], - 'tos' => ['admin/tos' , DI::l10n()->t('Terms of Service') , 'tos'], + 'site' => ['admin/site' , DI::l10n()->t('Site') , 'site'], + 'storage' => ['admin/storage' , DI::l10n()->t('Storage') , 'storage'], + 'addons' => ['admin/addons' , DI::l10n()->t('Addons') , 'addons'], + 'themes' => ['admin/themes' , DI::l10n()->t('Themes') , 'themes'], + 'features' => ['admin/features' , DI::l10n()->t('Additional features') , 'features'], + 'tos' => ['admin/tos' , DI::l10n()->t('Terms of Service') , 'tos'], ]], 'database' => [DI::l10n()->t('Database'), [ - 'dbsync' => ['admin/dbsync' , DI::l10n()->t('DB updates') , 'dbsync'], - 'deferred' => ['admin/queue/deferred', DI::l10n()->t('Inspect Deferred Workers'), 'deferred'], - 'workerqueue' => ['admin/queue' , DI::l10n()->t('Inspect worker Queue') , 'workerqueue'], + 'dbsync' => ['admin/dbsync' , DI::l10n()->t('DB updates') , 'dbsync'], + 'deferred' => ['admin/queue/deferred', DI::l10n()->t('Inspect Deferred Workers'), 'deferred'], + 'workerqueue' => ['admin/queue' , DI::l10n()->t('Inspect worker Queue') , 'workerqueue'], ]], 'logs' => [DI::l10n()->t('Logs'), [ - 'logsconfig' => ['admin/logs/', DI::l10n()->t('Logs') , 'logs'], - 'logsview' => ['admin/logs/view' , DI::l10n()->t('View Logs') , 'viewlogs'], + 'logsconfig' => ['admin/logs/', DI::l10n()->t('Logs') , 'logs'], + 'logsview' => ['admin/logs/view' , DI::l10n()->t('View Logs') , 'viewlogs'], ]], 'diagnostics' => [DI::l10n()->t('Diagnostics'), [ - 'phpinfo' => ['admin/phpinfo?t=' . self::getFormSecurityToken('phpinfo'), DI::l10n()->t('PHP Info') , 'phpinfo'], - 'probe' => ['probe' , DI::l10n()->t('probe address') , 'probe'], - 'webfinger' => ['webfinger' , DI::l10n()->t('check webfinger') , 'webfinger'], - 'babel' => ['babel' , DI::l10n()->t('Babel') , 'babel'], - 'debug/ap' => ['debug/ap' , DI::l10n()->t('ActivityPub Conversion') , 'debug/ap'], + 'phpinfo' => ['admin/phpinfo?t=' . self::getFormSecurityToken('phpinfo'), DI::l10n()->t('PHP Info') , 'phpinfo'], + 'probe' => ['probe' , DI::l10n()->t('probe address') , 'probe'], + 'webfinger' => ['webfinger' , DI::l10n()->t('check webfinger') , 'webfinger'], + 'babel' => ['babel' , DI::l10n()->t('Babel') , 'babel'], + 'debug/ap' => ['debug/ap' , DI::l10n()->t('ActivityPub Conversion') , 'debug/ap'], ]], ]; + $addons_admin = []; + + foreach (DI::addonHelper()->getEnabledAddonsWithAdminSettings() as $addonId) { + $addons_admin[$addonId] = [ + 'url' => 'admin/addons/' . $addonId, + 'name' => $addonId, + 'class' => 'addon', + ]; + } + $t = Renderer::getMarkupTemplate('admin/aside.tpl'); DI::page()['aside'] .= Renderer::replaceMacros($t, [ - '$admin' => ['addons_admin' => Addon::getAdminList()], - '$subpages' => $aside_sub, - '$admtxt' => DI::l10n()->t('Admin'), + '$admin' => ['addons_admin' => $addons_admin], + '$subpages' => $aside_sub, + '$admtxt' => DI::l10n()->t('Admin'), '$plugadmtxt' => DI::l10n()->t('Addon Features'), - '$h_pending' => DI::l10n()->t('User registrations waiting for confirmation'), - '$admurl' => 'admin/' + '$h_pending' => DI::l10n()->t('User registrations waiting for confirmation'), + '$admurl' => 'admin/' ]); return ''; diff --git a/src/Module/Filer/SaveTag.php b/src/Module/Filer/SaveTag.php index 4856d73681..63107c417a 100644 --- a/src/Module/Filer/SaveTag.php +++ b/src/Module/Filer/SaveTag.php @@ -56,7 +56,7 @@ class SaveTag extends BaseModule $tpl = Renderer::getMarkupTemplate("filer_dialog.tpl"); echo Renderer::replaceMacros($tpl, [ - '$field' => ['term', $this->t("Folder:"), '', '', $filetags, $this->t('- select -')], + '$field' => ['term', $this->t("Folder:"), '', '', $filetags, $this->t('- select -')], '$submit' => $this->t('Save'), ]); diff --git a/src/Module/Friendica.php b/src/Module/Friendica.php index cd1362b3af..1a741b890c 100644 --- a/src/Module/Friendica.php +++ b/src/Module/Friendica.php @@ -11,7 +11,7 @@ use Friendica\App; use Friendica\App\Arguments; use Friendica\App\BaseURL; use Friendica\BaseModule; -use Friendica\Core\Addon; +use Friendica\Core\Addon\AddonHelper; use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Hook; use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs; @@ -31,6 +31,7 @@ use Psr\Log\LoggerInterface; */ class Friendica extends BaseModule { + private AddonHelper $addonHelper; /** @var IManageConfigValues */ private $config; /** @var IManageKeyValuePairs */ @@ -38,18 +39,19 @@ class Friendica extends BaseModule /** @var IHandleUserSessions */ private $session; - public function __construct(IHandleUserSessions $session, IManageKeyValuePairs $keyValue, IManageConfigValues $config, L10n $l10n, BaseURL $baseUrl, Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) + public function __construct(AddonHelper $addonHelper, IHandleUserSessions $session, IManageKeyValuePairs $keyValue, IManageConfigValues $config, L10n $l10n, BaseURL $baseUrl, Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); - $this->config = $config; - $this->keyValue = $keyValue; - $this->session = $session; + $this->config = $config; + $this->keyValue = $keyValue; + $this->session = $session; + $this->addonHelper = $addonHelper; } protected function content(array $request = []): string { - $visibleAddonList = Addon::getVisibleList(); + $visibleAddonList = $this->addonHelper->getVisibleEnabledAddons(); if (!empty($visibleAddonList)) { $sorted = $visibleAddonList; @@ -83,8 +85,8 @@ class Friendica extends BaseModule if (!empty($blockList) && ($this->config->get('blocklist', 'public') || $this->session->isAuthenticated())) { $blocked = [ - 'title' => $this->t('On this server the following remote servers are blocked.'), - 'header' => [ + 'title' => $this->t('On this server the following remote servers are blocked.'), + 'header' => [ $this->t('Blocked domain'), $this->t('Reason for the block'), ], @@ -102,11 +104,13 @@ class Friendica extends BaseModule $tpl = Renderer::getMarkupTemplate('friendica.tpl'); return Renderer::replaceMacros($tpl, [ - 'about' => $this->t('This is Friendica, version %s that is running at the web location %s. The database version is %s, the post update version is %s.', + 'about' => $this->t( + 'This is Friendica, version %s that is running at the web location %s. The database version is %s, the post update version is %s.', '' . App::VERSION . '', $this->baseUrl, '' . $this->config->get('system', 'build') . '/' . DB_UPDATE_VERSION . '', - '' . $this->keyValue->get('post_update_version') . '/' . PostUpdate::VERSION . ''), + '' . $this->keyValue->get('post_update_version') . '/' . PostUpdate::VERSION . '' + ), 'friendica' => $this->t('Please visit Friendi.ca to learn more about the Friendica project.'), 'bugs' => $this->t('Bug reports and issues: please visit') . ' ' . '' . $this->t('the bugtracker at github') . '', 'info' => $this->t('Suggestions, praise, etc. - please email "info" at "friendi - dot - ca'), @@ -148,7 +152,7 @@ class Friendica extends BaseModule $register_policy = $register_policies[$register_policy_int]; } - $admin = []; + $admin = []; $administrator = User::getFirstAdmin(['username', 'nickname']); if (!empty($administrator)) { $admin = [ @@ -157,11 +161,11 @@ class Friendica extends BaseModule ]; } - $visible_addons = Addon::getVisibleList(); + $visible_addons = $this->addonHelper->getVisibleEnabledAddons(); $this->config->reload(); $locked_features = []; - $featureLocks = $this->config->get('config', 'feature_lock'); + $featureLocks = $this->config->get('config', 'feature_lock'); if (isset($featureLocks)) { foreach ($featureLocks as $feature => $lock) { if ($feature === 'config_loaded') { diff --git a/src/Protocol/ZOT.php b/src/Protocol/ZOT.php index b5604bcc84..28fa493454 100644 --- a/src/Protocol/ZOT.php +++ b/src/Protocol/ZOT.php @@ -8,7 +8,6 @@ namespace Friendica\Protocol; use Friendica\App; -use Friendica\Core\Addon; use Friendica\DI; use Friendica\Module; use Friendica\Module\Register; @@ -43,6 +42,11 @@ class ZOT */ public static function getSiteInfo(): array { + $baseUrl = (string) DI::baseUrl(); + $keyValue = DI::keyValue(); + $addonHelper = DI::addonHelper(); + $config = DI::config(); + $policies = [ Module\Register::OPEN => 'open', Module\Register::APPROVE => 'approve', @@ -50,14 +54,14 @@ class ZOT ]; return [ - 'url' => (string)DI::baseUrl(), - 'openWebAuth' => (string)DI::baseUrl() . '/owa', - 'authRedirect' => (string)DI::baseUrl() . '/magic', + 'url' => $baseUrl, + 'openWebAuth' => $baseUrl . '/owa', + 'authRedirect' => $baseUrl . '/magic', 'register_policy' => $policies[Register::getPolicy()], - 'accounts' => DI::keyValue()->get('nodeinfo_total_users'), - 'plugins' => Addon::getVisibleList(), - 'sitename' => DI::config()->get('config', 'sitename'), - 'about' => DI::config()->get('config', 'info'), + 'accounts' => $keyValue->get('nodeinfo_total_users'), + 'plugins' => $addonHelper->getVisibleEnabledAddons(), + 'sitename' => $config->get('config', 'sitename'), + 'about' => $config->get('config', 'info'), 'project' => App::PLATFORM, 'version' => App::VERSION, ]; diff --git a/src/Worker/Cron.php b/src/Worker/Cron.php index 3438b9e55a..b576f09ae7 100644 --- a/src/Worker/Cron.php +++ b/src/Worker/Cron.php @@ -7,7 +7,6 @@ namespace Friendica\Worker; -use Friendica\Core\Addon; use Friendica\Core\Hook; use Friendica\Core\Worker; use Friendica\Database\DBA; @@ -145,7 +144,7 @@ class Cron // Update "blocked" status of servers Worker::add(Worker::PRIORITY_LOW, 'UpdateBlockedServers'); - Addon::reload(); + DI::addonHelper()->reloadAddons(); DI::keyValue()->set('last_cron_daily', time()); } diff --git a/static/dependencies.config.php b/static/dependencies.config.php index 5ffaf134e4..5924ae512e 100644 --- a/static/dependencies.config.php +++ b/static/dependencies.config.php @@ -42,6 +42,12 @@ return (function(string $basepath, array $getVars, array $serverVars, array $coo [Dice::INSTANCE => Dice::SELF], ], ], + \Friendica\Core\Addon\AddonHelper::class => [ + 'instanceOf' => \Friendica\Core\Addon\AddonProxy::class, + 'constructParams' => [ + $basepath . '/addon', + ], + ], \Friendica\Util\BasePath::class => [ 'constructParams' => [ $basepath, @@ -81,6 +87,7 @@ return (function(string $basepath, array $getVars, array $serverVars, array $coo 'call' => [ ['createConfigFileManager', [ $basepath, + $basepath . '/addon', $serverVars, ], Dice::CHAIN_CALL], ], diff --git a/tests/ApiTestCase.php b/tests/ApiTestCase.php index bcf916abed..6124bf9f32 100644 --- a/tests/ApiTestCase.php +++ b/tests/ApiTestCase.php @@ -8,7 +8,7 @@ namespace Friendica\Test; use Friendica\Capabilities\ICanCreateResponses; -use Friendica\Core\Addon; +use Friendica\Core\Addon\AddonHelper; use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Hook; use Friendica\DI; @@ -124,7 +124,7 @@ abstract class ApiTestCase extends FixtureTestCase file_put_contents( $tmpFile, base64_decode( - // Empty 1x1 px PNG image + // Empty 1x1 px PNG image 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==' ) ); @@ -201,7 +201,7 @@ abstract class ApiTestCase extends FixtureTestCase 'plugin_admin' => function_exists($addon . '_addon_admin'), ]); - Addon::loadAddons(); + $this->dice->create(AddonHelper::class)->loadAddons(); Hook::loadHooks(); } } diff --git a/tests/FixtureTestTrait.php b/tests/FixtureTestTrait.php index 61de6441de..8c4508eeb8 100644 --- a/tests/FixtureTestTrait.php +++ b/tests/FixtureTestTrait.php @@ -44,7 +44,7 @@ trait FixtureTestTrait ->addRules(include __DIR__ . '/../static/dependencies.config.php') ->addRule(ConfigFileManager::class, [ 'instanceOf' => Config::class, - 'call' => [['createConfigFileManager', [$this->root->url(), $server,], Dice::CHAIN_CALL]]]) + 'call' => [['createConfigFileManager', [$this->root->url(), $this->root->url() . '/addon', $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, [ diff --git a/tests/Unit/Core/Addon/AddonInfoTest.php b/tests/Unit/Core/Addon/AddonInfoTest.php new file mode 100644 index 0000000000..a8e007b50a --- /dev/null +++ b/tests/Unit/Core/Addon/AddonInfoTest.php @@ -0,0 +1,55 @@ + '', + 'name' => '', + 'description' => '', + 'authors' => [], + 'maintainers' => [], + 'version' => '', + 'status' => '', + ]; + + $this->assertInstanceOf(AddonInfo::class, AddonInfo::fromArray($data)); + } + + public function testGetterReturningCorrectValues(): void + { + $data = [ + 'id' => 'test', + 'name' => 'Test-Addon', + 'description' => 'This is an addon for tests', + 'authors' => [['name' => 'Sam']], + 'maintainers' => [['name' => 'Sam', 'link' => 'https://example.com']], + 'version' => '0.1', + 'status' => 'In Development', + ]; + + $info = AddonInfo::fromArray($data); + + $this->assertSame($data['id'], $info->getId()); + $this->assertSame($data['name'], $info->getName()); + $this->assertSame($data['description'], $info->getDescription()); + $this->assertSame($data['description'], $info->getDescription()); + $this->assertSame($data['authors'], $info->getAuthors()); + $this->assertSame($data['maintainers'], $info->getMaintainers()); + $this->assertSame($data['version'], $info->getVersion()); + $this->assertSame($data['status'], $info->getStatus()); + } +} diff --git a/tests/Util/CreateDatabaseTrait.php b/tests/Util/CreateDatabaseTrait.php index c188ee8f94..05d3d6c0ca 100644 --- a/tests/Util/CreateDatabaseTrait.php +++ b/tests/Util/CreateDatabaseTrait.php @@ -15,8 +15,6 @@ use Friendica\Database\Definition\DbaDefinition; use Friendica\Database\Definition\ViewDefinition; use Friendica\Test\DatabaseTestTrait; use Friendica\Test\Util\Database\StaticDatabase; -use Friendica\Util\Profiler; -use Psr\Log\NullLogger; trait CreateDatabaseTrait { @@ -32,8 +30,13 @@ trait CreateDatabaseTrait return $this->dba; } - $configFileManager = new ConfigFileManager($this->root->url(), $this->root->url() . '/config/', $this->root->url() . '/static/'); - $config = new ReadOnlyFileConfig(new Cache([ + $configFileManager = new ConfigFileManager( + $this->root->url(), + $this->root->url() . '/addon', + $this->root->url() . '/config', + $this->root->url() . '/static' + ); + $config = new ReadOnlyFileConfig(new Cache([ 'database' => [ 'disable_pdo' => true ], diff --git a/tests/src/Core/Config/Cache/ConfigFileManagerTest.php b/tests/src/Core/Config/Cache/ConfigFileManagerTest.php index e5b1fc623d..6ccfc9733c 100644 --- a/tests/src/Core/Config/Cache/ConfigFileManagerTest.php +++ b/tests/src/Core/Config/Cache/ConfigFileManagerTest.php @@ -34,6 +34,7 @@ class ConfigFileManagerTest extends MockedTestCase $configFileLoader = new ConfigFileManager( $this->root->url(), + $this->root->url() . DIRECTORY_SEPARATOR . 'addon', $this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR, $this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR ); @@ -61,10 +62,11 @@ class ConfigFileManagerTest extends MockedTestCase $configFileLoader = new ConfigFileManager( $this->root->url(), + $this->root->url() . DIRECTORY_SEPARATOR . 'addon', $this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR, $this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR ); - $configCache = new Cache(); + $configCache = new Cache(); $configFileLoader->setupCache($configCache); } @@ -90,10 +92,11 @@ class ConfigFileManagerTest extends MockedTestCase $configFileLoader = new ConfigFileManager( $this->root->url(), + $this->root->url() . DIRECTORY_SEPARATOR . 'addon', $this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR, $this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR ); - $configCache = new Cache(); + $configCache = new Cache(); $configFileLoader->setupCache($configCache); @@ -127,10 +130,11 @@ class ConfigFileManagerTest extends MockedTestCase $configFileLoader = new ConfigFileManager( $this->root->url(), + $this->root->url() . DIRECTORY_SEPARATOR . 'addon', $this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR, $this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR ); - $configCache = new Cache(); + $configCache = new Cache(); $configFileLoader->setupCache($configCache); @@ -163,10 +167,11 @@ class ConfigFileManagerTest extends MockedTestCase $configFileLoader = new ConfigFileManager( $this->root->url(), + $this->root->url() . DIRECTORY_SEPARATOR . 'addon', $this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR, $this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR ); - $configCache = new Cache(); + $configCache = new Cache(); $configFileLoader->setupCache($configCache); @@ -217,6 +222,7 @@ class ConfigFileManagerTest extends MockedTestCase $configFileLoader = new ConfigFileManager( $this->root->url(), + $this->root->url() . DIRECTORY_SEPARATOR . 'addon', $this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR, $this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR ); @@ -254,10 +260,11 @@ class ConfigFileManagerTest extends MockedTestCase $configFileLoader = new ConfigFileManager( $this->root->url(), + $this->root->url() . DIRECTORY_SEPARATOR . 'addon', $this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR, $this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR ); - $configCache = new Cache(); + $configCache = new Cache(); $configFileLoader->setupCache($configCache); @@ -288,10 +295,11 @@ class ConfigFileManagerTest extends MockedTestCase $configFileLoader = new ConfigFileManager( $this->root->url(), + $this->root->url() . DIRECTORY_SEPARATOR . 'addon', $this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR, $this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR ); - $configCache = new Cache(); + $configCache = new Cache(); $configFileLoader->setupCache($configCache); @@ -322,6 +330,7 @@ class ConfigFileManagerTest extends MockedTestCase $configFileLoader = new ConfigFileManager( $this->root->url(), + $this->root->url() . DIRECTORY_SEPARATOR . 'addon', $this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR, $this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR ); @@ -341,8 +350,12 @@ class ConfigFileManagerTest extends MockedTestCase { $this->delConfigFile('local.config.php'); - $configFileManager = (new Config())->createConfigFileManager($this->root->url(), ['FRIENDICA_CONFIG_DIR' => '/a/wrong/dir/']); - $configCache = new Cache(); + $configFileManager = (new Config())->createConfigFileManager( + $this->root->url(), + $this->root->url() . '/addon', + ['FRIENDICA_CONFIG_DIR' => '/a/wrong/dir/'], + ); + $configCache = new Cache(); $configFileManager->setupCache($configCache); @@ -367,11 +380,12 @@ class ConfigFileManagerTest extends MockedTestCase ->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 = (new Config())->createConfigFileManager( + $this->root->url(), + $this->root->url() . '/addon', + ['FRIENDICA_CONFIG_DIR' => $this->root->getChild('config2')->url()], + ); + $configCache = new Cache(); $configFileManager->setupCache($configCache); @@ -389,11 +403,12 @@ class ConfigFileManagerTest extends MockedTestCase ->at($this->root->getChild('config')) ->setContent(''); - $configFileManager = (new Config())->createConfigFileManager($this->root->url()); - $configCache = new Cache(); + $configFileManager = (new Config())->createConfigFileManager( + $this->root->url(), + $this->root->url() . '/addon', + ); + $configCache = new Cache(); $configFileManager->setupCache($configCache); - - self::assertEquals(1,1); } } diff --git a/tests/src/Core/Config/ConfigTest.php b/tests/src/Core/Config/ConfigTest.php index 83dbaa0af0..fc2c41a164 100644 --- a/tests/src/Core/Config/ConfigTest.php +++ b/tests/src/Core/Config/ConfigTest.php @@ -16,7 +16,6 @@ use Friendica\Core\Config\ValueObject\Cache; use Friendica\Test\DatabaseTestCase; use Friendica\Test\Util\CreateDatabaseTrait; use Friendica\Test\Util\VFSTrait; -use org\bovigo\vfs\vfsStream; class ConfigTest extends DatabaseTestCase { @@ -55,8 +54,13 @@ class ConfigTest extends DatabaseTestCase parent::setUp(); - $this->configCache = new Cache(); - $this->configFileManager = new ConfigFileManager($this->root->url(), $this->root->url() . '/config/', $this->root->url() . '/static/'); + $this->configCache = new Cache(); + $this->configFileManager = new ConfigFileManager( + $this->root->url(), + $this->root->url() . '/addon', + $this->root->url() . '/config', + $this->root->url() . '/static' + ); } /** @@ -94,7 +98,7 @@ class ConfigTest extends DatabaseTestCase 'key1' => 'value1a', 'key4' => 'value4', ], - 'other' => [ + 'other' => [ 'key5' => 'value5', 'key6' => 'value6', ], @@ -108,18 +112,18 @@ class ConfigTest extends DatabaseTestCase 'config', 'other' ], - 'load' => [ + 'load' => [ 'system', ], ], - 'other' => [ + 'other' => [ 'data' => $data, 'possibleCats' => [ 'system', 'config', 'other' ], - 'load' => [ + 'load' => [ 'other', ], ], @@ -130,18 +134,18 @@ class ConfigTest extends DatabaseTestCase 'config', 'other' ], - 'load' => [ + 'load' => [ 'config', ], ], - 'all' => [ + 'all' => [ 'data' => $data, 'possibleCats' => [ 'system', 'config', 'other' ], - 'load' => [ + 'load' => [ 'system', 'config', 'other' @@ -173,7 +177,7 @@ class ConfigTest extends DatabaseTestCase */ public function testSetUp(array $data) { - $this->loadDirectFixture($this->configToDbArray($data) , $this->getDbInstance()); + $this->loadDirectFixture($this->configToDbArray($data), $this->getDbInstance()); $this->testedConfig = $this->getInstance(); self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); @@ -209,13 +213,13 @@ class ConfigTest extends DatabaseTestCase { return [ 'config' => [ - 'data1' => [ + 'data1' => [ 'config' => [ 'key1' => 'value1', 'key2' => 'value2', ], ], - 'data2' => [ + 'data2' => [ 'config' => [ 'key1' => 'overwritten!', 'key3' => 'value3', @@ -230,19 +234,19 @@ class ConfigTest extends DatabaseTestCase ], ], ], - 'other' => [ - 'data1' => [ + 'other' => [ + 'data1' => [ 'config' => [ 'key12' => 'data4', 'key45' => 7, ], - 'other' => [ + 'other' => [ 'key1' => 'value1', 'key2' => 'value2', ], ], - 'data2' => [ - 'other' => [ + 'data2' => [ + 'other' => [ 'key1' => 'overwritten!', 'key3' => 'value3', ], @@ -252,7 +256,7 @@ class ConfigTest extends DatabaseTestCase ] ], 'expect' => [ - 'other' => [ + 'other' => [ // load should overwrite values everytime! 'key1' => 'overwritten!', 'key2' => 'value2', @@ -399,26 +403,26 @@ class ConfigTest extends DatabaseTestCase public function dataTestCat() { return [ - 'test_with_hashmap' => [ - 'data' => [ + 'test_with_hashmap' => [ + 'data' => [ 'test_with_hashmap' => [ 'notifyall' => [ 'last_update' => 1671051565, 'admin' => true, ], - 'blockbot' => [ + 'blockbot' => [ 'last_update' => 1658952852, 'admin' => true, ], ], - 'config' => [ + 'config' => [ 'register_policy' => 2, 'register_text' => '', 'sitename' => 'Friendica Social Network23', 'hostname' => 'friendica.local', 'private_addons' => false, ], - 'system' => [ + 'system' => [ 'dbclean_expire_conversation' => 90, ], ], @@ -428,14 +432,14 @@ class ConfigTest extends DatabaseTestCase 'last_update' => 1671051565, 'admin' => true, ], - 'blockbot' => [ + 'blockbot' => [ 'last_update' => 1658952852, 'admin' => true, ], ], ], - 'test_with_keys' => [ - 'data' => [ + 'test_with_keys' => [ + 'data' => [ 'test_with_keys' => [ [ 'last_update' => 1671051565, @@ -446,14 +450,14 @@ class ConfigTest extends DatabaseTestCase 'admin' => true, ], ], - 'config' => [ + 'config' => [ 'register_policy' => 2, 'register_text' => '', 'sitename' => 'Friendica Social Network23', 'hostname' => 'friendica.local', 'private_addons' => false, ], - 'system' => [ + 'system' => [ 'dbclean_expire_conversation' => 90, ], ], @@ -470,7 +474,7 @@ class ConfigTest extends DatabaseTestCase ], ], 'test_with_inner_array' => [ - 'data' => [ + 'data' => [ 'test_with_inner_array' => [ 'notifyall' => [ 'last_update' => 1671051565, @@ -479,19 +483,19 @@ class ConfigTest extends DatabaseTestCase 'no' => 1.5, ], ], - 'blogbot' => [ + 'blogbot' => [ 'last_update' => 1658952852, 'admin' => true, ], ], - 'config' => [ + 'config' => [ 'register_policy' => 2, 'register_text' => '', 'sitename' => 'Friendica Social Network23', 'hostname' => 'friendica.local', 'private_addons' => false, ], - 'system' => [ + 'system' => [ 'dbclean_expire_conversation' => 90, ], ], @@ -504,7 +508,7 @@ class ConfigTest extends DatabaseTestCase 'no' => 1.5, ], ], - 'blogbot' => [ + 'blogbot' => [ 'last_update' => 1658952852, 'admin' => true, ], @@ -519,7 +523,7 @@ class ConfigTest extends DatabaseTestCase public function testGetCategory(array $data, string $category, array $assertion) { $this->configCache = new Cache($data); - $config = new ReadOnlyFileConfig($this->configCache); + $config = new ReadOnlyFileConfig($this->configCache); self::assertEquals($assertion, $config->get($category)); } @@ -528,15 +532,15 @@ class ConfigTest extends DatabaseTestCase { return [ 'default' => [ - 'value' => ['test' => ['array']], + 'value' => ['test' => ['array']], 'assertion' => ['test' => ['array']], ], 'issue-12803' => [ - 'value' => 's:48:"s:40:"s:32:"https://punkrock-underground.com";";";', + 'value' => 's:48:"s:40:"s:32:"https://punkrock-underground.com";";";', 'assertion' => 'https://punkrock-underground.com', ], 'double-serialized-array' => [ - 'value' => 's:53:"a:1:{s:9:"testArray";a:1:{s:4:"with";s:7:"entries";}}";', + 'value' => 's:53:"a:1:{s:9:"testArray";a:1:{s:4:"with";s:7:"entries";}}";', 'assertion' => ['testArray' => ['with' => 'entries']], ], ]; @@ -558,33 +562,33 @@ class ConfigTest extends DatabaseTestCase $data = [ 'config' => [ 'admin_email' => 'value1', - 'timezone' => 'value2', - 'language' => 'value3', - 'sitename' => 'value', + 'timezone' => 'value2', + 'language' => 'value3', + 'sitename' => 'value', ], 'system' => [ - 'url' => 'value1a', + 'url' => 'value1a', 'debugging' => true, - 'logfile' => 'value4', - 'loglevel' => 'notice', - 'proflier' => true, + 'logfile' => 'value4', + 'loglevel' => 'notice', + 'proflier' => true, ], - 'proxy' => [ + 'proxy' => [ 'trusted_proxies' => 'value5', ], ]; return [ 'empty' => [ - 'data' => $data, - 'server' => [], + 'data' => $data, + 'server' => [], 'assertDisabled' => [], ], 'mixed' => [ 'data' => $data, 'server' => [ 'FRIENDICA_ADMIN_MAIL' => 'test@friendica.local', - 'FRIENDICA_DEBUGGING' => true, + 'FRIENDICA_DEBUGGING' => true, ], 'assertDisabled' => [ 'config' => [ @@ -608,7 +612,13 @@ class ConfigTest extends DatabaseTestCase $this->setConfigFile('static' . DIRECTORY_SEPARATOR . 'env.config.php', true); $this->loadDirectFixture($this->configToDbArray($data), $this->getDbInstance()); - $configFileManager = new ConfigFileManager($this->root->url(), $this->root->url() . '/config/', $this->root->url() . '/static/', $server); + $configFileManager = new ConfigFileManager( + $this->root->url(), + $this->root->url() . '/addon', + $this->root->url() . '/config', + $this->root->url() . '/static', + $server + ); $configFileManager->setupCache($this->configCache); $config = new DatabaseConfig($this->getDbInstance(), $this->configCache); diff --git a/tests/src/Core/Config/ConfigTransactionTest.php b/tests/src/Core/Config/ConfigTransactionTest.php index 5c704b7600..42ec830ce6 100644 --- a/tests/src/Core/Config/ConfigTransactionTest.php +++ b/tests/src/Core/Config/ConfigTransactionTest.php @@ -9,16 +9,11 @@ namespace Friendica\Test\src\Core\Config; use Friendica\Core\Config\Capability\ISetConfigValuesTransactionally; use Friendica\Core\Config\Model\DatabaseConfig; -use Friendica\Core\Config\Model\ReadOnlyFileConfig; use Friendica\Core\Config\Model\ConfigTransaction; use Friendica\Core\Config\Util\ConfigFileManager; use Friendica\Core\Config\ValueObject\Cache; use Friendica\Database\Database; -use Friendica\Test\DatabaseTestCase; use Friendica\Test\FixtureTestCase; -use Friendica\Test\MockedTest; -use Friendica\Test\Util\Database\StaticDatabase; -use Friendica\Test\Util\VFSTrait; use Mockery\Exception\InvalidCountException; class ConfigTransactionTest extends FixtureTestCase @@ -30,7 +25,12 @@ class ConfigTransactionTest extends FixtureTestCase { parent::setUp(); - $this->configFileManager = new ConfigFileManager($this->root->url(), $this->root->url() . '/config/', $this->root->url() . '/static/'); + $this->configFileManager = new ConfigFileManager( + $this->root->url(), + $this->root->url() . '/addon', + $this->root->url() . '/config', + $this->root->url() . '/static' + ); } public function dataTests(): array @@ -96,7 +96,7 @@ class ConfigTransactionTest extends FixtureTestCase { $this->configFileManager = \Mockery::spy(ConfigFileManager::class); - $config = new DatabaseConfig($this->dice->create(Database::class), new Cache()); + $config = new DatabaseConfig($this->dice->create(Database::class), new Cache()); $configTransaction = new ConfigTransaction($config); // commit empty transaction diff --git a/tests/src/Core/Storage/Repository/StorageManagerTest.php b/tests/src/Core/Storage/Repository/StorageManagerTest.php index ac74274c03..7697f59381 100644 --- a/tests/src/Core/Storage/Repository/StorageManagerTest.php +++ b/tests/src/Core/Storage/Repository/StorageManagerTest.php @@ -21,16 +21,12 @@ use Friendica\Core\Storage\Repository\StorageManager; use Friendica\Core\Storage\Type\Filesystem; use Friendica\Core\Storage\Type\SystemResource; use Friendica\Database\Database; -use Friendica\Database\Definition\DbaDefinition; -use Friendica\Database\Definition\ViewDefinition; use Friendica\DI; use Friendica\Core\Config\Factory\Config; use Friendica\Core\Storage\Type; use Friendica\Test\DatabaseTestCase; use Friendica\Test\Util\CreateDatabaseTrait; use Friendica\Test\Util\Database\StaticDatabase; -use Friendica\Test\Util\VFSTrait; -use Friendica\Util\Profiler; use org\bovigo\vfs\vfsStream; use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; @@ -60,12 +56,15 @@ class StorageManagerTest extends DatabaseTestCase vfsStream::newDirectory(Type\FilesystemConfig::DEFAULT_BASE_FOLDER, 0777)->at($this->root); - $this->logger = new NullLogger(); + $this->logger = new NullLogger(); $this->database = $this->getDbInstance(); $configFactory = new Config(); - $configFileManager = $configFactory->createConfigFileManager($this->root->url()); - $configCache = $configFactory->createCache($configFileManager); + $configFileManager = $configFactory->createConfigFileManager( + $this->root->url(), + $this->root->url() . '/addon', + ); + $configCache = $configFactory->createCache($configFileManager); $this->config = new \Friendica\Core\Config\Model\DatabaseConfig($this->database, $configCache); $this->config->set('storage', 'name', 'Database'); @@ -96,21 +95,21 @@ class StorageManagerTest extends DatabaseTestCase 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, @@ -124,7 +123,7 @@ class StorageManagerTest extends DatabaseTestCase 'assert' => SystemResource::class, 'assertName' => SystemResource::NAME, ], - 'invalid' => [ + 'invalid' => [ 'name' => 'invalid', 'valid' => false, 'interface' => null, diff --git a/tests/src/Database/DatabaseTest.php b/tests/src/Database/DatabaseTest.php index c889d6d7d1..c9b6dd9528 100644 --- a/tests/src/Database/DatabaseTest.php +++ b/tests/src/Database/DatabaseTest.php @@ -32,7 +32,12 @@ class DatabaseTest extends FixtureTestCase parent::setUp(); $this->configCache = new Cache(); - $this->configFileManager = new ConfigFileManager($this->root->url(), $this->root->url() . '/config/', $this->root->url() . '/static/'); + $this->configFileManager = new ConfigFileManager( + $this->root->url(), + $this->root->url() . '/addon', + $this->root->url() . '/config', + $this->root->url() . '/static' + ); } /** @@ -87,7 +92,7 @@ class DatabaseTest extends FixtureTestCase self::assertTrue($db->update('gserver', ['active-week-users' => 0, 'registered-users' => 0], ['nurl' => 'http://friendica.local'])); - $fields = ["`registered-users` = `registered-users` + 1"]; + $fields = ["`registered-users` = `registered-users` + 1"]; $fields[] = "`active-week-users` = `active-week-users` + 2"; self::assertTrue($db->update('gserver', $fields, ['nurl' => 'http://friendica.local']));