From 73d464248944b9f7bfcd255e135f59bc64f9c6cb Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 11 Oct 2025 10:42:26 +0200 Subject: [PATCH 001/197] change Dockerfile to use php image --- .devcontainer/Dockerfile | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 4867640812..b8e6f82ac9 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,5 +1,5 @@ -ARG VARIANT="8.2-apache-bullseye" -FROM mcr.microsoft.com/vscode/devcontainers/php:${VARIANT} +ARG VARIANT="8.2-fpm" +FROM php:${VARIANT} ARG DEBIAN_FRONTEND=noninteractive ARG apcu_version=5.1.23 @@ -13,14 +13,21 @@ RUN apt-get update -y; RUN apt-get install -y mariadb-client # Base packages -RUN apt install -y vim software-properties-common sudo nano gnupg2 +RUN apt-get install -y \ + vim \ + sudo \ + nano \ + git \ + gnupg2 \ + ; # entrypoint.sh and cron.sh dependencies RUN apt-get install -y --no-install-recommends \ rsync \ bzip2 \ msmtp \ - tini + tini \ + ; RUN apt-get install -y --no-install-recommends \ bash \ @@ -38,15 +45,16 @@ RUN apt-get install -y --no-install-recommends \ libzip-dev \ libldap2-dev \ libgmp-dev \ - libmagickcore-6.q16-6-extra \ - ; \ - \ - docker-php-ext-configure gd \ + # libmagickcore-6.q16-6-extra \ + ; + +RUN docker-php-ext-configure gd \ --with-freetype \ --with-jpeg \ --with-webp \ - ; \ - docker-php-ext-install -j "$(nproc)" \ + ; + +RUN docker-php-ext-install -j "$(nproc)" \ pdo_mysql \ gd \ exif \ @@ -56,7 +64,8 @@ RUN apt-get install -y --no-install-recommends \ pcntl \ ldap \ gmp \ - intl + intl \ + ; # pecl will claim success even if one install fails, so we need to perform each install separately RUN pecl install apcu-${apcu_version}; \ From 7f95b5f8b1fedecebefa7d9f83c26ff4594bf9d7 Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 11 Oct 2025 10:58:20 +0200 Subject: [PATCH 002/197] Switch to image php:8.3-apache, fix code style --- .devcontainer/Dockerfile | 63 +++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index b8e6f82ac9..9cbbf85184 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -ARG VARIANT="8.2-fpm" +ARG VARIANT="8.2-apache" FROM php:${VARIANT} ARG DEBIAN_FRONTEND=noninteractive @@ -19,7 +19,7 @@ RUN apt-get install -y \ nano \ git \ gnupg2 \ - ; +; # entrypoint.sh and cron.sh dependencies RUN apt-get install -y --no-install-recommends \ @@ -27,7 +27,7 @@ RUN apt-get install -y --no-install-recommends \ bzip2 \ msmtp \ tini \ - ; +; RUN apt-get install -y --no-install-recommends \ bash \ @@ -46,37 +46,40 @@ RUN apt-get install -y --no-install-recommends \ libldap2-dev \ libgmp-dev \ # libmagickcore-6.q16-6-extra \ - ; +; RUN docker-php-ext-configure gd \ - --with-freetype \ - --with-jpeg \ - --with-webp \ - ; + --with-freetype \ + --with-jpeg \ + --with-webp \ +; RUN docker-php-ext-install -j "$(nproc)" \ - pdo_mysql \ - gd \ - exif \ - zip \ - opcache \ - ctype \ - pcntl \ - ldap \ - gmp \ - intl \ - ; + pdo_mysql \ + gd \ + exif \ + zip \ + opcache \ + ctype \ + pcntl \ + ldap \ + gmp \ + intl \ + ; # pecl will claim success even if one install fails, so we need to perform each install separately RUN pecl install apcu-${apcu_version}; \ pecl install memcached-${memcached_version}; \ pecl install redis-${redis_version}; \ - pecl install imagick-${imagick_version}; \ - docker-php-ext-enable \ - apcu \ - memcached \ - redis \ - imagick + pecl install imagick-${imagick_version} \ +; + +RUN docker-php-ext-enable \ + apcu \ + memcached \ + redis \ + imagick \ +; RUN apt-get clean -y && rm -rf /var/lib/apt/lists/* @@ -98,8 +101,8 @@ RUN { \ echo 'memory_limit=${PHP_MEMORY_LIMIT}'; \ echo 'upload_max_filesize=${PHP_UPLOAD_LIMIT}'; \ echo 'post_max_size=${PHP_UPLOAD_LIMIT}'; \ - } > /usr/local/etc/php/conf.d/friendica.ini; \ - ln -s /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini; \ - \ - mkdir /var/www/data; \ - chmod -R g=u /var/www + } > /usr/local/etc/php/conf.d/friendica.ini; + +RUN ln -s /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini +RUN mkdir /var/www/data +RUN chmod -R g=u /var/www From f508cbb79dcc84d32eb30ae6f29feec58fe0b321 Mon Sep 17 00:00:00 2001 From: Marcus Funch Date: Sun, 1 Jun 2025 15:33:26 +0200 Subject: [PATCH 003/197] Always show 'Accounts' in the profile menu --- src/Content/Nav.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Content/Nav.php b/src/Content/Nav.php index 4ca3564c6c..849bab6097 100644 --- a/src/Content/Nav.php +++ b/src/Content/Nav.php @@ -318,8 +318,12 @@ class Nav $nav['messages']['outbox'] = ['message/sent', $this->l10n->t('Outbox'), '', $this->l10n->t('Outbox')]; $nav['messages']['new'] = ['message/new', $this->l10n->t('New Message'), '', $this->l10n->t('New Message')]; + $nav_accounts_name = $this->l10n->t('Accounts'); + $nav_accounts_description = $this->l10n->t('Manage other accounts, including groups and pages'); if (User::hasIdentities($this->session->getSubManagedUserId() ?: $this->session->getLocalUserId())) { - $nav['delegation'] = ['delegation', $this->l10n->t('Accounts'), '', $this->l10n->t('Manage other accounts, including groups and pages')]; + $nav['delegation'] = ['delegation', $nav_accounts_name, '', $nav_accounts_description]; + } else { + $nav['delegation'] = ['settings/delegation', $nav_accounts_name, '', $nav_accounts_description]; } $nav['settings'] = ['settings', $this->l10n->t('Settings'), '', $this->l10n->t('Account settings')]; From eea2fd4f7074725dc602aa6482bebafcceffbd6d Mon Sep 17 00:00:00 2001 From: Art4 Date: Mon, 27 Oct 2025 21:22:38 +0100 Subject: [PATCH 004/197] Update docker-compose.yml --- .devcontainer/docker-compose.yml | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 4463ebad86..9a4313eef5 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -1,6 +1,4 @@ -version: '3.8' - -services: +services: app: build: context: . @@ -14,16 +12,14 @@ services: command: sleep infinity ports: - - 80:80 - - 443:443 - - 8080:8080 - - 3306:3306 - - # Use "forwardPorts" in **devcontainer.json** to forward an app port locally. + - ${ServerPort:-8080}:80 + - 8443:443 + + # Use "forwardPorts" in **devcontainer.json** to forward an app port locally. # (Adding the "ports" property to this file will not forward from a Codespace.) extra_hosts: - - "${ServerAlias}:127.0.0.1" + - "${ServerAlias}:127.0.0.1" db: image: mariadb:10.4 @@ -49,4 +45,3 @@ volumes: networks: default: - \ No newline at end of file From 7322431178a14ec669ceb7cc483415fb0f1d74be Mon Sep 17 00:00:00 2001 From: Art4 Date: Mon, 27 Oct 2025 21:50:10 +0100 Subject: [PATCH 005/197] update devcontainer to php 8.4, update pecl packages --- .devcontainer/Dockerfile | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 9cbbf85184..5c227c7b15 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,11 +1,6 @@ -ARG VARIANT="8.2-apache" -FROM php:${VARIANT} +FROM php:8.4-apache -ARG DEBIAN_FRONTEND=noninteractive -ARG apcu_version=5.1.23 -ARG memcached_version=3.2.0 -ARG redis_version=6.0.2 -ARG imagick_version=3.7.0 +ARG DEBIAN_FRONTEND=noninteractive´ RUN apt-get update -y; @@ -68,11 +63,10 @@ RUN docker-php-ext-install -j "$(nproc)" \ ; # pecl will claim success even if one install fails, so we need to perform each install separately -RUN pecl install apcu-${apcu_version}; \ - pecl install memcached-${memcached_version}; \ - pecl install redis-${redis_version}; \ - pecl install imagick-${imagick_version} \ -; +RUN pecl install apcu-5.1.27; +RUN pecl install memcached-3.4.0; +RUN pecl install redis-6.2.0; +RUN pecl install imagick-3.8.0; RUN docker-php-ext-enable \ apcu \ From 046c9770fad5a539af4ad132505e0c1423fc9c41 Mon Sep 17 00:00:00 2001 From: Art4 Date: Mon, 27 Oct 2025 21:56:32 +0100 Subject: [PATCH 006/197] install pinentry-curses in devcontainer --- .devcontainer/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 5c227c7b15..572cb09832 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -14,6 +14,7 @@ RUN apt-get install -y \ nano \ git \ gnupg2 \ + pinentry-curses \ ; # entrypoint.sh and cron.sh dependencies From 3ad5031e09a78b030a21df17755a302d6a9e0ffd Mon Sep 17 00:00:00 2001 From: Artur Weigandt Date: Tue, 28 Oct 2025 20:22:04 +0100 Subject: [PATCH 007/197] Update .devcontainer/Dockerfile --- .devcontainer/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 572cb09832..5bef5e2c18 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,6 +1,6 @@ FROM php:8.4-apache -ARG DEBIAN_FRONTEND=noninteractive´ +ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -y; From 90bfc38e0acc542ec3d7d96e7d2122203bd1fa8b Mon Sep 17 00:00:00 2001 From: Marcus Funch Date: Fri, 2 Jan 2026 18:19:17 +0100 Subject: [PATCH 008/197] UI adjustments to the admin and moderation summaries --- src/Module/Admin/Summary.php | 45 ++++++++++++---- src/Module/Moderation/Summary.php | 13 ++--- view/lang/C/messages.po | 54 +++++++++++-------- view/templates/admin/addons/index.tpl | 2 +- view/templates/admin/summary.tpl | 4 +- view/theme/frio/css/style.css | 8 +++ view/theme/frio/templates/admin/summary.tpl | 51 +++++++++--------- .../frio/templates/moderation/summary.tpl | 46 ++++++++-------- 8 files changed, 131 insertions(+), 92 deletions(-) diff --git a/src/Module/Admin/Summary.php b/src/Module/Admin/Summary.php index 2f6905103c..de0b4943c3 100644 --- a/src/Module/Admin/Summary.php +++ b/src/Module/Admin/Summary.php @@ -8,6 +8,7 @@ namespace Friendica\Module\Admin; use Friendica\App; +use Friendica\Core\Addon\Exception\InvalidAddonException; use Friendica\Core\Config\ValueObject\Cache; use Friendica\Core\Renderer; use Friendica\Core\Update; @@ -178,18 +179,42 @@ class Summary extends BaseAdmin ] ]; + $addons = []; + + $addonHelper = DI::addonHelper(); + foreach ($addonHelper->getEnabledAddons() as $addonId) { + try { + $addonInfo = $addonHelper->getAddonInfo($addonId); + } catch (InvalidAddonException $th) { + $this->logger->error('Invalid addon found: ' . $addonId, ['exception' => $th]); + continue; + } + + $info = [ + 'name' => $addonInfo->getName(), + 'description' => $addonInfo->getDescription(), + 'version' => $addonInfo->getVersion(), + ]; + + $addons[] = [ + $addonId, + $info, + ]; + } + $t = Renderer::getMarkupTemplate('admin/summary.tpl'); return Renderer::replaceMacros($t, [ - '$title' => DI::l10n()->t('Administration'), - '$page' => DI::l10n()->t('Summary'), - '$queues' => $queues, - '$version_label' => DI::l10n()->t('Version'), - '$platform' => App::PLATFORM, - '$codename' => App::CODENAME, - '$build' => DI::config()->get('system', 'build'), - '$addons' => [DI::l10n()->t('Active addons'), DI::addonHelper()->getEnabledAddons()], - '$serversettings' => $server_settings, - '$warningtext' => $warningtext, + '$title' => DI::l10n()->t('Administration'), + '$page' => DI::l10n()->t('Summary'), + '$queues' => $queues, + '$version_label' => DI::l10n()->t('Version'), + '$platform' => App::PLATFORM, + '$codename' => App::CODENAME, + '$build' => DI::config()->get('system', 'build'), + '$addons' => [DI::l10n()->t('Active addons'), $addons], + '$serversettings' => $server_settings, + '$warningtext' => $warningtext, + '$link_enable_addons' => DI::l10n()->t('Enable new addons'), ]); } diff --git a/src/Module/Moderation/Summary.php b/src/Module/Moderation/Summary.php index 99ab2ee296..8a8e48b928 100644 --- a/src/Module/Moderation/Summary.php +++ b/src/Module/Moderation/Summary.php @@ -61,12 +61,13 @@ class Summary extends BaseModeration $t = Renderer::getMarkupTemplate('moderation/summary.tpl'); return Renderer::replaceMacros($t, [ - '$title' => $this->t('Moderation'), - '$page' => $this->t('Summary'), - '$users' => [$this->t('Registered users'), $users], - '$accounts' => $accounts, - '$pending' => [$this->t('Pending registrations'), $pending], - '$warningtext' => [], + '$title' => $this->t('Moderation'), + '$page' => $this->t('Summary'), + '$users' => [$this->t('Registered users'), $users], + '$accounts' => $accounts, + '$pending' => [$this->t('Pending registrations'), $pending], + '$warningtext' => [], + '$account_type_header' => $this->t('Registered accounts by type'), ]); } } diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index 4c9e411c3f..c3be1900f1 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 2025.07-rc\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-01-04 20:49+0100\n" +"POT-Creation-Date: 2026-01-06 15:55+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -3594,7 +3594,7 @@ msgstr "" msgid "Title/Description:" msgstr "" -#: src/Model/Profile.php:803 src/Module/Admin/Summary.php:184 +#: src/Model/Profile.php:803 src/Module/Admin/Summary.php:208 #: src/Module/Moderation/Report/Create.php:282 #: src/Module/Moderation/Summary.php:65 msgid "Summary" @@ -3908,7 +3908,7 @@ msgstr "" #: src/Module/Admin/Federation.php:218 src/Module/Admin/Logs/Settings.php:74 #: src/Module/Admin/Logs/View.php:71 src/Module/Admin/Queue.php:59 #: src/Module/Admin/Site.php:457 src/Module/Admin/Storage.php:124 -#: src/Module/Admin/Summary.php:183 src/Module/Admin/Themes/Details.php:82 +#: src/Module/Admin/Summary.php:207 src/Module/Admin/Themes/Details.php:82 #: src/Module/Admin/Themes/Index.php:103 src/Module/Admin/Tos.php:63 #: src/Module/Moderation/Users/Pending.php:82 msgid "Administration" @@ -5396,98 +5396,102 @@ msgstr "" msgid "Database (legacy)" msgstr "" -#: src/Module/Admin/Summary.php:39 +#: src/Module/Admin/Summary.php:40 #, php-format msgid "Template engine (%s) error: %s" msgstr "" -#: src/Module/Admin/Summary.php:43 +#: src/Module/Admin/Summary.php:44 #, php-format msgid "Your DB still runs with MyISAM tables. You should change the engine type to InnoDB. As Friendica will use InnoDB only features in the future, you should change this! See here for a guide that may be helpful converting the table engines. You may also use the command php bin/console.php dbstructure toinnodb of your Friendica installation for an automatic conversion.
" msgstr "" -#: src/Module/Admin/Summary.php:48 +#: src/Module/Admin/Summary.php:49 #, php-format msgid "Your DB still runs with InnoDB tables in the Antelope file format. You should change the file format to Barracuda. Friendica is using features that are not provided by the Antelope format. See here for a guide that may be helpful converting the table engines. You may also use the command php bin/console.php dbstructure toinnodb of your Friendica installation for an automatic conversion.
" msgstr "" -#: src/Module/Admin/Summary.php:58 +#: src/Module/Admin/Summary.php:59 #, php-format msgid "Your table_definition_cache is too low (%d). This can lead to the database error \"Prepared statement needs to be re-prepared\". Please set it at least to %d. See here for more information.
" msgstr "" -#: src/Module/Admin/Summary.php:66 +#: src/Module/Admin/Summary.php:67 #, php-format msgid "There is a new version of Friendica available for download. Your current version is %1$s, upstream version is %2$s" msgstr "" -#: src/Module/Admin/Summary.php:74 +#: src/Module/Admin/Summary.php:75 msgid "The database update failed. Please run \"php bin/console.php dbstructure update\" from the command line and have a look at the errors that might appear." msgstr "" -#: src/Module/Admin/Summary.php:78 +#: src/Module/Admin/Summary.php:79 msgid "The last update failed. Please run \"php bin/console.php dbstructure update\" from the command line and have a look at the errors that might appear. (Some of the errors are possibly inside the logfile.)" msgstr "" -#: src/Module/Admin/Summary.php:82 +#: src/Module/Admin/Summary.php:83 msgid "The system.url entry is missing. This is a low level setting and can lead to unexpected behavior. Please add a valid entry as soon as possible in the config file or per console command!" msgstr "" -#: src/Module/Admin/Summary.php:87 +#: src/Module/Admin/Summary.php:88 msgid "The worker was never executed. Please check your database structure!" msgstr "" -#: src/Module/Admin/Summary.php:89 +#: src/Module/Admin/Summary.php:90 #, php-format msgid "The last worker execution was on %s UTC. This is older than one hour. Please check your crontab settings." msgstr "" -#: src/Module/Admin/Summary.php:94 +#: src/Module/Admin/Summary.php:95 #, php-format msgid "Friendica's configuration now is stored in config/local.config.php, please copy config/local-sample.config.php and move your config from .htconfig.php. See the Config help page for help with the transition." msgstr "" -#: src/Module/Admin/Summary.php:98 +#: src/Module/Admin/Summary.php:99 #, php-format msgid "Friendica's configuration now is stored in config/local.config.php, please copy config/local-sample.config.php and move your config from config/local.ini.php. See the Config help page for help with the transition." msgstr "" -#: src/Module/Admin/Summary.php:105 +#: src/Module/Admin/Summary.php:106 #, php-format msgid "%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." msgstr "" -#: src/Module/Admin/Summary.php:133 +#: src/Module/Admin/Summary.php:134 #, php-format msgid "Friendica's system.basepath was updated from '%s' to '%s'. Please remove the system.basepath from your db to avoid differences." msgstr "" -#: src/Module/Admin/Summary.php:143 +#: src/Module/Admin/Summary.php:144 #, php-format msgid "Friendica's current system.basepath '%s' is wrong and the config file '%s' isn't used." msgstr "" -#: src/Module/Admin/Summary.php:153 +#: src/Module/Admin/Summary.php:154 #, php-format msgid "Friendica's current system.basepath '%s' is not equal to the config file '%s'. Please fix your configuration." msgstr "" -#: src/Module/Admin/Summary.php:165 +#: src/Module/Admin/Summary.php:166 msgid "Message queues" msgstr "" -#: src/Module/Admin/Summary.php:168 +#: src/Module/Admin/Summary.php:169 msgid "Server Settings" msgstr "" -#: src/Module/Admin/Summary.php:186 +#: src/Module/Admin/Summary.php:210 msgid "Version" msgstr "" -#: src/Module/Admin/Summary.php:190 +#: src/Module/Admin/Summary.php:214 msgid "Active addons" msgstr "" +#: src/Module/Admin/Summary.php:217 +msgid "Enable new addons" +msgstr "" + #: src/Module/Admin/Themes/Details.php:49 src/Module/Admin/Themes/Index.php:57 #, php-format msgid "Theme %s disabled." @@ -8085,6 +8089,10 @@ msgstr "" msgid "Pending registrations" msgstr "" +#: src/Module/Moderation/Summary.php:70 +msgid "Registered accounts by type" +msgstr "" + #: src/Module/Moderation/Users/Active.php:29 #: src/Module/Moderation/Users/Index.php:29 #, php-format diff --git a/view/templates/admin/addons/index.tpl b/view/templates/admin/addons/index.tpl index 499217a883..e2a885aac3 100644 --- a/view/templates/admin/addons/index.tpl +++ b/view/templates/admin/addons/index.tpl @@ -12,7 +12,7 @@ {{$noplugshint}} {{else}} - {{$reload}} +

{{$reload}}

    {{foreach $addons as $p}}
  • diff --git a/view/templates/admin/summary.tpl b/view/templates/admin/summary.tpl index 117a06600f..d498bc5661 100644 --- a/view/templates/admin/summary.tpl +++ b/view/templates/admin/summary.tpl @@ -23,8 +23,8 @@
    {{$addons.0}}
    - {{foreach $addons.1 as $p}} -
    {{$p}}
    + {{foreach $addons.1 as $a}} +
    {{$a.1.name}}
    {{/foreach}}
    diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index f3ab89db3f..1415b5d726 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -3507,6 +3507,14 @@ section.help-content-wrapper li { #admin-summary-wrapper { padding-top: 10px; } +#admin-summary-wrapper h2 { + font-size: 21px; + padding-top: 13px; + padding-bottom: 8px; +} +#admin-summary-addons tr td:first-child { + width: clamp(30px, 20vw, 200px); +} #adminpage ul#addonslist, li.addon { list-style: none; diff --git a/view/theme/frio/templates/admin/summary.tpl b/view/theme/frio/templates/admin/summary.tpl index d96785430f..b8e1ee3589 100644 --- a/view/theme/frio/templates/admin/summary.tpl +++ b/view/theme/frio/templates/admin/summary.tpl @@ -5,7 +5,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later *}} -
    +

    {{$title}} - {{$page}}

    {{if $warningtext|count}} @@ -17,35 +17,36 @@ {{/if}}
    - {{* The work queues short statistic. *}} -
    -
    {{$queues.label}}
    -
    {{$queues.deferred}} - {{$queues.workerq}}
    -
    + {{* The work queues short statistic and the friendica version. *}} + + + + + + + + + +
    {{$queues.label}}{{$queues.deferred}} - {{$queues.workerq}}
    {{$version_label}}{{$platform}} '{{$codename}}' {{$VERSION}} - {{$build}}
    {{* List enabled addons. *}} -
    -
    -
    {{$addons.0}}
    -
    - {{foreach $addons.1 as $p}} - {{$p}}
    +
    +

    {{$addons.0}}

    + + {{foreach $addons.1 as $a}} + + + + {{/foreach}} - - - - {{* The Friendica version. *}} -
    -
    -
    {{$version_label}}
    -
    {{$platform}} '{{$codename}}' {{$VERSION}} - {{$build}}
    +
    {{$a.1.name}}{{$a.1.description}}
    +

    {{$link_enable_addons}}

    {{* Server Settings. *}} -
    -
    -
    {{$serversettings.label}}
    -
    +
    +

    {{$serversettings.label}}

    +
    @@ -63,6 +64,4 @@ -
    - diff --git a/view/theme/frio/templates/moderation/summary.tpl b/view/theme/frio/templates/moderation/summary.tpl index c20d07c009..d9b129e29e 100644 --- a/view/theme/frio/templates/moderation/summary.tpl +++ b/view/theme/frio/templates/moderation/summary.tpl @@ -5,35 +5,33 @@ * SPDX-License-Identifier: AGPL-3.0-or-later *}} -
    +

    {{$title}} - {{$page}}

    - {{* Number of pending registrations. *}} -
    -
    -
    {{$pending.0}}
    -
    {{$pending.1}}
    -
    +
    PHP
    + {{* Number of pending registrations. *}} + + + + - {{* Number of registered users *}} -
    -
    -
    {{$users.0}}
    -
    {{$users.1}}
    -
    + {{* Number of registered users *}} + + + + +
    {{$pending.0}}{{$pending.1}}
    {{$users.0}}{{$users.1}}
    {{* Account types of registered users. *}} - {{foreach $accounts as $p}} -
    -
    -
    {{$p.0}}
    -
    {{if $p.1}}{{$p.1}}{{else}}0{{/if}}
    -
    - {{/foreach}} - +

    {{$account_type_header}}

    + + {{foreach $accounts as $p}} + + + + + {{/foreach}} +
    {{$p.0}}{{if $p.1}}{{$p.1}}{{else}}0{{/if}}
    - -
    -
    From 92eedc70bf3399fa508eb78a3efe52a5e18673ae Mon Sep 17 00:00:00 2001 From: Tealk Date: Sun, 11 Jan 2026 22:59:38 +0100 Subject: [PATCH 009/197] add gnome colored sheme to frio --- view/theme/frio/scheme/gnome.css | 431 +++++++++++++++++++++++++++++++ view/theme/frio/scheme/gnome.php | 29 +++ 2 files changed, 460 insertions(+) create mode 100644 view/theme/frio/scheme/gnome.css create mode 100644 view/theme/frio/scheme/gnome.php diff --git a/view/theme/frio/scheme/gnome.css b/view/theme/frio/scheme/gnome.css new file mode 100644 index 0000000000..9668e782d8 --- /dev/null +++ b/view/theme/frio/scheme/gnome.css @@ -0,0 +1,431 @@ +:root { + color-scheme: light dark; + + /* Accent Colors (from PHP) */ + --accent-color: $link_color; + --accent-hover: $menu_background_hover_color; + + /* Light Mode - GNOME Adwaita */ + --bg-primary: #ffffff; + --bg-secondary: #ebebed; + --bg-tertiary: #f3f3f5; + + --text-primary: #1d1d20; + --text-secondary: #5e5c64; + --text-disabled: #9a9996; + + --border-color: #cdc7c2; + --shadow: rgba(0, 0, 0, 0.1); +} + +/* Dark Mode - GNOME Adwaita Dark */ +@media (prefers-color-scheme: dark) { + :root { + --bg-primary: #1d1d20; + --bg-secondary: #2e2e32; + --bg-tertiary: #28282c; + + --text-primary: #ffffff; + --text-secondary: #c9c0c0; + --text-disabled: #8c8c8d; + + --border-color: #1b1b1b; + --shadow: rgba(0, 0, 0, 0.3); + } +} + +/* Body */ +body { + background-color: var(--bg-primary); + color: var(--text-primary); + transition: background-color 0.3s ease, color 0.3s ease; +} + +section > .generic-page-wrapper, +.videos-content-wrapper, +.suggest-content-wrapper, +.help-content-wrapper, +.match-content-wrapper, +.dirfind-content-wrapper, +.delegation-content-wrapper, +.notes-content-wrapper, +.message-content-wrapper, +.apps-content-wrapper, +#adminpage, +.delegate-content-wrapper, +.uexport-content-wrapper, +.dfrn_request-content-wrapper, +.friendica-content-wrapper, +.credits-content-wrapper, +.nocircle-content-wrapper, +.profperm-content-wrapper, +.invite-content-wrapper, +.tos-content-wrapper, +.fsuggest-content-wrapper, +.help-block { + color: var(--text-primary); +} + +div.login-form, +div.login-form label { + background-color: var(--bg-secondary) !important; + color: var(--text-primary) !important; +} + +/* Navigation */ +header #banner #logo-img, +.navbar-brand #logo-img { + background-color: var(--text-primary); +} + +#topbar-first, +.navbar { + background-color: var(--bg-secondary) !important; + border-bottom: 1px solid var(--border-color); + + button { + color: var(--text-primary) !important; + } + + #nav-notifications-menu { + + .dropdown-header, + a, + .time { + color: var(--text-primary) !important; + } + + li.notif-entry { + color: var(--text-primary); + border-bottom: 1px solid var(--accent-color); + + &:hover { + background-color: var(--bg-tertiary); + border-left: 3px solid var(--accent-hover); + } + } + + li.notification-unseen { + border-left: 3px solid var(--accent-color); + background-color: unset; + } + + li.notif-entry:hover { + background-color: unset; + border-left: 3px solid var(--accent-hover); + } + } + + .nav > .open > a, + .nav > .open > button, + .nav > .open > button:focus { + background-color: var(--bg-tertiary) !important; + } + + .nav > li > button:not(#main-menu):hover { + background-color: var(--bg-tertiary) !important; + } + + .nav > li { + & > a, + & > button { + color: var(--text-primary) !important; + + &:hover { + background-color: var(--bg-tertiary); + } + } + } +} + +nav.navbar { + .nav > li { + & > a, + & > button { + color: var(--text-primary) !important; + + &:hover { + background-color: var(--bg-tertiary) + } + } + } +} + +#topbar-second { + background-color: var(--bg-secondary); + border-color: 1px solid var(--border-color); +} + +/* Nav Icons */ +.nav-link, +.navbar-brand, +#nav-user-linkmenu { + i { + color: var(--text-primary); + } +} + +/* Links */ +a { + color: var(--accent-color); + transition: color 0.2s; + + &:hover { + color: var(--accent-hover); + } +} + +/* Buttons */ +.btn-default { + background-color: var(--bg-secondary) !important; + border-color: var(--bg-secondary) !important; + + &:hover, + &:focus { + background-color: var(--bg-tertiary) !important; + border-color: var(--bg-tertiary) !important; + } +} + +.btn-primary, +button.btn-primary { + background-color: var(--accent-color) !important; + border-color: var(--accent-color) !important; + + &:hover, + &:focus { + background-color: var(--accent-hover) !important; + border-color: var(--accent-hover) !important; + } +} + +.btn { + background-color: var(--bg-tertiary); + color: var(--text-primary) !important; +} + +/* Cards & Panels */ +.panel, +.wall-item-container, +.card { + background-color: var(--bg-secondary); + border-color: var(--border-color); + border-radius: 12px; + transition: background-color 0.3s, border-color 0.3s; +} + +.desktop-view .wall-item-container .wall-item-content a { + color: var(--text-secondary); +} + +.wall-item-container:hover .wall-item-content a { + color: var(--accent-color); +} + +.panel-footer { + background-color: var(--bg-secondary); + border-top: 1px solid var(--border-color); +} + +/* Input Fields */ +input, +textarea, +select, +.form-control { + background-color: var(--bg-primary); + color: var(--text-primary); + border-color: var(--accent-color); + transition: background-color 0.3s, color 0.3s, border-color 0.3s; + + &:focus { + border-color: var(--accent-color); + box-shadow: 0 0 0 2px rgba(53, 132, 228, 0.2); + } +} + +/* Comments */ +.comment-fake-form, +.wall-item-comment-wrapper { + padding: 10px; + border-top: 1px solid var(--accent-color); + background-color: var(--bg-secondary); + border-radius: 0 0 4px 4px; + margin-bottom: 0; +} + +/* Well */ +.well { + background-image: none; + border: none; + background-color: var(--bg-tertiary); +} + +/* Sidebar */ +#aside_spacer { + background-color: var(--bg-secondary); + transition: background-color 0.3s; +} + +aside { + background-color: transparent; + + nav { + background-color: var(--bg-secondary); + } + + .widget, + .contact-block-content { + color: var(--text-secondary); + + li a, + li a:hover { + color: var(--text-primary); + } + } +} + +#offcanvasUsermenu { + background-color: var(--bg-secondary); + + li, + a { + background-color: transparent; + color: var(--text-primary); + } + + li.list-group-item { + border: none; + } + + li.divider { + background-color: var(--accent-color); + + hr { + display: none; + border-color: var(--accent-color); + } + } +} + +@media screen and (max-width: 990px) { + aside { + background-color: var(--bg-secondary); + } +} + +/* Text Colors */ +.text-muted { + color: var(--text-secondary) !important; +} + +/* Dropdowns */ +.dropdown-menu { + background-color: var(--bg-secondary) !important; + border-color: var(--border-color) !important; + + li a, + li .btn-link { + color: var(--text-primary) !important; + } + + li > a { + border-left: 3px solid var(--accent-color) !important; + } +} + +.dropdown-item { + color: var(--text-primary); + + &:hover { + background-color: var(--bg-tertiary); + } +} + +/* Modals */ +.modal-content { + background-color: var(--bg-primary); + border-color: var(--border-color); +} + +.modal-header { + border-bottom-color: var(--border-color); +} + +.modal-footer { + border-top-color: var(--border-color); +} + +/* Navigation Links */ +.nav > li > a { + &:hover { + text-decoration: none; + background-color: var(--bg-tertiary); + } +} + +/* Wall Items */ +.wall-item-name-link { + color: var(--text-primary); + font-weight: bold; +} + +.wall-item-ago { + color: var(--text-disabled); +} + +.comment-edit-form .preview { + background-color: var(--bg-secondary) !important; + border: none !important; +} + +pre, code { + color: var(--text-primary); + background-color: var(--bg-tertiary); + border-color: var(--border-color); +} + +.acpopup { + color: var(--text-primary); + background-color: var(--bg-secondary); + + .textcomplete-item.active > a { + background-color: var(--bg-tertiary) !important; + } +} + + +.table-striped > tbody > tr:nth-of-type(2n+1) { + background-color: var(--bg-tertiary); +} + +.fg-emoji-nav { + background-color: var(--bg-primary) !important; + + ul li a:hover { + background-color: var(--bg-tertiary) !important; + } +} + +.fg-emoji-container { + background-color: var(--bg-primary) !important; + + input { + background-color: var(--bg-secondary) !important; + } +} + +.fg-picker-special-buttons a { + background-color: var(--accent-color) !important; +} + +.fg-emoji-picker-search .fg-emoji-picker-search-icon { + background-color: var(--bg-secondary) !important; +} + +.fg-emoji-list li a { + background-color: var(--bg-primary) !important; + + &:hover { + background-color: var(--accent-hover) !important; + } +} diff --git a/view/theme/frio/scheme/gnome.php b/view/theme/frio/scheme/gnome.php new file mode 100644 index 0000000000..46d6838b13 --- /dev/null +++ b/view/theme/frio/scheme/gnome.php @@ -0,0 +1,29 @@ + tealk@friendica.rollenspiel.monster + * Overwrites: nav_bg, nav_icon_color, link_color, background_color, background_image, login_bg_color, contentbg_transp + * Accented: yes + */ + +require_once 'view/theme/frio/php/PHPColors/Color.php'; + +$accentColor = new Color($scheme_accent); + +$menu_background_hover_color = '#' . $accentColor->darken(10); +$nav_bg = '#2c2c34'; +$link_color = '#' . $accentColor->lighten(1); +$nav_icon_color = '#d4d4d4'; +$background_color = '#1b1b1b'; +$contentbg_transp = '0'; +$font_color = '#cccccc'; +$font_color_darker = '#acacac'; +$font_color_lighter = '#444444'; +$background_image = ''; From c9c129aa49e34fce4e4f3331e6335fd9168c4b0a Mon Sep 17 00:00:00 2001 From: Tealk Date: Sun, 11 Jan 2026 23:17:26 +0100 Subject: [PATCH 010/197] add Licence to css file --- view/theme/frio/scheme/gnome.css | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/view/theme/frio/scheme/gnome.css b/view/theme/frio/scheme/gnome.css index 9668e782d8..2604f2a628 100644 --- a/view/theme/frio/scheme/gnome.css +++ b/view/theme/frio/scheme/gnome.css @@ -1,3 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2010-2024 the Friendica project + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +/* + Licence : AGPL + Created on : 18.11.2025 + Author : Daniel Buck tealk@friendica.rollenspiel.monster +*/ :root { color-scheme: light dark; From fc566bdccf5a6616215265f6ccbeadf45b0ed7da Mon Sep 17 00:00:00 2001 From: Tealk Date: Sun, 11 Jan 2026 23:20:20 +0100 Subject: [PATCH 011/197] fix code_standards_check --- view/theme/frio/scheme/gnome.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/view/theme/frio/scheme/gnome.php b/view/theme/frio/scheme/gnome.php index 46d6838b13..70df62b17e 100644 --- a/view/theme/frio/scheme/gnome.php +++ b/view/theme/frio/scheme/gnome.php @@ -18,12 +18,12 @@ require_once 'view/theme/frio/php/PHPColors/Color.php'; $accentColor = new Color($scheme_accent); $menu_background_hover_color = '#' . $accentColor->darken(10); -$nav_bg = '#2c2c34'; -$link_color = '#' . $accentColor->lighten(1); -$nav_icon_color = '#d4d4d4'; -$background_color = '#1b1b1b'; -$contentbg_transp = '0'; -$font_color = '#cccccc'; -$font_color_darker = '#acacac'; -$font_color_lighter = '#444444'; -$background_image = ''; +$nav_bg = '#2c2c34'; +$link_color = '#' . $accentColor->lighten(1); +$nav_icon_color = '#d4d4d4'; +$background_color = '#1b1b1b'; +$contentbg_transp = '0'; +$font_color = '#cccccc'; +$font_color_darker = '#acacac'; +$font_color_lighter = '#444444'; +$background_image = ''; From ffe9d061044c6685f236147ca8a5e24e8d22c78b Mon Sep 17 00:00:00 2001 From: Tealk Date: Mon, 12 Jan 2026 11:36:45 +0100 Subject: [PATCH 012/197] remove space --- view/theme/frio/scheme/gnome.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view/theme/frio/scheme/gnome.php b/view/theme/frio/scheme/gnome.php index 70df62b17e..0b9eca39b2 100644 --- a/view/theme/frio/scheme/gnome.php +++ b/view/theme/frio/scheme/gnome.php @@ -8,7 +8,7 @@ * * Name: Gnome * Licence: AGPL - * Author: Daniel Buck tealk@friendica.rollenspiel.monster + * Author: Daniel Buck tealk@friendica.rollenspiel.monster * Overwrites: nav_bg, nav_icon_color, link_color, background_color, background_image, login_bg_color, contentbg_transp * Accented: yes */ From c6104eac12cf103e14e3044623435dac8f715e94 Mon Sep 17 00:00:00 2001 From: Tealk Date: Thu, 15 Jan 2026 17:00:47 +0100 Subject: [PATCH 013/197] some light link fixes --- view/theme/frio/scheme/gnome.css | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/view/theme/frio/scheme/gnome.css b/view/theme/frio/scheme/gnome.css index 2604f2a628..ef56636934 100644 --- a/view/theme/frio/scheme/gnome.css +++ b/view/theme/frio/scheme/gnome.css @@ -186,6 +186,15 @@ a { } } +.desktop-view .wall-item-container .fakelink, +.desktop-view .toplevel_item .fakelink { + color: var(--text-primary); +} + +.media .time { + color: var(--text-secondary); +} + /* Buttons */ .btn-default { background-color: var(--bg-secondary) !important; @@ -229,6 +238,10 @@ button.btn-primary { color: var(--text-secondary); } +.wall-item-container .wall-item-responses a { + color: var(--text-secondary) !important; +} + .wall-item-container:hover .wall-item-content a { color: var(--accent-color); } @@ -378,10 +391,24 @@ aside { .wall-item-name-link { color: var(--text-primary); font-weight: bold; + + span.wall-item-name { + color: var(--text-primary); + } } .wall-item-ago { - color: var(--text-disabled); + color: var(--text-primary); + + time { + color: var(--text-primary) !important; + } +} + +.wall-item-actions { + button { + color: var(--text-primary); + } } .comment-edit-form .preview { @@ -404,7 +431,6 @@ pre, code { } } - .table-striped > tbody > tr:nth-of-type(2n+1) { background-color: var(--bg-tertiary); } From c71f81549bd8304d95fee7360b7c76ad1087eb29 Mon Sep 17 00:00:00 2001 From: Django Date: Sun, 18 Jan 2026 01:30:49 -0700 Subject: [PATCH 014/197] Add Access-Control-Allow-Origin header Added CORS header to allow requests from any origin. --- src/Module/ActivityPub/Inbox.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Module/ActivityPub/Inbox.php b/src/Module/ActivityPub/Inbox.php index f654b3853b..f5574421e5 100644 --- a/src/Module/ActivityPub/Inbox.php +++ b/src/Module/ActivityPub/Inbox.php @@ -49,6 +49,9 @@ class Inbox extends BaseApi throw new \Friendica\Network\HTTPException\ForbiddenException(); } $inbox = ActivityPub\ClientToServer::getInbox($uid, $page, $request['max_id'] ?? null); + + // Relaxed CORS header already authorized + header('Access-Control-Allow-Origin: *'); } else { $inbox = ActivityPub\ClientToServer::getPublicInbox($uid, $page, $request['max_id'] ?? null); } From 02c19adfdc7ee10d11be41a0758b2ce6c34e21e1 Mon Sep 17 00:00:00 2001 From: Tealk Date: Sun, 18 Jan 2026 11:37:02 +0100 Subject: [PATCH 015/197] remove space --- view/theme/frio/scheme/gnome.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view/theme/frio/scheme/gnome.css b/view/theme/frio/scheme/gnome.css index ef56636934..7906c127b3 100644 --- a/view/theme/frio/scheme/gnome.css +++ b/view/theme/frio/scheme/gnome.css @@ -7,7 +7,7 @@ /* Licence : AGPL Created on : 18.11.2025 - Author : Daniel Buck tealk@friendica.rollenspiel.monster + Author : Daniel Buck tealk@friendica.rollenspiel.monster */ :root { color-scheme: light dark; From ccb54a380183ddce5b08924a7332342f7e267451 Mon Sep 17 00:00:00 2001 From: Tealk Date: Sun, 18 Jan 2026 11:37:12 +0100 Subject: [PATCH 016/197] fix eventcard colore --- view/theme/frio/scheme/gnome.css | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/view/theme/frio/scheme/gnome.css b/view/theme/frio/scheme/gnome.css index 7906c127b3..0036003252 100644 --- a/view/theme/frio/scheme/gnome.css +++ b/view/theme/frio/scheme/gnome.css @@ -251,6 +251,16 @@ button.btn-primary { border-top: 1px solid var(--border-color); } +.event-card { + .event-card-title { + color: var(--text-primary); + } + + .event-card-content { + color: var(--text-secondary); + } +} + /* Input Fields */ input, textarea, From a64e8e20d5ea11d302af41c250b2089990e255cc Mon Sep 17 00:00:00 2001 From: Django Date: Sun, 18 Jan 2026 17:07:58 -0700 Subject: [PATCH 017/197] Include getPublicInbox in CORS header for inbox response getPublicInbox seems to correspond to the sharedInbox endpoint, so this is worth including for c2s clients --- src/Module/ActivityPub/Inbox.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Module/ActivityPub/Inbox.php b/src/Module/ActivityPub/Inbox.php index f5574421e5..80062683d9 100644 --- a/src/Module/ActivityPub/Inbox.php +++ b/src/Module/ActivityPub/Inbox.php @@ -50,12 +50,13 @@ class Inbox extends BaseApi } $inbox = ActivityPub\ClientToServer::getInbox($uid, $page, $request['max_id'] ?? null); - // Relaxed CORS header already authorized - header('Access-Control-Allow-Origin: *'); } else { $inbox = ActivityPub\ClientToServer::getPublicInbox($uid, $page, $request['max_id'] ?? null); } + // Relaxed CORS header already authorized + header('Access-Control-Allow-Origin: *'); + $this->jsonExit($inbox, 'application/activity+json'); } From 0cd582fddd008f5b09e345ce065318a5954fd3ba Mon Sep 17 00:00:00 2001 From: Django Date: Tue, 20 Jan 2026 20:26:04 -0700 Subject: [PATCH 018/197] Remove unnecessary line in Inbox.php --- src/Module/ActivityPub/Inbox.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Module/ActivityPub/Inbox.php b/src/Module/ActivityPub/Inbox.php index 80062683d9..001bd31157 100644 --- a/src/Module/ActivityPub/Inbox.php +++ b/src/Module/ActivityPub/Inbox.php @@ -49,7 +49,6 @@ class Inbox extends BaseApi throw new \Friendica\Network\HTTPException\ForbiddenException(); } $inbox = ActivityPub\ClientToServer::getInbox($uid, $page, $request['max_id'] ?? null); - } else { $inbox = ActivityPub\ClientToServer::getPublicInbox($uid, $page, $request['max_id'] ?? null); } From 99b497a0c354617c3b42081a4230ea5995cd606d Mon Sep 17 00:00:00 2001 From: "Marcus F." Date: Thu, 22 Jan 2026 21:02:24 +0100 Subject: [PATCH 019/197] Always show all personal notifications, remove related link to toggle --- src/Module/Notifications/Notifications.php | 25 ++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/Module/Notifications/Notifications.php b/src/Module/Notifications/Notifications.php index b2105dd88e..8d6195d909 100644 --- a/src/Module/Notifications/Notifications.php +++ b/src/Module/Notifications/Notifications.php @@ -44,32 +44,32 @@ class Notifications extends BaseNotifications public function getNotifications() { $notificationHeader = ''; - $notifications = []; + $notifications = []; $factory = $this->formattedNotifyFactory; if (($this->args->get(1) == 'network')) { $notificationHeader = $this->t('Network Notifications'); $notifications = [ - 'ident' => FormattedNotify::NETWORK, + 'ident' => FormattedNotify::NETWORK, 'notifications' => $factory->getNetworkList($this->showAll, $this->firstItemNum, self::ITEMS_PER_PAGE), ]; } elseif (($this->args->get(1) == 'system')) { $notificationHeader = $this->t('System Notifications'); $notifications = [ - 'ident' => FormattedNotify::SYSTEM, + 'ident' => FormattedNotify::SYSTEM, 'notifications' => $factory->getSystemList($this->showAll, $this->firstItemNum, self::ITEMS_PER_PAGE), ]; } elseif (($this->args->get(1) == 'personal')) { $notificationHeader = $this->t('Personal Notifications'); $notifications = [ - 'ident' => FormattedNotify::PERSONAL, - 'notifications' => $factory->getPersonalList($this->showAll, $this->firstItemNum, self::ITEMS_PER_PAGE), + 'ident' => FormattedNotify::PERSONAL, + 'notifications' => $factory->getPersonalList(true, $this->firstItemNum, self::ITEMS_PER_PAGE), ]; } elseif (($this->args->get(1) == 'home')) { $notificationHeader = $this->t('Home Notifications'); $notifications = [ - 'ident' => FormattedNotify::HOME, + 'ident' => FormattedNotify::HOME, 'notifications' => $factory->getHomeList($this->showAll, $this->firstItemNum, self::ITEMS_PER_PAGE), ]; } else { @@ -97,7 +97,7 @@ class Notifications extends BaseNotifications $notificationResult = $this->getNotifications(); $notifications = $notificationResult['notifications'] ?? []; - $notificationHeader = $notificationResult['header'] ?? ''; + $notificationHeader = $notificationResult['header'] ?? ''; if (!empty($notifications['notifications'])) { $notificationTemplates = [ @@ -127,10 +127,13 @@ class Notifications extends BaseNotifications $notificationNoContent = $this->t('No more %s notifications.', $notificationResult['ident']); } - $notificationShowLink = [ - 'href' => ($this->showAll ? 'notifications/' . $notifications['ident'] : 'notifications/' . $notifications['ident'] . '?show=all'), - 'text' => ($this->showAll ? $this->t('Show unread') : $this->t('Show all')), - ]; + $notificationShowLink = []; + if ($notifications['ident'] != "personal") { + $notificationShowLink = [ + 'href' => ($this->showAll ? 'notifications/' . $notifications['ident'] : 'notifications/' . $notifications['ident'] . '?show=all'), + 'text' => ($this->showAll ? $this->t('Show unread') : $this->t('Show all')), + ]; + } return $this->printContent($notificationHeader, $notificationContent, $notificationNoContent, $notificationShowLink); } From a01fb9cb6691e31d988a9dc9ad0db0c2305476bc Mon Sep 17 00:00:00 2001 From: "Marcus F." Date: Sat, 24 Jan 2026 10:41:07 +0100 Subject: [PATCH 020/197] Switch approach to change BaseNotifications instead --- src/Module/BaseNotifications.php | 2 +- src/Module/Notifications/Notifications.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Module/BaseNotifications.php b/src/Module/BaseNotifications.php index 0445075995..0366ed0bb3 100644 --- a/src/Module/BaseNotifications.php +++ b/src/Module/BaseNotifications.php @@ -155,7 +155,7 @@ abstract class BaseNotifications extends BaseModule foreach (self::URL_TYPES as $type => $url) { $tabs[] = [ 'label' => $this->t(self::PRINT_TYPES[$type]), - 'url' => 'notifications/' . $url, + 'url' => 'notifications/' . $url . (($url == "personal") ? "?show=all" : ""), 'sel' => (($selected == $url) ? 'active' : ''), 'id' => $type . '-tab', 'accesskey' => self::ACCESS_KEYS[$type], diff --git a/src/Module/Notifications/Notifications.php b/src/Module/Notifications/Notifications.php index 8d6195d909..859bff76a7 100644 --- a/src/Module/Notifications/Notifications.php +++ b/src/Module/Notifications/Notifications.php @@ -64,7 +64,7 @@ class Notifications extends BaseNotifications $notificationHeader = $this->t('Personal Notifications'); $notifications = [ 'ident' => FormattedNotify::PERSONAL, - 'notifications' => $factory->getPersonalList(true, $this->firstItemNum, self::ITEMS_PER_PAGE), + 'notifications' => $factory->getPersonalList($this->showAll, $this->firstItemNum, self::ITEMS_PER_PAGE), ]; } elseif (($this->args->get(1) == 'home')) { $notificationHeader = $this->t('Home Notifications'); From eb48c7888c9d066f02944aeba10cf97055b55f31 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Tue, 27 Jan 2026 09:00:29 +0100 Subject: [PATCH 021/197] added 2026.04 to CHANGELOG --- CHANGELOG | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index a33ce98aff..0daeb9eb3d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,10 @@ +Version 2026.04 (unreleased) + Friendica Core + + Friendica Addons + + Closed Issues + Version 2026.01 (2026-01-27) Friendica Core Updates to the translations From 5c0e024f033d2d7f5cbfe8f63a8f278870297432 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Tue, 27 Jan 2026 09:01:00 +0100 Subject: [PATCH 022/197] bump version 2026.04-dev --- VERSION | 2 +- database.sql | 2 +- src/App.php | 2 +- view/lang/C/messages.po | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/VERSION b/VERSION index 62f5eb2b61..0a016e46f1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2026.01 +2026.04-dev diff --git a/database.sql b/database.sql index b537f0cf21..209a9068e6 100644 --- a/database.sql +++ b/database.sql @@ -1,5 +1,5 @@ -- ------------------------------------------ --- Friendica 2026.01 (Blutwurz) +-- Friendica 2026.04-dev (Blutwurz) -- DB_UPDATE_VERSION 1586 -- ------------------------------------------ diff --git a/src/App.php b/src/App.php index eb1657856e..9d530d077b 100644 --- a/src/App.php +++ b/src/App.php @@ -67,7 +67,7 @@ class App { const PLATFORM = 'Friendica'; const CODENAME = 'Blutwurz'; - const VERSION = '2026.01'; + const VERSION = '2026.04-dev'; /** * @internal diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index edc20183fb..0a672a1782 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -6,7 +6,7 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: 2026.01\n" +"Project-Id-Version: 2026.04-dev\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-01-04 20:49+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" From 4603e9c5d5fe9d449fbe2a2b4df09b16cf1358f9 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 23 Jan 2026 04:43:12 +0000 Subject: [PATCH 023/197] Check to store the user defined channel cache for all posts --- src/Content/Conversation/Entity/UserDefinedChannel.php | 6 ++++++ src/Content/Conversation/Factory/ChannelPost.php | 8 ++++++-- .../Conversation/Repository/UserDefinedChannel.php | 10 ++++++++-- src/Model/Item.php | 8 ++++---- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/Content/Conversation/Entity/UserDefinedChannel.php b/src/Content/Conversation/Entity/UserDefinedChannel.php index 6ef6d67dac..6cba387fb0 100644 --- a/src/Content/Conversation/Entity/UserDefinedChannel.php +++ b/src/Content/Conversation/Entity/UserDefinedChannel.php @@ -9,4 +9,10 @@ namespace Friendica\Content\Conversation\Entity; class UserDefinedChannel extends Channel { + const CIRCLE_GLOBAL = 0; + const CIRCLE_ACTIVITY = -5; + const CIRCLE_POSTS = -4; + const CIRCLE_CREATION = -3; + const CIRCLE_FOLLOWING = -1; + const CIRCLE_FOLLOWERS = -2; } diff --git a/src/Content/Conversation/Factory/ChannelPost.php b/src/Content/Conversation/Factory/ChannelPost.php index c4631fefa7..c554d16a2b 100644 --- a/src/Content/Conversation/Factory/ChannelPost.php +++ b/src/Content/Conversation/Factory/ChannelPost.php @@ -9,11 +9,13 @@ declare(strict_types=1); namespace Friendica\Content\Conversation\Factory; +use Friendica\Content\Conversation\Entity\UserDefinedChannel as UserDefinedChannelEntity; use Friendica\Content\Conversation\Repository\UserDefinedChannel; use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\L10n; use Friendica\Database\Database; use Friendica\Model\Contact; +use Friendica\Model\Item; use Friendica\Model\Post; use Friendica\Model\Tag; use Psr\Log\LoggerInterface; @@ -56,11 +58,12 @@ final class ChannelPost * system's channel caching is enabled and matching channels are found. * * @param array $engagement post-engagement record + * @param int $gravity Gravity of the post * @param int $uid User id context. * @param int $reshare_id Optional reshare id. * @return void */ - public function add(array $engagement, int $uid, int $reshare_id = 0): void + public function add(array $engagement, int $gravity, int $uid, int $reshare_id = 0): void { if (!$this->config->get('system', 'channel_cache')) { return; @@ -80,8 +83,9 @@ final class ChannelPost $language = $engagement['language'] !== L10n::UNDETERMINED_LANGUAGE ? $engagement['language'] : ''; $tags = array_column(Tag::getByURIId($engagement['uri-id'], [Tag::HASHTAG]), 'name'); + $circles = ($gravity != Item::GRAVITY_PARENT) ? [UserDefinedChannelEntity::CIRCLE_CREATION, UserDefinedChannelEntity::CIRCLE_POSTS, UserDefinedChannelEntity::CIRCLE_ACTIVITY] : []; - $channels = $this->channelRepository->getMatchingChannels($engagement['searchtext'], $language, $tags, $engagement['media-type'], $engagement['owner-id'], $reshare_id, $uids); + $channels = $this->channelRepository->getMatchingChannels($engagement['searchtext'], $language, $tags, $engagement['media-type'], $engagement['owner-id'], $reshare_id, $uids, $circles); if (!($channels instanceof \Friendica\Content\Conversation\Collection\UserDefinedChannels) || $channels->count() === 0) { $this->logger->debug('No channels found', ['uri-id' => $engagement['uri-id'], 'uids' => $uids, 'reshare_id' => $reshare_id]); return; diff --git a/src/Content/Conversation/Repository/UserDefinedChannel.php b/src/Content/Conversation/Repository/UserDefinedChannel.php index e1da39a2f6..8e07f1c418 100644 --- a/src/Content/Conversation/Repository/UserDefinedChannel.php +++ b/src/Content/Conversation/Repository/UserDefinedChannel.php @@ -316,9 +316,10 @@ class UserDefinedChannel extends BaseRepository * @param int $owner_id Owner contact id. * @param int $reshare_id Reshare contact id. * @param array $uids User IDs to filter channels. + * @param array $circles circle IDs to filter channels. * @return UserDefinedChannels|null Collection of matching channels or null. */ - public function getMatchingChannels(string $searchtext, string $language, array $tags, int $media_type, int $owner_id, int $reshare_id, array $uids): ?UserDefinedChannels + public function getMatchingChannels(string $searchtext, string $language, array $tags, int $media_type, int $owner_id, int $reshare_id, array $uids, array $circles): ?UserDefinedChannels { if (!in_array($language, User::getLanguages())) { $this->logger->debug('Unwanted language found. No matched channel found.', ['language' => $language, 'searchtext' => $searchtext]); @@ -327,7 +328,12 @@ class UserDefinedChannel extends BaseRepository $disposableFullTextSearch = new DisposableFullTextSearch($this->db, $searchtext); - $filteredChannels = $this->select(['uid' => $uids, 'valid' => true])->filter( + $condition = ['uid' => $uids, 'valid' => true]; + if ($circles) { + $condition = DBA::mergeConditions($condition, ['circle' => $circles]); + } + + $filteredChannels = $this->select($condition)->filter( function (UserDefinedChannelEntity $channel) use ($owner_id, $reshare_id, $language, $tags, $media_type, $disposableFullTextSearch, $searchtext) { if ( ($channel->circle > 0) diff --git a/src/Model/Item.php b/src/Model/Item.php index 0153ea093d..7680ed6cde 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -1196,13 +1196,13 @@ class Item DI::logger()->debug('Post accepted for channels', ['uri-id' => $uri_id, 'uid' => $uid, 'network' => $item['network']]); if (($item['gravity'] === self::GRAVITY_ACTIVITY) && ($item['verb'] === Activity::ANNOUNCE) && ($item['parent-uri-id'] === $item['thr-parent-id'])) { - DI::ChannelPost()->add($engagement, $uid, $item['author-id']); + DI::ChannelPost()->add($engagement, self::GRAVITY_PARENT, $uid, $item['author-id']); DI::SystemChannelPost()->add($engagement, self::GRAVITY_PARENT, $uid, $item['network'], $item['author-id']); } else { if ($item['origin']) { - DI::ChannelPost()->add($engagement, $uid, $item['author-id']); - } elseif ($item['gravity'] === self::GRAVITY_PARENT) { - DI::ChannelPost()->add($engagement, $uid); + DI::ChannelPost()->add($engagement, $item['gravity'], $uid, $item['author-id']); + } else { + DI::ChannelPost()->add($engagement, $item['gravity'], $uid); } DI::SystemChannelPost()->add($engagement, $item['gravity'], $uid, $item['network']); } From 8c27953d48fe4c5e16f57c41db4dce5d94d5f738 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Wed, 28 Jan 2026 06:31:32 +0100 Subject: [PATCH 024/197] Fix: syntax error in SMARTY template When viewing a contact in Friendica 2026.04-dev I encountered a syntax error in the `contact_edit` template. Adding the missing `fetchoutbox` fixes it and seems what was supposed to be there without digging deeper into the calling PHP files. --- view/templates/contact_edit.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view/templates/contact_edit.tpl b/view/templates/contact_edit.tpl index b6c22a63b2..aa1b174611 100644 --- a/view/templates/contact_edit.tpl +++ b/view/templates/contact_edit.tpl @@ -27,7 +27,7 @@ {{if $lblsuggest}}
  • {{$contact_actions.suggest.label}}
  • {{/if}} {{if $poll_enabled}}
  • {{$contact_actions.update.label}}
  • {{/if}} {{if $contact_actions.updateprofile}}
  • {{$contact_actions.updateprofile.label}}
  • {{/if}} - {{if $contact_actions.}}
  • {{$contact_actions.fetchoutbox.label}}
  • {{/if}} + {{if $contact_actions.fetchoutbox}}
  • {{$contact_actions.fetchoutbox.label}}
  • {{/if}}
  • {{$contact_actions.block.label}}
  • {{$contact_actions.ignore.label}}
  • From 8d64ef115fbc8d28f93d56392a778a57571a1840 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 28 Jan 2026 11:00:03 +0000 Subject: [PATCH 025/197] Quote check is removed --- src/Factory/Api/Mastodon/Notification.php | 5 +- src/Factory/Api/Mastodon/Status.php | 61 +++---------------- src/Module/Api/Friendica/Statuses/Dislike.php | 3 +- .../Api/Friendica/Statuses/Undislike.php | 3 +- src/Module/Api/Mastodon/Accounts/Statuses.php | 4 +- src/Module/Api/Mastodon/Bookmarks.php | 4 +- src/Module/Api/Mastodon/Favourited.php | 4 +- src/Module/Api/Mastodon/Notifications.php | 5 +- src/Module/Api/Mastodon/Search.php | 6 +- src/Module/Api/Mastodon/Statuses.php | 6 +- src/Module/Api/Mastodon/Statuses/Bookmark.php | 2 +- src/Module/Api/Mastodon/Statuses/Context.php | 11 ++-- .../Api/Mastodon/Statuses/Favourite.php | 3 +- src/Module/Api/Mastodon/Statuses/Mute.php | 3 +- src/Module/Api/Mastodon/Statuses/Pin.php | 3 +- src/Module/Api/Mastodon/Statuses/Reblog.php | 3 +- .../Api/Mastodon/Statuses/Unbookmark.php | 3 +- .../Api/Mastodon/Statuses/Unfavourite.php | 3 +- src/Module/Api/Mastodon/Statuses/Unmute.php | 3 +- src/Module/Api/Mastodon/Statuses/Unpin.php | 3 +- src/Module/Api/Mastodon/Statuses/Unreblog.php | 3 +- src/Module/Api/Mastodon/Timelines/Home.php | 4 +- .../Api/Mastodon/Timelines/ListTimeline.php | 4 +- .../Api/Mastodon/Timelines/PublicTimeline.php | 4 +- src/Module/Api/Mastodon/Timelines/Tag.php | 4 +- src/Module/Api/Mastodon/Trends/Statuses.php | 4 +- src/Module/BaseApi.php | 11 ---- 27 files changed, 41 insertions(+), 131 deletions(-) diff --git a/src/Factory/Api/Mastodon/Notification.php b/src/Factory/Api/Mastodon/Notification.php index 4b78a90b8a..c235451a71 100644 --- a/src/Factory/Api/Mastodon/Notification.php +++ b/src/Factory/Api/Mastodon/Notification.php @@ -33,12 +33,11 @@ class Notification extends BaseFactory /** * @param NotificationEntity $Notification - * @param bool $display_quotes Display quoted posts * * @return MstdnNotification * @throws UnexpectedNotificationTypeException */ - public function createFromNotification(NotificationEntity $Notification, bool $display_quotes): MstdnNotification + public function createFromNotification(NotificationEntity $Notification): MstdnNotification { $type = self::getType($Notification); @@ -50,7 +49,7 @@ class Notification extends BaseFactory if ($Notification->targetUriId) { try { - $status = $this->mstdnStatusFactory->createFromUriId($Notification->targetUriId, $Notification->uid, $display_quotes); + $status = $this->mstdnStatusFactory->createFromUriId($Notification->targetUriId, $Notification->uid); } catch (\Exception $exception) { $status = null; } diff --git a/src/Factory/Api/Mastodon/Status.php b/src/Factory/Api/Mastodon/Status.php index 54ca7ce008..7fa09affd7 100644 --- a/src/Factory/Api/Mastodon/Status.php +++ b/src/Factory/Api/Mastodon/Status.php @@ -87,7 +87,6 @@ class Status extends BaseFactory /** * @param int $uriId Uri-ID of the item * @param int $uid Item user - * @param bool $display_quote Display quoted posts * @param bool $reblog Check for reblogged post * @param bool $in_reply_status Add an "in_reply_status" element * @@ -95,7 +94,7 @@ class Status extends BaseFactory * @throws InternalServerErrorException * @throws ImagickException|NotFoundException */ - public function createFromUriId(int $uriId, int $uid = 0, bool $display_quote = false, bool $reblog = true, bool $in_reply_status = true): \Friendica\Object\Api\Mastodon\Status + public function createFromUriId(int $uriId, int $uid = 0, bool $reblog = true, bool $in_reply_status = true): \Friendica\Object\Api\Mastodon\Status { $fields = ['uri-id', 'uid', 'author-id', 'causer-id', 'author-uri-id', 'author-link', 'author-gsid', 'causer-uri-id', 'post-reason', 'starred', 'app', 'title', 'body', 'raw-body', 'content-warning', 'question-id', 'created', 'edited', 'commented', 'received', 'changed', 'network', 'thr-parent-id', 'parent-author-id', 'language', 'uri', 'plink', 'private', 'vid', 'gravity', 'featured', 'has-media', 'quote-uri-id', @@ -261,56 +260,12 @@ class Status extends BaseFactory $poll = null; } - if ($display_quote) { - $quote = self::createQuote($item, $uid); + $quote = self::createQuote($item, $uid); - $item['body'] = BBCode::removeSharedData($item['body']); + $item['body'] = BBCode::removeSharedData($item['body']); - if (!is_null($item['raw-body'])) { - $item['raw-body'] = BBCode::removeSharedData($item['raw-body']); - } - } else { - // We can always safely add attached activities. Real quotes are added to the body via "addSharedPost". - if (empty($item['quote-uri-id'])) { - $quote = self::createQuote($item, $uid); - } else { - $quote = []; - } - - $shared = $this->contentItem->getSharedPost($item, ['uri-id']); - if (!empty($shared)) { - $shared_uri_id = $shared['post']['uri-id']; - - foreach ($this->mstdnMentionFactory->createFromUriId($shared_uri_id)->getArrayCopy() as $mention) { - if (!in_array($mention, $mentions)) { - $mentions[] = $mention; - } - } - - foreach ($this->mstdnTagFactory->createFromUriId($shared_uri_id) as $tag) { - if (!in_array($tag, $tags)) { - $tags[] = $tag; - } - } - - foreach ($this->mstdnAttachmentFactory->createFromUriId($shared_uri_id) as $attachment) { - if (!in_array($attachment, $attachments)) { - $attachments[] = $attachment; - } - } - - if (empty($card->toArray())) { - $card = $this->mstdnCardFactory->createFromUriId($shared_uri_id); - } - } - - if (!is_null($item['raw-body'])) { - $item['raw-body'] = $this->contentItem->addSharedPost($item, $item['raw-body']); - $item['raw-body'] = Post\Media::addHTMLLinkToBody($uriId, $item['raw-body']); - } else { - $item['body'] = $this->contentItem->addSharedPost($item); - $item['body'] = Post\Media::addHTMLLinkToBody($uriId, $item['body']); - } + if (!is_null($item['raw-body'])) { + $item['raw-body'] = BBCode::removeSharedData($item['raw-body']); } $emojis = null; @@ -330,7 +285,7 @@ class Status extends BaseFactory if ($is_reshare) { try { - $reshare = $this->createFromUriId($uriId, $uid, $display_quote, false, false)->toArray(); + $reshare = $this->createFromUriId($uriId, $uid, false, false)->toArray(); } catch (\Exception $exception) { DI::logger()->info('Reshare not fetchable', ['uri-id' => $item['uri-id'], 'uid' => $uid, 'exception' => $exception]); $reshare = []; @@ -341,7 +296,7 @@ class Status extends BaseFactory if ($in_reply_status && ($item['gravity'] == Item::GRAVITY_COMMENT)) { try { - $in_reply = $this->createFromUriId($item['thr-parent-id'], $uid, $display_quote, false, false)->toArray(); + $in_reply = $this->createFromUriId($item['thr-parent-id'], $uid, false, false)->toArray(); } catch (\Exception $exception) { DI::logger()->info('Reply post not fetchable', ['uri-id' => $item['uri-id'], 'uid' => $uid, 'exception' => $exception]); $in_reply = []; @@ -382,7 +337,7 @@ class Status extends BaseFactory if (!empty($quote_id) && ($quote_id != $item['uri-id'])) { try { - $quoted_status = $this->createFromUriId($quote_id, $uid, false, false, false)->toArray(); + $quoted_status = $this->createFromUriId($quote_id, $uid, false, false)->toArray(); $quote = [ 'state' => 'accepted', 'quoted_status' => $quoted_status, diff --git a/src/Module/Api/Friendica/Statuses/Dislike.php b/src/Module/Api/Friendica/Statuses/Dislike.php index 400b085fc5..73a1d5ab04 100644 --- a/src/Module/Api/Friendica/Statuses/Dislike.php +++ b/src/Module/Api/Friendica/Statuses/Dislike.php @@ -7,7 +7,6 @@ namespace Friendica\Module\Api\Friendica\Statuses; -use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Item; @@ -35,6 +34,6 @@ class Dislike extends BaseApi Item::performActivity($item['id'], 'dislike', $uid); - $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, self::appSupportsQuotes())->toArray()); + $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid)->toArray()); } } diff --git a/src/Module/Api/Friendica/Statuses/Undislike.php b/src/Module/Api/Friendica/Statuses/Undislike.php index bf332bee0e..d00f066e58 100644 --- a/src/Module/Api/Friendica/Statuses/Undislike.php +++ b/src/Module/Api/Friendica/Statuses/Undislike.php @@ -7,7 +7,6 @@ namespace Friendica\Module\Api\Friendica\Statuses; -use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Item; @@ -35,6 +34,6 @@ class Undislike extends BaseApi Item::performActivity($item['id'], 'undislike', $uid); - $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, self::appSupportsQuotes())->toArray()); + $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid)->toArray()); } } diff --git a/src/Module/Api/Mastodon/Accounts/Statuses.php b/src/Module/Api/Mastodon/Accounts/Statuses.php index e16a9e521a..bddd53bcd2 100644 --- a/src/Module/Api/Mastodon/Accounts/Statuses.php +++ b/src/Module/Api/Mastodon/Accounts/Statuses.php @@ -93,12 +93,10 @@ class Statuses extends BaseApi $items = Post::selectTimelineForUser($uid, ['uri-id'], $condition, $params); } - $display_quotes = self::appSupportsQuotes(); - $statuses = []; while ($item = Post::fetch($items)) { try { - $status = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid, $display_quotes); + $status = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid); $this->updateBoundaries($status, $item, $request['friendica_order']); $statuses[] = $status; } catch (\Throwable $th) { diff --git a/src/Module/Api/Mastodon/Bookmarks.php b/src/Module/Api/Mastodon/Bookmarks.php index b0f0ca34a5..ab43a6102a 100644 --- a/src/Module/Api/Mastodon/Bookmarks.php +++ b/src/Module/Api/Mastodon/Bookmarks.php @@ -54,13 +54,11 @@ class Bookmarks extends BaseApi $items = Post::selectThreadForUser($uid, ['uri-id'], $condition, $params); - $display_quotes = self::appSupportsQuotes(); - $statuses = []; while ($item = Post::fetch($items)) { self::setBoundaries($item['uri-id']); try { - $statuses[] = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid, $display_quotes); + $statuses[] = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid); } catch (\Exception $exception) { $this->logger->info('Post not fetchable', ['uri-id' => $item['uri-id'], 'uid' => $uid, 'exception' => $exception]); } diff --git a/src/Module/Api/Mastodon/Favourited.php b/src/Module/Api/Mastodon/Favourited.php index 3d9ec883bc..f2070c5257 100644 --- a/src/Module/Api/Mastodon/Favourited.php +++ b/src/Module/Api/Mastodon/Favourited.php @@ -56,13 +56,11 @@ class Favourited extends BaseApi $items = Post::selectForUser($uid, ['thr-parent-id'], $condition, $params); - $display_quotes = self::appSupportsQuotes(); - $statuses = []; while ($item = Post::fetch($items)) { self::setBoundaries($item['thr-parent-id']); try { - $statuses[] = DI::mstdnStatus()->createFromUriId($item['thr-parent-id'], $uid, $display_quotes); + $statuses[] = DI::mstdnStatus()->createFromUriId($item['thr-parent-id'], $uid); } catch (\Exception $exception) { $this->logger->info('Post not fetchable', ['uri-id' => $item['thr-parent-id'], 'uid' => $uid, 'exception' => $exception]); } diff --git a/src/Module/Api/Mastodon/Notifications.php b/src/Module/Api/Mastodon/Notifications.php index 5e392be976..2d7f56dd23 100644 --- a/src/Module/Api/Mastodon/Notifications.php +++ b/src/Module/Api/Mastodon/Notifications.php @@ -7,7 +7,6 @@ namespace Friendica\Module\Api\Mastodon; -use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Contact; @@ -34,7 +33,7 @@ class Notifications extends BaseApi $id = $this->parameters['id']; try { $notification = DI::notification()->selectOneForUser($uid, ['id' => $id]); - $this->jsonExit(DI::mstdnNotification()->createFromNotification($notification, self::appSupportsQuotes())); + $this->jsonExit(DI::mstdnNotification()->createFromNotification($notification)); } catch (\Exception $e) { $this->logAndJsonError(404, $this->errorFactory->RecordNotFound()); } @@ -132,7 +131,7 @@ class Notifications extends BaseApi foreach ($Notifications as $Notification) { try { - $mstdnNotifications[] = DI::mstdnNotification()->createFromNotification($Notification, self::appSupportsQuotes()); + $mstdnNotifications[] = DI::mstdnNotification()->createFromNotification($Notification); self::setBoundaries($Notification->id); } catch (\Exception $e) { // Skip this notification diff --git a/src/Module/Api/Mastodon/Search.php b/src/Module/Api/Mastodon/Search.php index f46ea1e981..d2b22a84c6 100644 --- a/src/Module/Api/Mastodon/Search.php +++ b/src/Module/Api/Mastodon/Search.php @@ -102,7 +102,7 @@ class Search extends BaseApi // If the user-specific search failed, we search and probe a public post $item_id = Item::fetchByLink($q, $uid) ?: Item::fetchByLink($q); if ($item_id && $item = Post::selectFirst(['uri-id'], ['id' => $item_id])) { - $result['statuses'] = [DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid, self::appSupportsQuotes())]; + $result['statuses'] = [DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid)]; $this->jsonExit($result); } } @@ -190,13 +190,11 @@ class Search extends BaseApi $items = DBA::select($table, ['uri-id'], $condition, $params); - $display_quotes = self::appSupportsQuotes(); - $statuses = []; while ($item = Post::fetch($items)) { self::setBoundaries($item['uri-id']); try { - $statuses[] = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid, $display_quotes); + $statuses[] = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid); } catch (\Exception $exception) { $this->logger->info('Post not fetchable', ['uri-id' => $item['uri-id'], 'uid' => $uid, 'exception' => $exception]); } diff --git a/src/Module/Api/Mastodon/Statuses.php b/src/Module/Api/Mastodon/Statuses.php index 45e976e9fe..6236e8eec3 100644 --- a/src/Module/Api/Mastodon/Statuses.php +++ b/src/Module/Api/Mastodon/Statuses.php @@ -183,7 +183,7 @@ class Statuses extends BaseApi Item::updateDisplayCache($post['uri-id']); - $this->jsonExit(DI::mstdnStatus()->createFromUriId($post['uri-id'], $uid, self::appSupportsQuotes())); + $this->jsonExit(DI::mstdnStatus()->createFromUriId($post['uri-id'], $uid)); } protected function post(array $request = []) @@ -345,7 +345,7 @@ class Statuses extends BaseApi if (!empty($id)) { $item = Post::selectFirst(['uri-id'], ['id' => $id]); if (!empty($item['uri-id'])) { - $this->jsonExit(DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid, self::appSupportsQuotes())); + $this->jsonExit(DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid)); } } @@ -396,7 +396,7 @@ class Statuses extends BaseApi } } - $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, self::appSupportsQuotes(), false)); + $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, false)); } private function getApp(): string diff --git a/src/Module/Api/Mastodon/Statuses/Bookmark.php b/src/Module/Api/Mastodon/Statuses/Bookmark.php index 0e2a537fac..8f31dfe721 100644 --- a/src/Module/Api/Mastodon/Statuses/Bookmark.php +++ b/src/Module/Api/Mastodon/Statuses/Bookmark.php @@ -55,6 +55,6 @@ class Bookmark extends BaseApi // Issue tracking the behavior of createFromUriId: https://github.com/friendica/friendica/issues/13350 $isReblog = $item['uri-id'] != $this->parameters['id']; - $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, self::appSupportsQuotes(), $isReblog)->toArray()); + $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, $isReblog)->toArray()); } } diff --git a/src/Module/Api/Mastodon/Statuses/Context.php b/src/Module/Api/Mastodon/Statuses/Context.php index 2d17eed232..57c3efe357 100644 --- a/src/Module/Api/Mastodon/Statuses/Context.php +++ b/src/Module/Api/Mastodon/Statuses/Context.php @@ -7,7 +7,6 @@ namespace Friendica\Module\Api\Mastodon\Statuses; -use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Item; @@ -46,7 +45,7 @@ class Context extends BaseApi $parent = Post::selectOriginal(['uri-id', 'parent-uri-id'], ['uri-id' => $id]); if (DBA::isResult($parent)) { - $id = $parent['uri-id']; + $id = $parent['uri-id']; $params = ['order' => ['uri-id' => true]]; $condition = ['parent-uri-id' => $parent['parent-uri-id'], 'gravity' => [Item::GRAVITY_PARENT, Item::GRAVITY_COMMENT]]; @@ -59,7 +58,7 @@ class Context extends BaseApi } if (!empty($request['min_id'])) { - $condition = DBA::mergeConditions($condition, ["`uri-id` > ?", $request['min_id']]); + $condition = DBA::mergeConditions($condition, ["`uri-id` > ?", $request['min_id']]); $params['order'] = ['uri-id']; } @@ -112,11 +111,9 @@ class Context extends BaseApi asort($ancestors); - $display_quotes = self::appSupportsQuotes(); - foreach (array_slice($ancestors, 0, $request['limit']) as $ancestor) { try { - $statuses['ancestors'][] = DI::mstdnStatus()->createFromUriId($ancestor, $uid, $display_quotes); + $statuses['ancestors'][] = DI::mstdnStatus()->createFromUriId($ancestor, $uid); } catch (\Throwable $th) { $this->logger->info('Post not fetchable', ['uri-id' => $ancestor, 'uid' => $uid, 'error' => $th]); } @@ -128,7 +125,7 @@ class Context extends BaseApi foreach (array_slice($descendants, 0, $request['limit']) as $descendant) { try { - $statuses['descendants'][] = DI::mstdnStatus()->createFromUriId($descendant, $uid, $display_quotes); + $statuses['descendants'][] = DI::mstdnStatus()->createFromUriId($descendant, $uid); } catch (\Throwable $th) { $this->logger->info('Post not fetchable', ['uri-id' => $descendant, 'uid' => $uid, 'error' => $th]); } diff --git a/src/Module/Api/Mastodon/Statuses/Favourite.php b/src/Module/Api/Mastodon/Statuses/Favourite.php index 1cfe5ffd33..04f3a9921b 100644 --- a/src/Module/Api/Mastodon/Statuses/Favourite.php +++ b/src/Module/Api/Mastodon/Statuses/Favourite.php @@ -7,7 +7,6 @@ namespace Friendica\Module\Api\Mastodon\Statuses; -use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Item; @@ -40,6 +39,6 @@ class Favourite extends BaseApi // Issue tracking the behavior of createFromUriId: https://github.com/friendica/friendica/issues/13350 $isReblog = $item['uri-id'] != $this->parameters['id']; - $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, self::appSupportsQuotes(), $isReblog)->toArray()); + $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, $isReblog)->toArray()); } } diff --git a/src/Module/Api/Mastodon/Statuses/Mute.php b/src/Module/Api/Mastodon/Statuses/Mute.php index d48363767c..81be3bbd84 100644 --- a/src/Module/Api/Mastodon/Statuses/Mute.php +++ b/src/Module/Api/Mastodon/Statuses/Mute.php @@ -7,7 +7,6 @@ namespace Friendica\Module\Api\Mastodon\Statuses; -use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Item; @@ -44,6 +43,6 @@ class Mute extends BaseApi // Issue tracking the behavior of createFromUriId: https://github.com/friendica/friendica/issues/13350 $isReblog = $item['uri-id'] != $this->parameters['id']; - $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, self::appSupportsQuotes(), $isReblog)->toArray()); + $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, $isReblog)->toArray()); } } diff --git a/src/Module/Api/Mastodon/Statuses/Pin.php b/src/Module/Api/Mastodon/Statuses/Pin.php index 16a053b914..e2cb7d5b75 100644 --- a/src/Module/Api/Mastodon/Statuses/Pin.php +++ b/src/Module/Api/Mastodon/Statuses/Pin.php @@ -7,7 +7,6 @@ namespace Friendica\Module\Api\Mastodon\Statuses; -use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Post; @@ -39,6 +38,6 @@ class Pin extends BaseApi // Issue tracking the behavior of createFromUriId: https://github.com/friendica/friendica/issues/13350 $isReblog = $item['uri-id'] != $this->parameters['id']; - $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, self::appSupportsQuotes(),$isReblog)->toArray()); + $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, $isReblog)->toArray()); } } diff --git a/src/Module/Api/Mastodon/Statuses/Reblog.php b/src/Module/Api/Mastodon/Statuses/Reblog.php index 0641143b81..5f85385f53 100644 --- a/src/Module/Api/Mastodon/Statuses/Reblog.php +++ b/src/Module/Api/Mastodon/Statuses/Reblog.php @@ -9,7 +9,6 @@ namespace Friendica\Module\Api\Mastodon\Statuses; use Friendica\Content\ContactSelector; use Friendica\Core\Protocol; -use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Item; @@ -52,6 +51,6 @@ class Reblog extends BaseApi // Issue tracking the behavior of createFromUriId: https://github.com/friendica/friendica/issues/13350 $isReblog = $item['uri-id'] != $this->parameters['id']; - $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, self::appSupportsQuotes(), $isReblog)->toArray()); + $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, $isReblog)->toArray()); } } diff --git a/src/Module/Api/Mastodon/Statuses/Unbookmark.php b/src/Module/Api/Mastodon/Statuses/Unbookmark.php index d1447ecd12..1377e7c9fa 100644 --- a/src/Module/Api/Mastodon/Statuses/Unbookmark.php +++ b/src/Module/Api/Mastodon/Statuses/Unbookmark.php @@ -7,7 +7,6 @@ namespace Friendica\Module\Api\Mastodon\Statuses; -use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Item; @@ -56,6 +55,6 @@ class Unbookmark extends BaseApi // Issue tracking the behavior of createFromUriId: https://github.com/friendica/friendica/issues/13350 $isReblog = $item['uri-id'] != $this->parameters['id']; - $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, self::appSupportsQuotes(), $isReblog)->toArray()); + $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, $isReblog)->toArray()); } } diff --git a/src/Module/Api/Mastodon/Statuses/Unfavourite.php b/src/Module/Api/Mastodon/Statuses/Unfavourite.php index e59739a2a1..73fc270c6d 100644 --- a/src/Module/Api/Mastodon/Statuses/Unfavourite.php +++ b/src/Module/Api/Mastodon/Statuses/Unfavourite.php @@ -7,7 +7,6 @@ namespace Friendica\Module\Api\Mastodon\Statuses; -use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Item; @@ -40,6 +39,6 @@ class Unfavourite extends BaseApi // Issue tracking the behavior of createFromUriId: https://github.com/friendica/friendica/issues/13350 $isReblog = $item['uri-id'] != $this->parameters['id']; - $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, self::appSupportsQuotes(), $isReblog)->toArray()); + $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, $isReblog)->toArray()); } } diff --git a/src/Module/Api/Mastodon/Statuses/Unmute.php b/src/Module/Api/Mastodon/Statuses/Unmute.php index 9e540f0e6b..67495fbc85 100644 --- a/src/Module/Api/Mastodon/Statuses/Unmute.php +++ b/src/Module/Api/Mastodon/Statuses/Unmute.php @@ -7,7 +7,6 @@ namespace Friendica\Module\Api\Mastodon\Statuses; -use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Item; @@ -44,6 +43,6 @@ class Unmute extends BaseApi // Issue tracking the behavior of createFromUriId: https://github.com/friendica/friendica/issues/13350 $isReblog = $item['uri-id'] != $this->parameters['id']; - $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, self::appSupportsQuotes(), $isReblog)->toArray()); + $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, $isReblog)->toArray()); } } diff --git a/src/Module/Api/Mastodon/Statuses/Unpin.php b/src/Module/Api/Mastodon/Statuses/Unpin.php index de74fe8246..45b589bc64 100644 --- a/src/Module/Api/Mastodon/Statuses/Unpin.php +++ b/src/Module/Api/Mastodon/Statuses/Unpin.php @@ -7,7 +7,6 @@ namespace Friendica\Module\Api\Mastodon\Statuses; -use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Post; @@ -39,6 +38,6 @@ class Unpin extends BaseApi // Issue tracking the behavior of createFromUriId: https://github.com/friendica/friendica/issues/13350 $isReblog = $item['uri-id'] != $this->parameters['id']; - $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, self::appSupportsQuotes(), $isReblog)->toArray()); + $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, $isReblog)->toArray()); } } diff --git a/src/Module/Api/Mastodon/Statuses/Unreblog.php b/src/Module/Api/Mastodon/Statuses/Unreblog.php index 3650892fb7..95758c3be3 100644 --- a/src/Module/Api/Mastodon/Statuses/Unreblog.php +++ b/src/Module/Api/Mastodon/Statuses/Unreblog.php @@ -9,7 +9,6 @@ namespace Friendica\Module\Api\Mastodon\Statuses; use Friendica\Content\ContactSelector; use Friendica\Core\Protocol; -use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Item; @@ -58,6 +57,6 @@ class Unreblog extends BaseApi // Issue tracking the behavior of createFromUriId: https://github.com/friendica/friendica/issues/13350 $isReblog = $item['uri-id'] != $this->parameters['id']; - $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, self::appSupportsQuotes(), $isReblog)->toArray()); + $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, $isReblog)->toArray()); } } diff --git a/src/Module/Api/Mastodon/Timelines/Home.php b/src/Module/Api/Mastodon/Timelines/Home.php index fc1eaa6d01..2131061be1 100644 --- a/src/Module/Api/Mastodon/Timelines/Home.php +++ b/src/Module/Api/Mastodon/Timelines/Home.php @@ -69,12 +69,10 @@ class Home extends BaseApi $items = Post::selectTimelineForUser($uid, ['uri-id'], $condition, $params); - $display_quotes = self::appSupportsQuotes(); - $statuses = []; while ($item = Post::fetch($items)) { try { - $status = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid, $display_quotes); + $status = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid); $this->updateBoundaries($status, $item, $request['friendica_order']); $statuses[] = $status; } catch (\Throwable $th) { diff --git a/src/Module/Api/Mastodon/Timelines/ListTimeline.php b/src/Module/Api/Mastodon/Timelines/ListTimeline.php index 093ed6ca35..311a123234 100644 --- a/src/Module/Api/Mastodon/Timelines/ListTimeline.php +++ b/src/Module/Api/Mastodon/Timelines/ListTimeline.php @@ -66,8 +66,6 @@ class ListTimeline extends BaseApi 'friendica_order' => TimelineOrderByTypes::ID, // Sort order options (defaults to ID) ], $request); - $display_quotes = self::appSupportsQuotes(); - if (substr($this->parameters['id'], 0, 6) == 'group:') { $items = $this->getStatusesForGroup($uid, $request); } elseif (substr($this->parameters['id'], 0, 8) == 'channel:') { @@ -79,7 +77,7 @@ class ListTimeline extends BaseApi $statuses = []; foreach ($items as $item) { try { - $status = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid, $display_quotes); + $status = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid); $this->updateBoundaries($status, $item, $request['friendica_order']); $statuses[] = $status; } catch (\Throwable $th) { diff --git a/src/Module/Api/Mastodon/Timelines/PublicTimeline.php b/src/Module/Api/Mastodon/Timelines/PublicTimeline.php index acc4aac52c..0465a7b469 100644 --- a/src/Module/Api/Mastodon/Timelines/PublicTimeline.php +++ b/src/Module/Api/Mastodon/Timelines/PublicTimeline.php @@ -103,12 +103,10 @@ class PublicTimeline extends BaseApi $items = Post::selectTimelineForUser($uid, ['uri-id'], $condition, $params); } - $display_quotes = self::appSupportsQuotes(); - $statuses = []; while ($item = Post::fetch($items)) { try { - $status = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid, $display_quotes); + $status = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid); $this->updateBoundaries($status, $item, $request['friendica_order']); $statuses[] = $status; } catch (\Throwable $th) { diff --git a/src/Module/Api/Mastodon/Timelines/Tag.php b/src/Module/Api/Mastodon/Timelines/Tag.php index 5eb26cad6a..58ffa34e72 100644 --- a/src/Module/Api/Mastodon/Timelines/Tag.php +++ b/src/Module/Api/Mastodon/Timelines/Tag.php @@ -97,13 +97,11 @@ class Tag extends BaseApi $items = DBA::select('tag-search-view', ['uri-id'], $condition, $params); - $display_quotes = self::appSupportsQuotes(); - $statuses = []; while ($item = Post::fetch($items)) { self::setBoundaries($item['uri-id']); try { - $statuses[] = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid, $display_quotes); + $statuses[] = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid); } catch (\Exception $exception) { $this->logger->info('Post not fetchable', ['uri-id' => $item['uri-id'], 'uid' => $uid, 'exception' => $exception]); } diff --git a/src/Module/Api/Mastodon/Trends/Statuses.php b/src/Module/Api/Mastodon/Trends/Statuses.php index a64b83e130..d81802fe68 100644 --- a/src/Module/Api/Mastodon/Trends/Statuses.php +++ b/src/Module/Api/Mastodon/Trends/Statuses.php @@ -58,13 +58,11 @@ class Statuses extends BaseApi $condition = ["NOT `private` AND `commented` > ? AND `created` > ?", DateTimeFormat::utc('now -1 day'), DateTimeFormat::utc('now -1 week')]; $condition = DBA::mergeConditions($condition, ['network' => Protocol::FEDERATED]); - $display_quotes = self::appSupportsQuotes(); - $trending = []; $statuses = Post::selectPostThread(['uri-id'], $condition, ['limit' => [$request['offset'], $request['limit']], 'order' => ['total-actors' => true]]); while ($status = Post::fetch($statuses)) { try { - $trending[] = DI::mstdnStatus()->createFromUriId($status['uri-id'], $uid, $display_quotes); + $trending[] = DI::mstdnStatus()->createFromUriId($status['uri-id'], $uid); } catch (\Exception $exception) { $this->logger->info('Post not fetchable', ['uri-id' => $status['uri-id'], 'uid' => $uid, 'exception' => $exception]); } diff --git a/src/Module/BaseApi.php b/src/Module/BaseApi.php index e1566eec76..4f2adb447a 100644 --- a/src/Module/BaseApi.php +++ b/src/Module/BaseApi.php @@ -356,17 +356,6 @@ class BaseApi extends BaseModule } } - /** - * Check if the app is known to support quoted posts - * - * @return bool - */ - public static function appSupportsQuotes(): bool - { - // @todo Clean up the whole functionality since it isn't of any use anymore. - return true; - } - /** * Get current application token * From d6b6dd1b94276f514b699611fa56792a7a156e76 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 23 Jan 2026 06:36:06 +0000 Subject: [PATCH 026/197] Channel posts can now be embedded into the timeline --- database.sql | 10 +- doc/en/spec/database/db-channel-post.md | 17 +- .../spec/database/db-system-channel-post.md | 29 +- src/Content/Conversation.php | 73 +- .../Conversation/Factory/ChannelPost.php | 27 +- .../Factory/SystemChannelPost.php | 25 +- .../Repository/UserDefinedChannel.php | 6 +- src/Database/Database.php | 23 +- src/Model/Item.php | 1 + src/Model/Post/Engagement.php | 2 +- src/Module/Conversation/Network.php | 87 +- src/Module/Conversation/Timeline.php | 13 +- src/Module/Settings/Channels.php | 15 +- src/Module/Settings/Display.php | 35 +- src/Worker/UpdateChannelPosts.php | 11 +- static/dbstructure.config.php | 6 +- static/dbview.config.php | 4 + view/lang/C/messages.po | 743 +++++++++--------- view/templates/settings/display.tpl | 7 + .../theme/frio/templates/settings/display.tpl | 10 + view/theme/frio/templates/sub/direction.tpl | 2 + 21 files changed, 680 insertions(+), 466 deletions(-) diff --git a/database.sql b/database.sql index 209a9068e6..c97446d23a 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2026.04-dev (Blutwurz) --- DB_UPDATE_VERSION 1586 +-- DB_UPDATE_VERSION 1587 -- ------------------------------------------ @@ -1368,6 +1368,7 @@ CREATE TABLE IF NOT EXISTS `channel-post` ( `channel` int unsigned NOT NULL COMMENT 'Channel id', `uri-id` int unsigned NOT NULL COMMENT 'Post engagement entry', `uid` mediumint unsigned NOT NULL COMMENT 'User id', + `in-timeline` boolean NOT NULL DEFAULT '0' COMMENT 'If true, this post is in the user\'s main timeline', `created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT '', `received` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT '', `commented` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT '', @@ -1389,13 +1390,14 @@ CREATE TABLE IF NOT EXISTS `system-channel-post` ( `channel` varchar(20) NOT NULL COMMENT 'System channel id', `uid` mediumint unsigned NOT NULL COMMENT 'User id', `uri-id` int unsigned NOT NULL COMMENT 'Post engagement entry', + `in-timeline` boolean NOT NULL DEFAULT '0' COMMENT 'If true, this post is in the user\'s main timeline', `created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT '', `received` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT '', `commented` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT '', PRIMARY KEY(`channel`,`uid`,`uri-id`), INDEX `uri-id` (`uri-id`), INDEX `uid` (`uid`), - INDEX `channel_created` (`channel`,`uid`,`created`), + INDEX `channel_uid_created` (`channel`,`uid`,`created`), FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE CASCADE, FOREIGN KEY (`uri-id`) REFERENCES `post-engagement` (`uri-id`) ON UPDATE RESTRICT ON DELETE CASCADE ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Posts in a system channel'; @@ -2103,6 +2105,7 @@ CREATE VIEW `channel-post-view` AS SELECT `channel-post`.`channel` AS `channel`, `channel-post`.`uid` AS `uid`, `channel-post`.`uri-id` AS `uri-id`, + `channel-post`.`in-timeline` AS `in-timeline`, `post-engagement`.`owner-id` AS `owner-id`, `post-engagement`.`media-type` AS `media-type`, `post-engagement`.`language` AS `language`, @@ -2131,6 +2134,7 @@ CREATE VIEW `system-channel-post-view` AS SELECT `system-channel-post`.`channel` AS `channel`, `system-channel-post`.`uid` AS `uid`, `system-channel-post`.`uri-id` AS `uri-id`, + `system-channel-post`.`in-timeline` AS `in-timeline`, `post-engagement`.`owner-id` AS `owner-id`, `post-engagement`.`media-type` AS `media-type`, `post-engagement`.`language` AS `language`, @@ -3517,6 +3521,7 @@ CREATE VIEW `tag-view` AS SELECT -- DROP VIEW IF EXISTS `network-thread-view`; CREATE VIEW `network-thread-view` AS SELECT + '' AS `channel`, `post-thread-user`.`uri-id` AS `uri-id`, `post-thread-user`.`post-user-id` AS `parent`, `post-thread-user`.`received` AS `received`, @@ -3546,6 +3551,7 @@ CREATE VIEW `network-thread-view` AS SELECT -- DROP VIEW IF EXISTS `network-thread-circle-view`; CREATE VIEW `network-thread-circle-view` AS SELECT + '' AS `channel`, `post-thread-user`.`uri-id` AS `uri-id`, `post-thread-user`.`post-user-id` AS `parent`, `post-thread-user`.`received` AS `received`, diff --git a/doc/en/spec/database/db-channel-post.md b/doc/en/spec/database/db-channel-post.md index 5b661f3843..e23c2ede7b 100644 --- a/doc/en/spec/database/db-channel-post.md +++ b/doc/en/spec/database/db-channel-post.md @@ -4,14 +4,15 @@ Posts in a user defined channel ## Fields -| Field | Description | Type | Null | Key | Default | Extra | -| --------- | --------------------- | ------------------ | ---- | --- | ------------------- | ----- | -| channel | Channel id | int unsigned | NO | PRI | NULL | | -| uri-id | Post engagement entry | int unsigned | NO | PRI | NULL | | -| uid | User id | mediumint unsigned | NO | | NULL | | -| created | | datetime | NO | | 0001-01-01 00:00:00 | | -| received | | datetime | NO | | 0001-01-01 00:00:00 | | -| commented | | datetime | NO | | 0001-01-01 00:00:00 | | +| Field | Description | Type | Null | Key | Default | Extra | +| ----------- | ------------------------------------------------- | ------------------ | ---- | --- | ------------------- | ----- | +| channel | Channel id | int unsigned | NO | PRI | NULL | | +| uri-id | Post engagement entry | int unsigned | NO | PRI | NULL | | +| uid | User id | mediumint unsigned | NO | | NULL | | +| in-timeline | If true, this post is in the user's main timeline | boolean | NO | | 0 | | +| created | | datetime | NO | | 0001-01-01 00:00:00 | | +| received | | datetime | NO | | 0001-01-01 00:00:00 | | +| commented | | datetime | NO | | 0001-01-01 00:00:00 | | ## Indexes diff --git a/doc/en/spec/database/db-system-channel-post.md b/doc/en/spec/database/db-system-channel-post.md index c2de82c152..ed1d4445f1 100644 --- a/doc/en/spec/database/db-system-channel-post.md +++ b/doc/en/spec/database/db-system-channel-post.md @@ -4,23 +4,24 @@ Posts in a system channel ## Fields -| Field | Description | Type | Null | Key | Default | Extra | -| --------- | --------------------- | ------------------ | ---- | --- | ------------------- | ----- | -| channel | System channel id | varchar(20) | NO | PRI | NULL | | -| uid | User id | mediumint unsigned | NO | PRI | NULL | | -| uri-id | Post engagement entry | int unsigned | NO | PRI | NULL | | -| created | | datetime | NO | | 0001-01-01 00:00:00 | | -| received | | datetime | NO | | 0001-01-01 00:00:00 | | -| commented | | datetime | NO | | 0001-01-01 00:00:00 | | +| Field | Description | Type | Null | Key | Default | Extra | +| ----------- | ------------------------------------------------- | ------------------ | ---- | --- | ------------------- | ----- | +| channel | System channel id | varchar(20) | NO | PRI | NULL | | +| uid | User id | mediumint unsigned | NO | PRI | NULL | | +| uri-id | Post engagement entry | int unsigned | NO | PRI | NULL | | +| in-timeline | If true, this post is in the user's main timeline | boolean | NO | | 0 | | +| created | | datetime | NO | | 0001-01-01 00:00:00 | | +| received | | datetime | NO | | 0001-01-01 00:00:00 | | +| commented | | datetime | NO | | 0001-01-01 00:00:00 | | ## Indexes -| Name | Fields | -| --------------- | --------------------- | -| PRIMARY | channel, uid, uri-id | -| uri-id | uri-id | -| uid | uid | -| channel_created | channel, uid, created | +| Name | Fields | +| ------------------- | --------------------- | +| PRIMARY | channel, uid, uri-id | +| uri-id | uri-id | +| uid | uid | +| channel_uid_created | channel, uid, created | ## Foreign keys diff --git a/src/Content/Conversation.php b/src/Content/Conversation.php index bd68272381..ffdf3ec725 100644 --- a/src/Content/Conversation.php +++ b/src/Content/Conversation.php @@ -12,6 +12,9 @@ use Friendica\App\BaseURL; use Friendica\App\Mode; use Friendica\App\Page; use Friendica\BaseModule; +use Friendica\Content\Conversation\Factory\Channel; +use Friendica\Content\Conversation\Repository\UserDefinedChannel; +use Friendica\Content\Conversation\Entity\Channel as ChannelEntity; use Friendica\Core\ACL; use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\L10n; @@ -85,23 +88,27 @@ class Conversation /** @var UserGServerRepository */ private $userGServer; private EventDispatcherInterface $eventDispatcher; + private Channel $channel; + private UserDefinedChannel $userDefinedChannel; - public function __construct(UserGServerRepository $userGServer, LoggerInterface $logger, Profiler $profiler, Activity $activity, L10n $l10n, Item $item, Arguments $args, BaseURL $baseURL, IManageConfigValues $config, IManagePersonalConfigValues $pConfig, Page $page, Mode $mode, EventDispatcherInterface $eventDispatcher, IHandleUserSessions $session) + public function __construct(UserGServerRepository $userGServer, Channel $channel, UserDefinedChannel $userDefinedChannel, LoggerInterface $logger, Profiler $profiler, Activity $activity, L10n $l10n, Item $item, Arguments $args, BaseURL $baseURL, IManageConfigValues $config, IManagePersonalConfigValues $pConfig, Page $page, Mode $mode, EventDispatcherInterface $eventDispatcher, IHandleUserSessions $session) { - $this->activity = $activity; - $this->item = $item; - $this->config = $config; - $this->mode = $mode; - $this->baseURL = $baseURL; - $this->profiler = $profiler; - $this->logger = $logger; - $this->l10n = $l10n; - $this->args = $args; - $this->pConfig = $pConfig; - $this->page = $page; - $this->eventDispatcher = $eventDispatcher; - $this->session = $session; - $this->userGServer = $userGServer; + $this->activity = $activity; + $this->item = $item; + $this->config = $config; + $this->mode = $mode; + $this->baseURL = $baseURL; + $this->profiler = $profiler; + $this->logger = $logger; + $this->l10n = $l10n; + $this->args = $args; + $this->pConfig = $pConfig; + $this->page = $page; + $this->eventDispatcher = $eventDispatcher; + $this->session = $session; + $this->userGServer = $userGServer; + $this->channel = $channel; + $this->userDefinedChannel = $userDefinedChannel; } /** @@ -687,10 +694,13 @@ class Conversation * @param array $row Post row * @param array $activity Contact data of the resharer * @param array $thr_parent Thread parent row + * @param string $channel Channel information + * @param int $uid User ID + * @param array $channels Available channels for the user * * @return array items with parents and comments */ - private function addRowInformation(array $row, array $activity, array $thr_parent): array + private function addRowInformation(array $row, array $activity, array $thr_parent, string $channel, int $uid, array $channels): array { $this->profiler->startRecording('rendering'); @@ -715,6 +725,11 @@ class Conversation } } + if ($channel) { + $row['channel'] = $channel; + $row['post-reason'] = ItemModel::PR_CHANNEL; + } + switch ($row['post-reason']) { case ItemModel::PR_TO: $row['direction'] = ['direction' => 7, 'title' => $this->l10n->t('You had been addressed (%s).', 'to')]; @@ -793,6 +808,16 @@ class Conversation case ItemModel::PR_PUSHED: $row['direction'] = ['direction' => 1, 'title' => $this->l10n->t('Pushed to us')]; break; + case ItemModel::PR_CHANNEL: + $title = $channels[$channel]->label ?? $channel; + $description = $channels[$channel]->description ?? ''; + + if ($description) { + $row['direction'] = ['direction' => 11, 'title' => $this->l10n->t('Channel "%s": %s', $title, $description)]; + } else { + $row['direction'] = ['direction' => 11, 'title' => $this->l10n->t('Channel "%s"', $title)]; + } + break; } $row['thr-parent-row'] = $thr_parent; @@ -829,6 +854,7 @@ class Conversation $uriids = []; $commentcounter = []; $activitycounter = []; + $postchannels = []; foreach ($parents as $parent) { if (!empty($parent['thr-parent-id']) && !empty($parent['gravity']) && ($parent['gravity'] == ItemModel::GRAVITY_ACTIVITY)) { @@ -848,6 +874,7 @@ class Conversation $commentcounter[$uriid] = 0; $activitycounter[$uriid] = 0; + $postchannels[$uriid] = $parent['channel'] ?? ''; } $condition = ['parent-uri-id' => $uriids]; @@ -892,6 +919,16 @@ class Conversation $thread_items = Post::select(array_merge(ItemModel::DISPLAY_FIELDLIST, ['featured', 'contact-uid', 'gravity', 'post-type', 'post-reason']), $condition, $params); + $channels = []; + foreach ($this->userDefinedChannel->selectByUid($uid) as $userchannel) { + $channels[$userchannel->code] = $userchannel; + } + + /** @var ChannelEntity $systemchannel */ + foreach ($this->channel->getTimelines($uid) as $systemchannel) { + $channels[$systemchannel->code] = $systemchannel; + } + $items = []; $quote_uri_ids = []; $authors = []; @@ -934,7 +971,7 @@ class Conversation ]; } - $items[$row['uri-id']] = $this->addRowInformation($row, $activities[$row['uri-id']] ?? [], $thr_parent[$row['thr-parent-id']] ?? []); + $items[$row['uri-id']] = $this->addRowInformation($row, $activities[$row['uri-id']] ?? [], $thr_parent[$row['thr-parent-id']] ?? [], $postchannels[$row['thr-parent-id']] ?? '', $uid, $channels); } DBA::close($thread_items); @@ -955,7 +992,7 @@ class Conversation $authors[] = $row['author-id']; $authors[] = $row['owner-id']; - $items[$row['uri-id']] = $this->addRowInformation($row, [], []); + $items[$row['uri-id']] = $this->addRowInformation($row, [], [], $postchannels[$row['thr-parent-id']] ?? '', $uid, $channels); } DBA::close($quotes); diff --git a/src/Content/Conversation/Factory/ChannelPost.php b/src/Content/Conversation/Factory/ChannelPost.php index c554d16a2b..7cb08c3ab1 100644 --- a/src/Content/Conversation/Factory/ChannelPost.php +++ b/src/Content/Conversation/Factory/ChannelPost.php @@ -92,27 +92,34 @@ final class ChannelPost } foreach ($channels as $channel) { - if (in_array($channel->circle, [-3, -4, -5]) && !Post::exists(['parent-uri-id' => $engagement['uri-id'], 'uid' => $channel->uid])) { + $in_timeline = Post::exists(['parent-uri-id' => $engagement['uri-id'], 'uid' => $channel->uid]); + + if ($engagement['restricted'] && !$in_timeline) { continue; } - if ($channel->circle === -1 && !Contact::isSharing($engagement['owner-id'], $channel->uid)) { + if (in_array($channel->circle, [UserDefinedChannelEntity::CIRCLE_CREATION, UserDefinedChannelEntity::CIRCLE_POSTS, UserDefinedChannelEntity::CIRCLE_ACTIVITY]) && !$in_timeline) { continue; } - if ($channel->circle === -2 && (!Contact::isFollower($engagement['owner-id'], $channel->uid) || Contact::isSharing($engagement['owner-id'], $channel->uid))) { + if ($channel->circle === UserDefinedChannelEntity::CIRCLE_FOLLOWING && !Contact::isSharing($engagement['owner-id'], $channel->uid)) { + continue; + } + + if ($channel->circle === UserDefinedChannelEntity::CIRCLE_FOLLOWERS && (!Contact::isFollower($engagement['owner-id'], $channel->uid) || Contact::isSharing($engagement['owner-id'], $channel->uid))) { continue; } $cache = [ - 'channel' => (int)$channel->code, - 'uid' => $channel->uid, - 'uri-id' => $engagement['uri-id'], - 'created' => $post['created'], - 'received' => $post['received'], - 'commented' => $post['commented'], + 'channel' => (int)$channel->code, + 'uid' => $channel->uid, + 'uri-id' => $engagement['uri-id'], + 'in-timeline' => $in_timeline, + 'created' => $post['created'], + 'received' => $post['received'], + 'commented' => $post['commented'], ]; - $ret = $this->dba->insert('channel-post', $cache, Database::INSERT_IGNORE); + $ret = $this->dba->insert('channel-post', $cache, Database::INSERT_UPDATE); $this->logger->debug('Added channel post', ['uri-id' => $engagement['uri-id'], 'cache' => $cache, 'ret' => $ret]); } } diff --git a/src/Content/Conversation/Factory/SystemChannelPost.php b/src/Content/Conversation/Factory/SystemChannelPost.php index 48689ec837..1042344114 100644 --- a/src/Content/Conversation/Factory/SystemChannelPost.php +++ b/src/Content/Conversation/Factory/SystemChannelPost.php @@ -91,10 +91,20 @@ final class SystemChannelPost $uids = $this->channelRepository->getUsersForPost($engagement['uri-id'], $post_uid, $post['network'], $post['private']); foreach ($uids as $uid) { + if ($engagement['restricted'] && !Post::exists(['parent-uri-id' => $engagement['uri-id'], 'uid' => $uid])) { + continue; + } + foreach ($channels as $channel) { if ($this->dba->exists('system-channel-post', ['channel' => $channel, 'uid' => $uid, 'uri-id' => $engagement['uri-id']])) { continue; } + + $wanted = User::getWantedLanguages($uid); + if ($channel !== Channel::LANGUAGE && $wanted && !in_array($engagement['language'], $wanted)) { + continue; + } + $store = false; switch ($channel) { case Channel::WHATSHOT: @@ -195,14 +205,15 @@ final class SystemChannelPost } $cache = [ - 'channel' => $channel, - 'uid' => $uid, - 'uri-id' => $engagement['uri-id'], - 'created' => $post['created'], - 'received' => $post['received'], - 'commented' => $post['commented'], + 'channel' => $channel, + 'uid' => $uid, + 'uri-id' => $engagement['uri-id'], + 'in-timeline' => Post::exists(['parent-uri-id' => $engagement['uri-id'], 'uid' => $uid]), + 'created' => $post['created'], + 'received' => $post['received'], + 'commented' => $post['commented'], ]; - $ret = $this->dba->insert('system-channel-post', $cache, Database::INSERT_IGNORE); + $ret = $this->dba->insert('system-channel-post', $cache, Database::INSERT_UPDATE); $this->logger->debug('Added system channel post', ['uri-id' => $engagement['uri-id'], 'cache' => $cache, 'ret' => $ret]); } } diff --git a/src/Content/Conversation/Repository/UserDefinedChannel.php b/src/Content/Conversation/Repository/UserDefinedChannel.php index 8e07f1c418..4e5b380c57 100644 --- a/src/Content/Conversation/Repository/UserDefinedChannel.php +++ b/src/Content/Conversation/Repository/UserDefinedChannel.php @@ -484,9 +484,9 @@ class UserDefinedChannel extends BaseRepository $condition = []; if (!empty($channel->circle)) { - if ($channel->circle == -1) { + if ($channel->circle == UserDefinedChannelEntity::CIRCLE_FOLLOWING) { $condition = ["`owner-id` IN (SELECT `pid` FROM `account-user-view` WHERE `uid` = ? AND `rel` IN (?, ?))", $uid, Contact::SHARING, Contact::FRIEND]; - } elseif ($channel->circle == -2) { + } elseif ($channel->circle == UserDefinedChannelEntity::CIRCLE_FOLLOWERS) { $condition = ["`owner-id` IN (SELECT `pid` FROM `account-user-view` WHERE `uid` = ? AND `rel` = ?)", $uid, Contact::FOLLOWER]; } elseif ($channel->circle > 0) { $condition = DBA::mergeConditions($condition, ["`owner-id` IN (SELECT `pid` FROM `group_member` INNER JOIN `account-user-view` ON `group_member`.`contact-id` = `account-user-view`.`id` WHERE `gid` = ? AND `account-user-view`.`uid` = ?)", $channel->circle, $uid]); @@ -548,7 +548,7 @@ class UserDefinedChannel extends BaseRepository $condition = DBA::mergeConditions($condition, ["`size` <= ?", $channel->maxSize]); } - if (in_array($channel->circle, [-3, -4, -5])) { + if (in_array($channel->circle, [UserDefinedChannelEntity::CIRCLE_CREATION, UserDefinedChannelEntity::CIRCLE_POSTS, UserDefinedChannelEntity::CIRCLE_ACTIVITY])) { $condition = DBA::mergeConditions($condition, ['uid' => $uid]); } diff --git a/src/Database/Database.php b/src/Database/Database.php index 82522a100a..7be7620161 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -1482,6 +1482,19 @@ class Database return false; } + $sql = $this->getSQL($table, $fields, $condition, $params); + DBA::buildCondition($condition); + $result = $this->p($sql, $condition); + + if ($this->driver == self::PDO && !empty($result)) { + $this->currentTable = $table; + } + + return $result; + } + + public function getSQL(string $table, array $fields = [], array $condition = [], array $params = []): string + { if (count($fields) > 0) { $fields = $this->escapeFields($fields, $params); $select_string = implode(', ', $fields); @@ -1495,15 +1508,7 @@ class Database $param_string = DBA::buildParameter($params); - $sql = "SELECT " . $select_string . " FROM " . $table_string . $condition_string . $param_string; - - $result = $this->p($sql, $condition); - - if ($this->driver == self::PDO && !empty($result)) { - $this->currentTable = $table; - } - - return $result; + return "SELECT " . $select_string . " FROM " . $table_string . $condition_string . $param_string; } /** diff --git a/src/Model/Item.php b/src/Model/Item.php index 7680ed6cde..9facded0fc 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -76,6 +76,7 @@ class Item const PR_PUSHED = 80; const PR_LOCAL = 81; const PR_AUDIENCE = 82; + const PR_CHANNEL = 83; // system.accept_only_sharer setting values const COMPLETION_NONE = 1; diff --git a/src/Model/Post/Engagement.php b/src/Model/Post/Engagement.php index 7c8a302ac5..e9c9e58cb1 100644 --- a/src/Model/Post/Engagement.php +++ b/src/Model/Post/Engagement.php @@ -379,7 +379,7 @@ class Engagement DI::logger()->notice('Cleared expired engagements', ['limit' => $limit, 'rows' => DBA::affectedRows()]); } - private static function getCreationDateLimit(bool $forDeletion): string + public static function getCreationDateLimit(bool $forDeletion): string { $posts = DI::config()->get('channel', 'engagement_post_limit'); if (!empty($posts)) { diff --git a/src/Module/Conversation/Network.php b/src/Module/Conversation/Network.php index 7281f60153..d8752eee02 100644 --- a/src/Module/Conversation/Network.php +++ b/src/Module/Conversation/Network.php @@ -468,51 +468,51 @@ class Network extends Timeline protected function getItems() { - $conditionFields = ['uid' => $this->session->getLocalUserId()]; - $conditionStrings = []; + $timelineCondition = []; + $commonCondition = ['uid' => $this->session->getLocalUserId()]; if (!is_null($this->accountType)) { - $conditionFields['contact-type'] = $this->accountType; + $commonCondition['contact-type'] = $this->accountType; } if ($this->star) { - $conditionFields['starred'] = true; + $timelineCondition['starred'] = true; } if ($this->mention) { - $conditionFields['mention'] = true; + $timelineCondition['mention'] = true; } if ($this->network) { - $conditionFields['network'] = $this->network; + $commonCondition['network'] = $this->network; } if ($this->dateFrom) { - $conditionStrings = DBA::mergeConditions($conditionStrings, ["`received` <= ? ", DateTimeFormat::convert($this->dateFrom, 'UTC', $this->appHelper->getTimeZone())]); + $commonCondition = DBA::mergeConditions($commonCondition, ["`received` <= ? ", DateTimeFormat::convert($this->dateFrom, 'UTC', $this->appHelper->getTimeZone())]); } if ($this->dateTo) { - $conditionStrings = DBA::mergeConditions($conditionStrings, ["`received` >= ? ", DateTimeFormat::convert($this->dateTo, 'UTC', $this->appHelper->getTimeZone())]); + $commonCondition = DBA::mergeConditions($commonCondition, ["`received` >= ? ", DateTimeFormat::convert($this->dateTo, 'UTC', $this->appHelper->getTimeZone())]); } if ($this->circleId) { - $conditionStrings = DBA::mergeConditions($conditionStrings, ["`contact-id` IN (SELECT `contact-id` FROM `group_member` WHERE `gid` = ?)", $this->circleId]); + $commonCondition = DBA::mergeConditions($commonCondition, ["`contact-id` IN (SELECT `contact-id` FROM `group_member` WHERE `gid` = ?)", $this->circleId]); } // Currently only the order modes "received" and "commented" are in use if (!empty($this->itemUriId)) { - $conditionStrings = DBA::mergeConditions($conditionStrings, ['uri-id' => $this->itemUriId]); + $commonCondition = DBA::mergeConditions($commonCondition, ['uri-id' => $this->itemUriId]); } else { if (isset($this->maxId)) { switch ($this->order) { case 'received': - $conditionStrings = DBA::mergeConditions($conditionStrings, ["`received` < ?", $this->maxId]); + $commonCondition = DBA::mergeConditions($commonCondition, ["`received` < ?", $this->maxId]); break; case 'commented': - $conditionStrings = DBA::mergeConditions($conditionStrings, ["`commented` < ?", $this->maxId]); + $commonCondition = DBA::mergeConditions($commonCondition, ["`commented` < ?", $this->maxId]); break; case 'created': - $conditionStrings = DBA::mergeConditions($conditionStrings, ["`created` < ?", $this->maxId]); + $commonCondition = DBA::mergeConditions($commonCondition, ["`created` < ?", $this->maxId]); break; case 'uriid': - $conditionStrings = DBA::mergeConditions($conditionStrings, ["`uri-id` < ?", $this->maxId]); + $commonCondition = DBA::mergeConditions($commonCondition, ["`uri-id` < ?", $this->maxId]); break; } } @@ -520,16 +520,16 @@ class Network extends Timeline if (isset($this->minId)) { switch ($this->order) { case 'received': - $conditionStrings = DBA::mergeConditions($conditionStrings, ["`received` > ?", $this->minId]); + $commonCondition = DBA::mergeConditions($commonCondition, ["`received` > ?", $this->minId]); break; case 'commented': - $conditionStrings = DBA::mergeConditions($conditionStrings, ["`commented` > ?", $this->minId]); + $commonCondition = DBA::mergeConditions($commonCondition, ["`commented` > ?", $this->minId]); break; case 'created': - $conditionStrings = DBA::mergeConditions($conditionStrings, ["`created` > ?", $this->minId]); + $commonCondition = DBA::mergeConditions($commonCondition, ["`created` > ?", $this->minId]); break; case 'uriid': - $conditionStrings = DBA::mergeConditions($conditionStrings, ["`uri-id` > ?", $this->minId]); + $commonCondition = DBA::mergeConditions($commonCondition, ["`uri-id` > ?", $this->minId]); break; } } @@ -546,13 +546,62 @@ class Network extends Timeline $params['order'] = [$this->order => true]; } - $items = $this->database->selectToArray($this->circleId ? 'network-thread-circle-view' : 'network-thread-view', [], DBA::mergeConditions($conditionFields, $conditionStrings), $params); + $filterchannels = $this->pConfig->get($this->session->getLocalUserId(), 'channel', 'filter_channels') ?? []; + if ($filterchannels) { + $query = "`uri-id` NOT IN (SELECT `uri-id` FROM `channel-post-view` WHERE `uid` = ? AND `channel` IN (" . substr(str_repeat('?, ', count($filterchannels)), 0, -2) . "))"; + $commonCondition = DBA::mergeConditions($commonCondition, array_merge([$query], [$this->session->getLocalUserId()], $filterchannels)); + } + + $fields = ['uri-id', 'created', 'received', 'commented', 'channel']; + $condition = DBA::mergeConditions($timelineCondition, $commonCondition); + + $timeline = $this->database->getSQL($this->circleId ? 'network-thread-circle-view' : 'network-thread-view', $fields, $condition, $params); + array_shift($condition); + $sql = '(' . $timeline . ')'; + + $systemchannels = []; + $userchannels = []; + foreach ($this->pConfig->get($this->session->getLocalUserId(), 'channel', 'timeline_channels') ?? [] as $channel) { + if (is_numeric($channel)) { + $userchannels[] = (int)$channel; + } else { + $systemchannels[] = $channel; + } + } + + if ($systemchannels) { + $channel_condition = DBA::mergeConditions(['channel' => $systemchannels, 'in-timeline' => false], $commonCondition); + $sql .= ' UNION ALL (' . $this->database->getSQL('system-channel-post-view', $fields, $channel_condition, $params) . ')'; + array_shift($channel_condition); + $condition = array_merge($condition, $channel_condition); + } + + if ($userchannels) { + $channel_condition = DBA::mergeConditions(['channel' => $userchannels, 'in-timeline' => false], $commonCondition); + $sql .= ' UNION ALL (' . $this->database->getSQL('channel-post-view', $fields, $channel_condition, $params) . ')'; + array_shift($channel_condition); + $condition = array_merge($condition, $channel_condition); + } + + if ($systemchannels || $userchannels) { + $sql .= DBA::buildParameter($params); + } + + $result = $this->database->p($sql, $condition); + $items = $this->database->toArray($result); // min_id quirk, continued if (isset($this->minId) && !isset($this->maxId)) { $items = array_reverse($items); } + // Avoid duplicates + $posts = []; + foreach ($items as $item) { + $posts[$item['uri-id']] = $item; + } + $items = $posts; + if ($this->ping || !$this->database->isResult($items)) { return $items; } diff --git a/src/Module/Conversation/Timeline.php b/src/Module/Conversation/Timeline.php index 1c91409098..bbf700ce1d 100644 --- a/src/Module/Conversation/Timeline.php +++ b/src/Module/Conversation/Timeline.php @@ -14,6 +14,7 @@ use Friendica\BaseModule; use Friendica\Content\Conversation\Collection\Timelines; use Friendica\Content\Conversation\Entity\Channel as ChannelEntity; use Friendica\Content\Conversation\Entity\Community; +use Friendica\Content\Conversation\Entity\UserDefinedChannel as EntityUserDefinedChannel; use Friendica\Content\Conversation\Repository\UserDefinedChannel; use Friendica\Core\Cache\Capability\ICanCache; use Friendica\Core\Config\Capability\IManageConfigValues; @@ -395,7 +396,7 @@ class Timeline extends BaseModule } elseif (is_numeric($this->selectedTab) && !empty($channel = $this->channelRepository->selectById($this->selectedTab, $uid))) { if (!$this->config->get('system', 'channel_cache')) { $condition = $this->channelRepository->getCondition($channel, $uid); - if (in_array($channel->circle, [-3, -4, -5])) { + if (in_array($channel->circle, [EntityUserDefinedChannel::CIRCLE_CREATION, EntityUserDefinedChannel::CIRCLE_POSTS, EntityUserDefinedChannel::CIRCLE_ACTIVITY])) { $table = SearchIndex::getSearchView(); $condition = DBA::mergeConditions($condition, ['uid' => $uid]); } @@ -403,9 +404,13 @@ class Timeline extends BaseModule $condition = ['channel' => $this->selectedTab]; $table = 'channel-post-view'; } - if (in_array($channel->circle, [-3, -4, -5])) { - $orders = ['-3' => 'created', '-4' => 'received', '-5' => 'commented']; - $this->order = $orders[$channel->circle]; + if (in_array($channel->circle, [EntityUserDefinedChannel::CIRCLE_CREATION, EntityUserDefinedChannel::CIRCLE_POSTS, EntityUserDefinedChannel::CIRCLE_ACTIVITY])) { + $orders = [ + EntityUserDefinedChannel::CIRCLE_CREATION => 'created', + EntityUserDefinedChannel::CIRCLE_POSTS => 'received', + EntityUserDefinedChannel::CIRCLE_ACTIVITY => 'commented' + ]; + $this->order = $orders[(int)$channel->circle]; } } diff --git a/src/Module/Settings/Channels.php b/src/Module/Settings/Channels.php index 393d4bf1a7..e7b41eff34 100644 --- a/src/Module/Settings/Channels.php +++ b/src/Module/Settings/Channels.php @@ -8,6 +8,7 @@ namespace Friendica\Module\Settings; use Friendica\App; +use Friendica\Content\Conversation\Entity\UserDefinedChannel as EntityUserDefinedChannel; use Friendica\Content\Conversation\Factory; use Friendica\Content\Conversation\Repository\UserDefinedChannel; use Friendica\Core\Config\Capability\IManageConfigValues; @@ -140,17 +141,17 @@ class Channels extends BaseSettings if (in_array($account_type, [User::ACCOUNT_TYPE_COMMUNITY, User::ACCOUNT_TYPE_RELAY])) { $intro = $this->t('This page can be used to define the channels that will automatically be reshared by your account.'); $circles = [ - 0 => $this->l10n->t('Global Community') + EntityUserDefinedChannel::CIRCLE_GLOBAL => $this->l10n->t('Global Community') ]; } else { $intro = $this->t('This page can be used to define your own channels.'); $circles = [ - 0 => $this->l10n->t('Global Community'), - -5 => $this->l10n->t('Latest Activity'), - -4 => $this->l10n->t('Latest Posts'), - -3 => $this->l10n->t('Latest Creation'), - -1 => $this->l10n->t('Following'), - -2 => $this->l10n->t('Followers'), + EntityUserDefinedChannel::CIRCLE_GLOBAL => $this->l10n->t('Global Community'), + EntityUserDefinedChannel::CIRCLE_ACTIVITY => $this->l10n->t('Latest Activity'), + EntityUserDefinedChannel::CIRCLE_POSTS => $this->l10n->t('Latest Posts'), + EntityUserDefinedChannel::CIRCLE_CREATION => $this->l10n->t('Latest Creation'), + EntityUserDefinedChannel::CIRCLE_FOLLOWING => $this->l10n->t('Following'), + EntityUserDefinedChannel::CIRCLE_FOLLOWERS => $this->l10n->t('Followers'), ]; } diff --git a/src/Module/Settings/Display.php b/src/Module/Settings/Display.php index 183e84c0f6..1637d185d5 100644 --- a/src/Module/Settings/Display.php +++ b/src/Module/Settings/Display.php @@ -13,6 +13,8 @@ use Friendica\App\Page; use Friendica\AppHelper; use Friendica\Content\ContactSelector; use Friendica\Content\Conversation\Collection\Timelines; +use Friendica\Content\Conversation\Entity\Channel; +use Friendica\Content\Conversation\Entity\UserDefinedChannel; use Friendica\Content\Text\BBCode; use Friendica\Content\Conversation\Factory\Channel as ChannelFactory; use Friendica\Content\Conversation\Factory\Community as CommunityFactory; @@ -26,11 +28,13 @@ use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues; use Friendica\Core\Renderer; use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Core\Theme; +use Friendica\Model\Post\Engagement; use Friendica\Model\User; use Friendica\Module\BaseSettings; use Friendica\Module\Response; use Friendica\Navigation\SystemMessages; use Friendica\Network\HTTPException; +use Friendica\Util\DateTimeFormat; use Friendica\Util\Profiler; use Friendica\Util\Strings; use Psr\Log\LoggerInterface; @@ -91,6 +95,8 @@ class Display extends BaseSettings $enable = (array)$request['enable']; $bookmark = (array)$request['bookmark']; $channel_languages = (array)$request['channel_languages']; + $timeline_channels = (array)$request['timeline_channels']; + $filter_channels = (array)$request['filter_channels']; $first_day_of_week = (int)$request['first_day_of_week']; $calendar_default_view = trim($request['calendar_default_view']); $infinite_scroll = (bool)$request['infinite_scroll']; @@ -170,6 +176,8 @@ class Display extends BaseSettings $this->pConfig->set($uid, 'system', 'network_timelines', $network_timelines); $this->pConfig->set($uid, 'system', 'enabled_timelines', $enabled_timelines); $this->pConfig->set($uid, 'channel', 'languages', $channel_languages); + $this->pConfig->set($uid, 'channel', 'timeline_channels', $timeline_channels); + $this->pConfig->set($uid, 'channel', 'filter_channels', $filter_channels); $this->pConfig->set($uid, 'accessibility', 'hide_empty_descriptions', $hide_empty_descriptions); $this->pConfig->set($uid, 'accessibility', 'hide_custom_emojis', $hide_custom_emojis); @@ -286,6 +294,27 @@ class Display extends BaseSettings $enabled_timelines = $this->pConfig->get($uid, 'system', 'enabled_timelines', $this->getAvailableTimelines($uid, false)->column('code')); $channel_languages = User::getWantedLanguages($uid); $languages = $this->l10n->getLanguageCodes(true, true); + $timeline_channels = $this->pConfig->get($uid, 'channel', 'timeline_channels') ?? []; + $filter_channels = $this->pConfig->get($uid, 'channel', 'filter_channels') ?? []; + + $channels = []; + if ($this->config->get('system', 'system_channel_cache')) { + foreach ($this->channel->getTimelines($uid) as $channel) { + if (!in_array($channel->code, [Channel::FORYOU, Channel::QUIETSHARERS])) { + $channels[$channel->code] = $channel->label; + } + } + } + + $filter = []; + if ($this->config->get('system', 'channel_cache')) { + foreach ($this->userDefinedChannel->selectByUid($uid) as $channel) { + $filter[$channel->code] = $channel->label; + if (in_array($channel->circle, [UserDefinedChannel::CIRCLE_GLOBAL, UserDefinedChannel::CIRCLE_FOLLOWERS])) { + $channels[$channel->code] = $channel->label; + } + } + } $timelines = []; foreach ($this->getAvailableTimelines($uid) as $timeline) { @@ -441,7 +470,11 @@ class Display extends BaseSettings '$timelines' => $timelines, '$timeline_explanation' => $this->t('Enable timelines that you want to see in the channels widget. Bookmark timelines that you want to see in the top menu.'), - '$channel_languages' => ['channel_languages[]', $this->t('Channel languages:'), $channel_languages, $this->t('Select all the languages you want to see in your channels. "Unspecified" describes all posts for which no language information was detected (e.g. posts with just an image or too little text to be sure of the language). If you want to see all languages, you will need to select all items in the list.'), $languages, 'multiple'], + '$channel_languages' => ['channel_languages[]', $this->t('Channel languages:'), $channel_languages, $this->t('Select all the languages you want to see in your channels. "Unspecified" describes all posts for which no language information was detected (e.g. posts with just an image or too little text to be sure of the language). If you want to see all languages, you will need to select all items in the list.'), $languages, 'multiple'], + '$timeline_channels' => ['timeline_channels[]', $this->t('Timeline channels:'), $timeline_channels, $this->t('Select all the channels that you want to see in your network timeline.'), $channels, 'multiple'], + '$has_timeline_channels' => !empty($channels), + '$filter_channels' => ['filter_channels[]', $this->t('Filter channels:'), $filter_channels, $this->t('Select all the channels that you want to use as a filter for your network timeline. All posts from these channels will be hidden. For technical reasons postings that are older than %s will not be filtered.', DateTimeFormat::local(Engagement::getCreationDateLimit(false)), 'r'), $filter, 'multiple'], + '$has_filter_channels' => !empty($filter), '$first_day_of_week' => ['first_day_of_week', $this->t('Beginning of week:'), $first_day_of_week, '', $weekdays, false], '$calendar_default_view' => ['calendar_default_view', $this->t('Default calendar view:'), $calendar_default_view, '', $calendarViews, false], diff --git a/src/Worker/UpdateChannelPosts.php b/src/Worker/UpdateChannelPosts.php index 96bb2236a0..02ec04a420 100644 --- a/src/Worker/UpdateChannelPosts.php +++ b/src/Worker/UpdateChannelPosts.php @@ -9,6 +9,7 @@ declare(strict_types=1); namespace Friendica\Worker; +use Friendica\Content\Conversation\Entity\UserDefinedChannel; use Friendica\Database\Database; use Friendica\Database\DBA; use Friendica\DI; @@ -53,9 +54,13 @@ final class UpdateChannelPosts $order = 'created'; $table = 'post-engagement'; $fields = ['uri-id', 'created']; - if (in_array($channel->circle, [-3, -4, -5])) { - $orders = ['-3' => 'created', '-4' => 'received', '-5' => 'commented']; - $order = $orders[$channel->circle]; + if (in_array($channel->circle, [UserDefinedChannel::CIRCLE_CREATION, UserDefinedChannel::CIRCLE_POSTS, UserDefinedChannel::CIRCLE_ACTIVITY])) { + $orders = [ + UserDefinedChannel::CIRCLE_CREATION => 'created', + UserDefinedChannel::CIRCLE_POSTS => 'received', + UserDefinedChannel::CIRCLE_ACTIVITY => 'commented' + ]; + $order = $orders[(int)$channel->circle]; $table = 'post-engagement-user-view'; $fields = ['uri-id', 'created', 'received', 'commented']; $condition = DBA::mergeConditions($condition, ['uid' => $uid]); diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index f1e3c58156..a876046452 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -44,7 +44,7 @@ use Friendica\Database\DBA; // This file is required several times during the test in DbaDefinition which justifies this condition if (!defined('DB_UPDATE_VERSION')) { - define('DB_UPDATE_VERSION', 1586); + define('DB_UPDATE_VERSION', 1587); } return [ @@ -1373,6 +1373,7 @@ return [ "channel" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["channel" => "id"], "comment" => "Channel id"], "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["post-engagement" => "uri-id"], "comment" => "Post engagement entry"], "uid" => ["type" => "mediumint unsigned", "not null" => "1", "foreign" => ["user" => "uid"], "comment" => "User id"], + "in-timeline" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "If true, this post is in the user's main timeline"], "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], "received" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], "commented" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""] @@ -1392,6 +1393,7 @@ return [ "channel" => ["type" => "varchar(20)", "not null" => "1", "primary" => "1", "comment" => "System channel id"], "uid" => ["type" => "mediumint unsigned", "not null" => "1", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "User id"], "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["post-engagement" => "uri-id"], "comment" => "Post engagement entry"], + "in-timeline" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "If true, this post is in the user's main timeline"], "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], "received" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], "commented" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""] @@ -1400,7 +1402,7 @@ return [ "PRIMARY" => ["channel", "uid", "uri-id"], "uri-id" => ["uri-id"], "uid" => ["uid"], - "channel_created" => ["channel", "uid", "created"], + "channel_uid_created" => ["channel", "uid", "created"], ] ], "post-history" => [ diff --git a/static/dbview.config.php b/static/dbview.config.php index 1ef6492119..97d33f2bfc 100644 --- a/static/dbview.config.php +++ b/static/dbview.config.php @@ -52,6 +52,7 @@ return [ "channel" => ["channel-post", "channel"], "uid" => ["channel-post", "uid"], "uri-id" => ["channel-post", "uri-id"], + "in-timeline" => ["channel-post", "in-timeline"], "owner-id" => ["post-engagement", "owner-id"], "media-type" => ["post-engagement", "media-type"], "language" => ["post-engagement", "language"], @@ -78,6 +79,7 @@ return [ "channel" => ["system-channel-post", "channel"], "uid" => ["system-channel-post", "uid"], "uri-id" => ["system-channel-post", "uri-id"], + "in-timeline" => ["system-channel-post", "in-timeline"], "owner-id" => ["post-engagement", "owner-id"], "media-type" => ["post-engagement", "media-type"], "language" => ["post-engagement", "language"], @@ -1430,6 +1432,7 @@ return [ ], "network-thread-view" => [ "fields" => [ + "channel" => "''", "uri-id" => ["post-thread-user", "uri-id"], "parent" => ["post-thread-user", "post-user-id"], "received" => ["post-thread-user", "received"], @@ -1457,6 +1460,7 @@ return [ ], "network-thread-circle-view" => [ "fields" => [ + "channel" => "''", "uri-id" => ["post-thread-user", "uri-id"], "parent" => ["post-thread-user", "post-user-id"], "received" => ["post-thread-user", "received"], diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index d6d9649bed..55c3782771 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -38,13 +38,13 @@ msgstr "" msgid "Empty post discarded." msgstr "" -#: mod/item.php:437 src/Module/Admin/Themes/Details.php:31 +#: mod/item.php:439 src/Module/Admin/Themes/Details.php:31 #: src/Module/Admin/Themes/Index.php:51 src/Module/Debug/ItemBody.php:34 #: src/Module/Debug/ItemBody.php:42 src/Module/Item/Feed.php:66 msgid "Item not found." msgstr "" -#: mod/item.php:461 mod/message.php:56 mod/message.php:102 mod/notes.php:34 +#: mod/item.php:463 mod/message.php:56 mod/message.php:102 mod/notes.php:34 #: mod/photos.php:132 mod/photos.php:624 src/Model/Event.php:511 #: src/Module/Attach.php:40 src/Module/BaseApi.php:90 #: src/Module/BaseNotifications.php:83 src/Module/BaseSettings.php:38 @@ -66,11 +66,11 @@ msgstr "" #: src/Module/Register.php:87 src/Module/Register.php:216 #: src/Module/Register.php:255 src/Module/Search/Directory.php:23 #: src/Module/Settings/Account.php:34 src/Module/Settings/Account.php:337 -#: src/Module/Settings/Channels.php:52 src/Module/Settings/Channels.php:127 -#: src/Module/Settings/ContactImport.php:49 -#: src/Module/Settings/ContactImport.php:96 -#: src/Module/Settings/Delegation.php:76 src/Module/Settings/Display.php:81 -#: src/Module/Settings/Display.php:206 +#: src/Module/Settings/Channels.php:54 src/Module/Settings/Channels.php:135 +#: src/Module/Settings/ContactImport.php:50 +#: src/Module/Settings/ContactImport.php:97 +#: src/Module/Settings/Delegation.php:76 src/Module/Settings/Display.php:85 +#: src/Module/Settings/Display.php:214 #: src/Module/Settings/Profile/Photo/Crop.php:148 #: src/Module/Settings/Profile/Photo/Index.php:96 #: src/Module/Settings/RemoveMe.php:103 src/Module/Settings/UserExport.php:64 @@ -78,7 +78,7 @@ msgstr "" #: src/Module/Settings/UserExport.php:199 #: src/Module/Settings/UserExport.php:219 #: src/Module/Settings/UserExport.php:284 src/Module/User/Delegation.php:146 -#: src/Module/User/Import.php:72 src/Module/User/Import.php:79 +#: src/Module/User/Import.php:73 src/Module/User/Import.php:80 msgid "Permission denied." msgstr "" @@ -272,7 +272,7 @@ msgstr "" msgid "Your message:" msgstr "" -#: mod/message.php:188 mod/message.php:345 src/Content/Conversation.php:364 +#: mod/message.php:188 mod/message.php:345 src/Content/Conversation.php:371 #: src/Module/Post/Edit.php:129 msgid "Upload photo" msgstr "" @@ -282,7 +282,7 @@ msgid "Insert web link" msgstr "" #: mod/message.php:190 mod/message.php:348 mod/photos.php:1256 -#: src/Content/Conversation.php:395 src/Content/Conversation.php:1574 +#: src/Content/Conversation.php:402 src/Content/Conversation.php:1611 #: src/Module/Item/Compose.php:205 src/Module/Post/Edit.php:143 #: src/Object/Post.php:617 msgid "Please wait" @@ -304,11 +304,11 @@ msgstr "" msgid "Delete message" msgstr "" -#: mod/message.php:316 mod/message.php:444 +#: mod/message.php:316 mod/message.php:439 msgid "D, d M Y - g:i A" msgstr "" -#: mod/message.php:331 mod/message.php:441 +#: mod/message.php:331 mod/message.php:436 msgid "Delete conversation" msgstr "" @@ -320,22 +320,22 @@ msgstr "" msgid "Send Reply" msgstr "" -#: mod/message.php:415 +#: mod/message.php:410 #, php-format msgid "Unknown sender - %s" msgstr "" -#: mod/message.php:417 +#: mod/message.php:412 #, php-format msgid "You and %s" msgstr "" -#: mod/message.php:419 +#: mod/message.php:414 #, php-format msgid "%s and You" msgstr "" -#: mod/message.php:447 +#: mod/message.php:442 #, php-format msgid "%d message" msgid_plural "%d messages" @@ -352,7 +352,7 @@ msgstr "" #: mod/notes.php:46 src/Module/Admin/Storage.php:128 #: src/Module/Filer/SaveTag.php:60 src/Module/Post/Edit.php:127 -#: src/Module/Settings/Channels.php:220 +#: src/Module/Settings/Channels.php:228 msgid "Save" msgstr "" @@ -449,7 +449,7 @@ msgstr "" msgid "Do not show a status post for this upload" msgstr "" -#: mod/photos.php:691 mod/photos.php:1051 src/Content/Conversation.php:397 +#: mod/photos.php:691 mod/photos.php:1051 src/Content/Conversation.php:404 #: src/Module/Calendar/Event/Form.php:239 src/Module/Post/Edit.php:181 msgid "Permissions" msgstr "" @@ -462,7 +462,7 @@ msgstr "" msgid "Delete Album" msgstr "" -#: mod/photos.php:758 mod/photos.php:857 src/Content/Conversation.php:412 +#: mod/photos.php:758 mod/photos.php:857 src/Content/Conversation.php:419 #: src/Module/Contact/Follow.php:158 src/Module/Contact/Revoke.php:92 #: src/Module/Contact/Unfollow.php:112 #: src/Module/Media/Attachment/Browser.php:64 @@ -588,23 +588,23 @@ msgid "Comment" msgstr "" #: mod/photos.php:1098 mod/photos.php:1154 mod/photos.php:1234 -#: src/Content/Conversation.php:409 src/Module/Calendar/Event/Form.php:234 +#: src/Content/Conversation.php:416 src/Module/Calendar/Event/Form.php:234 #: src/Module/Item/Compose.php:200 src/Module/Post/Edit.php:163 #: src/Object/Post.php:1176 msgid "Preview" msgstr "" -#: mod/photos.php:1099 src/Content/Conversation.php:363 src/Content/Nav.php:113 +#: mod/photos.php:1099 src/Content/Conversation.php:370 src/Content/Nav.php:113 #: src/Module/Post/Edit.php:128 src/Object/Post.php:1164 msgid "Loading..." msgstr "" -#: mod/photos.php:1191 src/Content/Conversation.php:1496 +#: mod/photos.php:1191 src/Content/Conversation.php:1533 #: src/Object/Post.php:263 msgid "Select" msgstr "" -#: mod/photos.php:1192 mod/photos.php:1279 src/Content/Conversation.php:1497 +#: mod/photos.php:1192 mod/photos.php:1279 src/Content/Conversation.php:1534 #: src/Module/Moderation/Users/Active.php:92 #: src/Module/Moderation/Users/Blocked.php:92 #: src/Module/Moderation/Users/Index.php:100 @@ -777,12 +777,12 @@ msgstr "" #: src/Content/Widget.php:257 src/Core/ACL.php:185 src/Module/Contact.php:399 #: src/Module/Privacy/PermissionTooltip.php:181 #: src/Module/Privacy/PermissionTooltip.php:203 -#: src/Module/Settings/Channels.php:146 +#: src/Module/Settings/Channels.php:154 msgid "Followers" msgstr "" #: src/BaseModule.php:445 src/Content/Widget.php:258 src/Module/Contact.php:402 -#: src/Module/Settings/Channels.php:145 +#: src/Module/Settings/Channels.php:153 msgid "Following" msgstr "" @@ -1133,375 +1133,385 @@ msgstr "" msgid "%s (via %s)" msgstr "" -#: src/Content/Conversation.php:215 +#: src/Content/Conversation.php:222 msgid "and" msgstr "" -#: src/Content/Conversation.php:218 +#: src/Content/Conversation.php:225 #, php-format msgid "and %d other people" msgstr "" -#: src/Content/Conversation.php:224 +#: src/Content/Conversation.php:231 #, php-format msgid "%2$s likes this." msgid_plural "%2$s like this." msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:226 +#: src/Content/Conversation.php:233 #, php-format msgid "%2$s doesn't like this." msgid_plural "%2$s don't like this." msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:228 +#: src/Content/Conversation.php:235 #, php-format msgid "%2$s attends." msgid_plural "%2$s attend." msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:230 +#: src/Content/Conversation.php:237 #, php-format msgid "%2$s doesn't attend." msgid_plural "%2$s don't attend." msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:232 +#: src/Content/Conversation.php:239 #, php-format msgid "%2$s attends maybe." msgid_plural "%2$s attend maybe." msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:234 +#: src/Content/Conversation.php:241 #, php-format msgid "%2$s reshared this." msgid_plural "%2$s reshared this." msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:265 +#: src/Content/Conversation.php:272 #, php-format msgid " likes this" msgid_plural " like this" msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:274 +#: src/Content/Conversation.php:281 #, php-format msgid " attends" msgid_plural " attend" msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:277 +#: src/Content/Conversation.php:284 #, php-format msgid " doesn't attend" msgid_plural " don't attend" msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:280 +#: src/Content/Conversation.php:287 #, php-format msgid " attends maybe" msgid_plural " attend maybe" msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:283 +#: src/Content/Conversation.php:290 #, php-format msgid " reshared this" msgid_plural " reshared this" msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:329 +#: src/Content/Conversation.php:336 msgid "Visible to everybody" msgstr "" -#: src/Content/Conversation.php:330 src/Module/Item/Compose.php:199 +#: src/Content/Conversation.php:337 src/Module/Item/Compose.php:199 #: src/Object/Post.php:1175 msgid "Please enter a image/video/audio/webpage URL:" msgstr "" -#: src/Content/Conversation.php:331 +#: src/Content/Conversation.php:338 msgid "Tag term:" msgstr "" -#: src/Content/Conversation.php:332 +#: src/Content/Conversation.php:339 msgid "Save to Folder" msgstr "" -#: src/Content/Conversation.php:333 +#: src/Content/Conversation.php:340 msgid "Where are you right now?" msgstr "" -#: src/Content/Conversation.php:334 +#: src/Content/Conversation.php:341 msgid "Delete item(s)?" msgstr "" -#: src/Content/Conversation.php:335 src/Module/Post/Edit.php:105 +#: src/Content/Conversation.php:342 src/Module/Post/Edit.php:105 msgid "Post published." msgstr "" -#: src/Content/Conversation.php:336 src/Module/Post/Edit.php:106 +#: src/Content/Conversation.php:343 src/Module/Post/Edit.php:106 msgid "Go to post" msgstr "" -#: src/Content/Conversation.php:349 src/Module/Item/Compose.php:174 +#: src/Content/Conversation.php:356 src/Module/Item/Compose.php:174 msgid "Created at" msgstr "" -#: src/Content/Conversation.php:359 +#: src/Content/Conversation.php:366 msgid "New Post" msgstr "" -#: src/Content/Conversation.php:362 +#: src/Content/Conversation.php:369 msgid "Share" msgstr "" -#: src/Content/Conversation.php:365 src/Module/Post/Edit.php:130 +#: src/Content/Conversation.php:372 src/Module/Post/Edit.php:130 msgid "upload photo" msgstr "" -#: src/Content/Conversation.php:366 src/Module/Post/Edit.php:131 +#: src/Content/Conversation.php:373 src/Module/Post/Edit.php:131 msgid "Attach file" msgstr "" -#: src/Content/Conversation.php:367 src/Module/Post/Edit.php:132 +#: src/Content/Conversation.php:374 src/Module/Post/Edit.php:132 msgid "attach file" msgstr "" -#: src/Content/Conversation.php:368 src/Module/Item/Compose.php:189 +#: src/Content/Conversation.php:375 src/Module/Item/Compose.php:189 #: src/Module/Post/Edit.php:169 src/Object/Post.php:1165 msgid "Bold" msgstr "" -#: src/Content/Conversation.php:369 src/Module/Item/Compose.php:190 +#: src/Content/Conversation.php:376 src/Module/Item/Compose.php:190 #: src/Module/Post/Edit.php:170 src/Object/Post.php:1166 msgid "Italic" msgstr "" -#: src/Content/Conversation.php:370 src/Module/Item/Compose.php:191 +#: src/Content/Conversation.php:377 src/Module/Item/Compose.php:191 #: src/Module/Post/Edit.php:171 src/Object/Post.php:1167 msgid "Underline" msgstr "" -#: src/Content/Conversation.php:371 src/Module/Item/Compose.php:192 +#: src/Content/Conversation.php:378 src/Module/Item/Compose.php:192 #: src/Module/Post/Edit.php:172 src/Object/Post.php:1169 msgid "Quote" msgstr "" -#: src/Content/Conversation.php:372 src/Module/Item/Compose.php:193 +#: src/Content/Conversation.php:379 src/Module/Item/Compose.php:193 #: src/Module/Post/Edit.php:173 src/Object/Post.php:1170 msgid "Add emojis" msgstr "" -#: src/Content/Conversation.php:373 src/Module/Item/Compose.php:194 +#: src/Content/Conversation.php:380 src/Module/Item/Compose.php:194 #: src/Object/Post.php:1168 msgid "Content Warning" msgstr "" -#: src/Content/Conversation.php:374 src/Module/Item/Compose.php:195 +#: src/Content/Conversation.php:381 src/Module/Item/Compose.php:195 #: src/Module/Post/Edit.php:174 src/Object/Post.php:1171 msgid "Code" msgstr "" -#: src/Content/Conversation.php:375 src/Module/Item/Compose.php:196 +#: src/Content/Conversation.php:382 src/Module/Item/Compose.php:196 #: src/Object/Post.php:1172 msgid "Image" msgstr "" -#: src/Content/Conversation.php:376 src/Module/Item/Compose.php:197 +#: src/Content/Conversation.php:383 src/Module/Item/Compose.php:197 #: src/Module/Post/Edit.php:175 src/Object/Post.php:1173 msgid "Link" msgstr "" -#: src/Content/Conversation.php:377 src/Module/Item/Compose.php:198 +#: src/Content/Conversation.php:384 src/Module/Item/Compose.php:198 #: src/Module/Post/Edit.php:176 src/Object/Post.php:1174 msgid "Link or Media" msgstr "" -#: src/Content/Conversation.php:378 +#: src/Content/Conversation.php:385 msgid "Video" msgstr "" -#: src/Content/Conversation.php:379 src/Module/Item/Compose.php:201 +#: src/Content/Conversation.php:386 src/Module/Item/Compose.php:201 #: src/Module/Post/Edit.php:139 msgid "Set your location" msgstr "" -#: src/Content/Conversation.php:380 src/Module/Post/Edit.php:140 +#: src/Content/Conversation.php:387 src/Module/Post/Edit.php:140 msgid "set location" msgstr "" -#: src/Content/Conversation.php:381 src/Module/Post/Edit.php:141 +#: src/Content/Conversation.php:388 src/Module/Post/Edit.php:141 msgid "Clear browser location" msgstr "" -#: src/Content/Conversation.php:382 src/Module/Post/Edit.php:142 +#: src/Content/Conversation.php:389 src/Module/Post/Edit.php:142 msgid "clear location" msgstr "" -#: src/Content/Conversation.php:384 src/Module/Item/Compose.php:206 +#: src/Content/Conversation.php:391 src/Module/Item/Compose.php:206 #: src/Module/Post/Edit.php:155 msgid "Set title" msgstr "" -#: src/Content/Conversation.php:386 src/Module/Item/Compose.php:207 +#: src/Content/Conversation.php:393 src/Module/Item/Compose.php:207 #: src/Module/Post/Edit.php:157 msgid "Categories (comma-separated list)" msgstr "" -#: src/Content/Conversation.php:391 src/Module/Item/Compose.php:227 +#: src/Content/Conversation.php:398 src/Module/Item/Compose.php:227 msgid "Scheduled at" msgstr "" -#: src/Content/Conversation.php:396 src/Module/Post/Edit.php:144 +#: src/Content/Conversation.php:403 src/Module/Post/Edit.php:144 msgid "Permission settings" msgstr "" -#: src/Content/Conversation.php:405 src/Module/Post/Edit.php:153 +#: src/Content/Conversation.php:412 src/Module/Post/Edit.php:153 msgid "Public post" msgstr "" -#: src/Content/Conversation.php:419 src/Content/Item.php:442 -#: src/Content/Widget/VCard.php:120 src/Model/Contact.php:1304 +#: src/Content/Conversation.php:426 src/Content/Item.php:442 +#: src/Content/Widget/VCard.php:120 src/Model/Contact.php:1307 #: src/Model/Profile.php:460 src/Module/Admin/Logs/View.php:80 #: src/Module/Post/Edit.php:179 msgid "Message" msgstr "" -#: src/Content/Conversation.php:420 src/Module/Post/Edit.php:180 +#: src/Content/Conversation.php:427 src/Module/Post/Edit.php:180 msgid "Add file" msgstr "" -#: src/Content/Conversation.php:422 src/Module/Post/Edit.php:183 +#: src/Content/Conversation.php:429 src/Module/Post/Edit.php:183 msgid "Open Compose page" msgstr "" -#: src/Content/Conversation.php:592 +#: src/Content/Conversation.php:599 msgid "remove" msgstr "" -#: src/Content/Conversation.php:596 +#: src/Content/Conversation.php:603 msgid "Delete Selected Items" msgstr "" -#: src/Content/Conversation.php:720 src/Content/Conversation.php:723 -#: src/Content/Conversation.php:726 src/Content/Conversation.php:729 -#: src/Content/Conversation.php:732 +#: src/Content/Conversation.php:735 src/Content/Conversation.php:738 +#: src/Content/Conversation.php:741 src/Content/Conversation.php:744 +#: src/Content/Conversation.php:747 #, php-format msgid "You had been addressed (%s)." msgstr "" -#: src/Content/Conversation.php:735 +#: src/Content/Conversation.php:750 #, php-format msgid "You are following %s." msgstr "" -#: src/Content/Conversation.php:740 +#: src/Content/Conversation.php:755 #, php-format msgid "You subscribed to %s." msgstr "" -#: src/Content/Conversation.php:742 +#: src/Content/Conversation.php:757 msgid "You subscribed to one or more tags in this post." msgstr "" -#: src/Content/Conversation.php:762 +#: src/Content/Conversation.php:777 #, php-format msgid "%s reshared this." msgstr "" -#: src/Content/Conversation.php:764 +#: src/Content/Conversation.php:779 msgid "Reshared" msgstr "" -#: src/Content/Conversation.php:764 +#: src/Content/Conversation.php:779 #, php-format msgid "Reshared by %s <%s>" msgstr "" -#: src/Content/Conversation.php:767 +#: src/Content/Conversation.php:782 #, php-format msgid "%s is participating in this thread." msgstr "" -#: src/Content/Conversation.php:770 +#: src/Content/Conversation.php:785 msgid "Stored for general reasons" msgstr "" -#: src/Content/Conversation.php:773 +#: src/Content/Conversation.php:788 msgid "Global post" msgstr "" -#: src/Content/Conversation.php:776 +#: src/Content/Conversation.php:791 msgid "Sent via an relay server" msgstr "" -#: src/Content/Conversation.php:776 +#: src/Content/Conversation.php:791 #, php-format msgid "Sent via the relay server %s <%s>" msgstr "" -#: src/Content/Conversation.php:779 +#: src/Content/Conversation.php:794 msgid "Fetched" msgstr "" -#: src/Content/Conversation.php:779 +#: src/Content/Conversation.php:794 #, php-format msgid "Fetched because of %s <%s>" msgstr "" -#: src/Content/Conversation.php:782 +#: src/Content/Conversation.php:797 msgid "Stored because of a child post to complete this thread." msgstr "" -#: src/Content/Conversation.php:785 +#: src/Content/Conversation.php:800 msgid "Local delivery" msgstr "" -#: src/Content/Conversation.php:788 +#: src/Content/Conversation.php:803 msgid "Stored because of your activity (like, comment, star, ...)" msgstr "" -#: src/Content/Conversation.php:791 +#: src/Content/Conversation.php:806 msgid "Distributed" msgstr "" -#: src/Content/Conversation.php:794 +#: src/Content/Conversation.php:809 msgid "Pushed to us" msgstr "" -#: src/Content/Conversation.php:1516 src/Object/Post.php:250 +#: src/Content/Conversation.php:816 +#, php-format +msgid "Channel \"%s\": %s" +msgstr "" + +#: src/Content/Conversation.php:818 +#, php-format +msgid "Channel \"%s\"" +msgstr "" + +#: src/Content/Conversation.php:1553 src/Object/Post.php:250 msgid "Pinned item" msgstr "" -#: src/Content/Conversation.php:1533 src/Object/Post.php:552 +#: src/Content/Conversation.php:1570 src/Object/Post.php:552 #: src/Object/Post.php:553 #, php-format msgid "View %s's profile @ %s" msgstr "" -#: src/Content/Conversation.php:1547 src/Object/Post.php:540 +#: src/Content/Conversation.php:1584 src/Object/Post.php:540 msgid "Categories:" msgstr "" -#: src/Content/Conversation.php:1548 src/Object/Post.php:541 +#: src/Content/Conversation.php:1585 src/Object/Post.php:541 msgid "Filed under:" msgstr "" -#: src/Content/Conversation.php:1556 src/Object/Post.php:568 +#: src/Content/Conversation.php:1593 src/Object/Post.php:568 #, php-format msgid "%s from %s" msgstr "" -#: src/Content/Conversation.php:1572 +#: src/Content/Conversation.php:1609 msgid "View in context" msgstr "" @@ -1555,7 +1565,7 @@ msgid "Posts from accounts that you follow but who don't post very often" msgstr "" #: src/Content/Conversation/Factory/Channel.php:36 -#: src/Module/Settings/Channels.php:185 src/Module/Settings/Channels.php:211 +#: src/Module/Settings/Channels.php:193 src/Module/Settings/Channels.php:219 msgid "Images" msgstr "" @@ -1564,7 +1574,7 @@ msgid "Posts with images" msgstr "" #: src/Content/Conversation/Factory/Channel.php:37 -#: src/Module/Settings/Channels.php:187 src/Module/Settings/Channels.php:213 +#: src/Module/Settings/Channels.php:195 src/Module/Settings/Channels.php:221 msgid "Audio" msgstr "" @@ -1573,7 +1583,7 @@ msgid "Posts with audio" msgstr "" #: src/Content/Conversation/Factory/Channel.php:38 -#: src/Module/Settings/Channels.php:186 src/Module/Settings/Channels.php:212 +#: src/Module/Settings/Channels.php:194 src/Module/Settings/Channels.php:220 msgid "Videos" msgstr "" @@ -1590,7 +1600,7 @@ msgid "Posts from local users on this server" msgstr "" #: src/Content/Conversation/Factory/Community.php:33 -#: src/Module/Settings/Channels.php:136 src/Module/Settings/Channels.php:141 +#: src/Module/Settings/Channels.php:144 src/Module/Settings/Channels.php:149 msgid "Global Community" msgstr "" @@ -1599,7 +1609,7 @@ msgid "Posts from users of the whole federated network" msgstr "" #: src/Content/Conversation/Factory/Network.php:24 -#: src/Module/Settings/Channels.php:142 +#: src/Module/Settings/Channels.php:150 msgid "Latest Activity" msgstr "" @@ -1608,7 +1618,7 @@ msgid "Sort by latest activity" msgstr "" #: src/Content/Conversation/Factory/Network.php:25 -#: src/Module/Settings/Channels.php:143 +#: src/Module/Settings/Channels.php:151 msgid "Latest Posts" msgstr "" @@ -1617,7 +1627,7 @@ msgid "Sort by post received date" msgstr "" #: src/Content/Conversation/Factory/Network.php:26 -#: src/Module/Settings/Channels.php:144 +#: src/Module/Settings/Channels.php:152 msgid "Latest Creation" msgstr "" @@ -1745,7 +1755,7 @@ msgstr "" #: src/Content/Feature.php:132 src/Content/Widget.php:626 #: src/Module/Admin/Site.php:474 src/Module/BaseSettings.php:113 -#: src/Module/Settings/Channels.php:216 src/Module/Settings/Display.php:400 +#: src/Module/Settings/Channels.php:224 src/Module/Settings/Display.php:429 msgid "Channels" msgstr "" @@ -1769,7 +1779,7 @@ msgstr "" msgid "Display a list of folders in which posts are stored." msgstr "" -#: src/Content/Feature.php:135 src/Module/Conversation/Timeline.php:190 +#: src/Content/Feature.php:135 src/Module/Conversation/Timeline.php:188 msgid "Own Contacts" msgstr "" @@ -1838,7 +1848,7 @@ msgstr "" msgid "Find groups to join" msgstr "" -#: src/Content/Item.php:336 src/Model/Item.php:2787 +#: src/Content/Item.php:336 src/Model/Item.php:2834 msgid "event" msgstr "" @@ -1846,7 +1856,7 @@ msgstr "" msgid "status" msgstr "" -#: src/Content/Item.php:345 src/Model/Item.php:2789 +#: src/Content/Item.php:345 src/Model/Item.php:2836 #: src/Module/Post/Tag/Add.php:112 msgid "photo" msgstr "" @@ -1864,27 +1874,27 @@ msgstr "" msgid "Complete Thread" msgstr "" -#: src/Content/Item.php:437 src/Model/Contact.php:1299 +#: src/Content/Item.php:437 src/Model/Contact.php:1302 msgid "View Status" msgstr "" -#: src/Content/Item.php:438 src/Content/Item.php:461 src/Model/Contact.php:1234 -#: src/Model/Contact.php:1290 src/Model/Contact.php:1300 +#: src/Content/Item.php:438 src/Content/Item.php:461 src/Model/Contact.php:1237 +#: src/Model/Contact.php:1293 src/Model/Contact.php:1303 #: src/Module/Directory.php:143 src/Module/Settings/Profile/Index.php:279 msgid "View Profile" msgstr "" -#: src/Content/Item.php:439 src/Model/Contact.php:1301 +#: src/Content/Item.php:439 src/Model/Contact.php:1304 msgid "View Photos" msgstr "" -#: src/Content/Item.php:440 src/Model/Contact.php:1268 +#: src/Content/Item.php:440 src/Model/Contact.php:1271 #: src/Model/Profile.php:443 msgid "Network Posts" msgstr "" -#: src/Content/Item.php:441 src/Model/Contact.php:1292 -#: src/Model/Contact.php:1303 +#: src/Content/Item.php:441 src/Model/Contact.php:1295 +#: src/Model/Contact.php:1306 msgid "View Contact" msgstr "" @@ -1898,8 +1908,8 @@ msgstr "" #: src/Content/Item.php:444 src/Module/Contact.php:454 #: src/Module/Contact/Profile.php:587 -#: src/Module/Notifications/Introductions.php:126 -#: src/Module/Notifications/Introductions.php:200 +#: src/Module/Notifications/Introductions.php:130 +#: src/Module/Notifications/Introductions.php:206 msgid "Ignore" msgstr "" @@ -1922,7 +1932,7 @@ msgid "Raw content" msgstr "" #: src/Content/Item.php:458 src/Content/Widget.php:65 -#: src/Model/Contact.php:1293 src/Model/Contact.php:1305 +#: src/Model/Contact.php:1296 src/Model/Contact.php:1308 #: src/Module/Contact/Follow.php:152 view/theme/vier/theme.php:182 msgid "Connect/Follow" msgstr "" @@ -2029,7 +2039,7 @@ msgstr "" #: src/Content/Nav.php:231 src/Content/Nav.php:291 #: src/Module/BaseProfile.php:70 src/Module/BaseProfile.php:73 #: src/Module/BaseProfile.php:81 src/Module/BaseProfile.php:84 -#: src/Module/Settings/Display.php:401 view/theme/frio/theme.php:224 +#: src/Module/Settings/Display.php:430 view/theme/frio/theme.php:224 #: view/theme/frio/theme.php:228 msgid "Calendar" msgstr "" @@ -2157,7 +2167,7 @@ msgid "Friend Requests" msgstr "" #: src/Content/Nav.php:311 src/Module/BaseNotifications.php:134 -#: src/Module/Notifications/Introductions.php:61 +#: src/Module/Notifications/Introductions.php:63 msgid "Notifications" msgstr "" @@ -2265,8 +2275,8 @@ msgstr "" msgid "%2$s %3$s" msgstr "" -#: src/Content/Text/BBCode.php:945 src/Model/Item.php:3677 -#: src/Model/Item.php:3683 src/Model/Item.php:3684 +#: src/Content/Text/BBCode.php:945 src/Model/Item.php:3724 +#: src/Model/Item.php:3730 src/Model/Item.php:3731 msgid "Link to source" msgstr "" @@ -2420,7 +2430,7 @@ msgstr "" msgid "Organisations" msgstr "" -#: src/Content/Widget.php:557 src/Model/Contact.php:1811 +#: src/Content/Widget.php:557 src/Model/Contact.php:1814 msgid "News" msgstr "" @@ -2482,12 +2492,12 @@ msgstr "" msgid "Show Less" msgstr "" -#: src/Content/Widget/VCard.php:94 src/Model/Contact.php:1262 +#: src/Content/Widget/VCard.php:94 src/Model/Contact.php:1265 #: src/Model/Profile.php:437 msgid "Post to group" msgstr "" -#: src/Content/Widget/VCard.php:99 src/Model/Contact.php:1266 +#: src/Content/Widget/VCard.php:99 src/Model/Contact.php:1269 #: src/Model/Profile.php:441 src/Module/Moderation/Item/Source.php:81 msgid "Mention" msgstr "" @@ -2505,13 +2515,13 @@ msgstr "" #: src/Content/Widget/VCard.php:111 src/Model/Event.php:68 #: src/Model/Event.php:95 src/Model/Event.php:462 src/Model/Event.php:953 #: src/Model/Profile.php:351 src/Module/Contact/Profile.php:458 -#: src/Module/Directory.php:133 src/Module/Notifications/Introductions.php:181 +#: src/Module/Directory.php:133 src/Module/Notifications/Introductions.php:187 #: src/Module/Profile/Profile.php:235 msgid "Location:" msgstr "" #: src/Content/Widget/VCard.php:114 src/Model/Profile.php:467 -#: src/Module/Notifications/Introductions.php:195 +#: src/Module/Notifications/Introductions.php:201 msgid "Network:" msgstr "" @@ -2520,13 +2530,13 @@ msgstr "" msgid "Follow" msgstr "" -#: src/Content/Widget/VCard.php:118 src/Model/Contact.php:1294 -#: src/Model/Contact.php:1306 src/Model/Profile.php:456 +#: src/Content/Widget/VCard.php:118 src/Model/Contact.php:1297 +#: src/Model/Contact.php:1309 src/Model/Profile.php:456 #: src/Module/Contact/Profile.php:521 msgid "Unfollow" msgstr "" -#: src/Content/Widget/VCard.php:124 src/Model/Contact.php:1264 +#: src/Content/Widget/VCard.php:124 src/Model/Contact.php:1267 #: src/Model/Profile.php:439 msgid "View group" msgstr "" @@ -2876,37 +2886,37 @@ msgid "%s (%s)" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:421 -#: src/Module/Settings/Display.php:368 +#: src/Module/Settings/Display.php:397 msgid "Monday" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:422 -#: src/Module/Settings/Display.php:369 +#: src/Module/Settings/Display.php:398 msgid "Tuesday" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:423 -#: src/Module/Settings/Display.php:370 +#: src/Module/Settings/Display.php:399 msgid "Wednesday" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:424 -#: src/Module/Settings/Display.php:371 +#: src/Module/Settings/Display.php:400 msgid "Thursday" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:425 -#: src/Module/Settings/Display.php:372 +#: src/Module/Settings/Display.php:401 msgid "Friday" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:426 -#: src/Module/Settings/Display.php:373 +#: src/Module/Settings/Display.php:402 msgid "Saturday" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:420 -#: src/Module/Settings/Display.php:367 +#: src/Module/Settings/Display.php:396 msgid "Sunday" msgstr "" @@ -3226,83 +3236,83 @@ msgstr "" msgid "Edit circles" msgstr "" -#: src/Model/Contact.php:1313 src/Module/Moderation/Users/Pending.php:88 -#: src/Module/Notifications/Introductions.php:124 +#: src/Model/Contact.php:1316 src/Module/Moderation/Users/Pending.php:88 +#: src/Module/Notifications/Introductions.php:128 msgid "Approve" msgstr "" -#: src/Model/Contact.php:1655 src/Model/Contact.php:1727 +#: src/Model/Contact.php:1658 src/Model/Contact.php:1730 #: src/Module/Contact/Profile.php:399 #, php-format msgid "%s has blocked you" msgstr "" -#: src/Model/Contact.php:1807 +#: src/Model/Contact.php:1810 msgid "Organisation" msgstr "" -#: src/Model/Contact.php:1815 +#: src/Model/Contact.php:1818 msgid "Group" msgstr "" -#: src/Model/Contact.php:1819 src/Module/Moderation/BaseUsers.php:150 +#: src/Model/Contact.php:1822 src/Module/Moderation/BaseUsers.php:150 msgid "Relay" msgstr "" -#: src/Model/Contact.php:3149 +#: src/Model/Contact.php:3152 msgid "Disallowed profile URL." msgstr "" -#: src/Model/Contact.php:3154 src/Module/Friendica.php:106 +#: src/Model/Contact.php:3157 src/Module/Friendica.php:106 msgid "Blocked domain" msgstr "" -#: src/Model/Contact.php:3159 +#: src/Model/Contact.php:3162 msgid "Connect URL missing." msgstr "" -#: src/Model/Contact.php:3172 +#: src/Model/Contact.php:3175 msgid "The contact could not be added. Please check the relevant network credentials in your Settings -> Social Networks page." msgstr "" -#: src/Model/Contact.php:3190 +#: src/Model/Contact.php:3193 #, php-format msgid "Expected network %s does not match actual network %s" msgstr "" -#: src/Model/Contact.php:3207 +#: src/Model/Contact.php:3210 msgid "This seems to be a relay account. They can't be followed by users." msgstr "" -#: src/Model/Contact.php:3214 +#: src/Model/Contact.php:3217 msgid "The profile address specified does not provide adequate information." msgstr "" -#: src/Model/Contact.php:3216 +#: src/Model/Contact.php:3219 msgid "No compatible communication protocols or feeds were discovered." msgstr "" -#: src/Model/Contact.php:3219 +#: src/Model/Contact.php:3222 msgid "An author or name was not found." msgstr "" -#: src/Model/Contact.php:3222 +#: src/Model/Contact.php:3225 msgid "No browser URL could be matched to this address." msgstr "" -#: src/Model/Contact.php:3225 +#: src/Model/Contact.php:3228 msgid "Unable to match @-style Identity Address with a known protocol or email contact." msgstr "" -#: src/Model/Contact.php:3226 +#: src/Model/Contact.php:3229 msgid "Use mailto: in front of address to force email check." msgstr "" -#: src/Model/Contact.php:3232 +#: src/Model/Contact.php:3235 msgid "Limited profile. This person will be unable to receive direct/personal notifications from you." msgstr "" -#: src/Model/Contact.php:3291 +#: src/Model/Contact.php:3294 msgid "Unable to retrieve contact information." msgstr "" @@ -3334,17 +3344,17 @@ msgid "today" msgstr "" #: src/Model/Event.php:454 src/Module/Calendar/Show.php:118 -#: src/Module/Settings/Display.php:378 src/Util/Temporal.php:343 +#: src/Module/Settings/Display.php:407 src/Util/Temporal.php:343 msgid "month" msgstr "" #: src/Model/Event.php:455 src/Module/Calendar/Show.php:119 -#: src/Module/Settings/Display.php:379 src/Util/Temporal.php:344 +#: src/Module/Settings/Display.php:408 src/Util/Temporal.php:344 msgid "week" msgstr "" #: src/Model/Event.php:456 src/Module/Calendar/Show.php:120 -#: src/Module/Settings/Display.php:380 src/Util/Temporal.php:345 +#: src/Module/Settings/Display.php:409 src/Util/Temporal.php:345 msgid "day" msgstr "" @@ -3411,84 +3421,84 @@ msgstr "" msgid "Happy Birthday %s" msgstr "" -#: src/Model/Item.php:2791 +#: src/Model/Item.php:2838 msgid "activity" msgstr "" -#: src/Model/Item.php:2793 +#: src/Model/Item.php:2840 msgid "comment" msgstr "" -#: src/Model/Item.php:2796 src/Module/Post/Tag/Add.php:112 +#: src/Model/Item.php:2843 src/Module/Post/Tag/Add.php:112 msgid "post" msgstr "" -#: src/Model/Item.php:2985 +#: src/Model/Item.php:3032 #, php-format msgid "%s is blocked" msgstr "" -#: src/Model/Item.php:2987 +#: src/Model/Item.php:3034 #, php-format msgid "%s is ignored" msgstr "" -#: src/Model/Item.php:2989 +#: src/Model/Item.php:3036 #, php-format msgid "Content from %s is collapsed" msgstr "" -#: src/Model/Item.php:2993 +#: src/Model/Item.php:3040 msgid "Sensitive content" msgstr "" -#: src/Model/Item.php:3547 +#: src/Model/Item.php:3594 msgid "bytes" msgstr "" -#: src/Model/Item.php:3581 +#: src/Model/Item.php:3628 #, php-format msgid "The media in this post is not displayed to visitors. To view it, please go to the original post." msgstr "" -#: src/Model/Item.php:3583 +#: src/Model/Item.php:3630 msgid "The media in this post is not displayed to visitors. To view it, please log in." msgstr "" -#: src/Model/Item.php:3608 +#: src/Model/Item.php:3655 #, php-format msgid "%2$s (%3$d%%, %1$d vote)" msgid_plural "%2$s (%3$d%%, %1$d votes)" msgstr[0] "" msgstr[1] "" -#: src/Model/Item.php:3610 +#: src/Model/Item.php:3657 #, php-format msgid "%2$s (%1$d vote)" msgid_plural "%2$s (%1$d votes)" msgstr[0] "" msgstr[1] "" -#: src/Model/Item.php:3615 +#: src/Model/Item.php:3662 #, php-format msgid "%d voter. Poll end: %s" msgid_plural "%d voters. Poll end: %s" msgstr[0] "" msgstr[1] "" -#: src/Model/Item.php:3617 +#: src/Model/Item.php:3664 #, php-format msgid "%d voter." msgid_plural "%d voters." msgstr[0] "" msgstr[1] "" -#: src/Model/Item.php:3619 +#: src/Model/Item.php:3666 #, php-format msgid "Poll end: %s" msgstr "" -#: src/Model/Item.php:3660 src/Model/Item.php:3661 +#: src/Model/Item.php:3707 src/Model/Item.php:3708 msgid "View on separate page" msgstr "" @@ -3510,7 +3520,7 @@ msgid "Homepage:" msgstr "" #: src/Model/Profile.php:355 src/Module/Contact/Profile.php:464 -#: src/Module/Notifications/Introductions.php:183 +#: src/Module/Notifications/Introductions.php:189 msgid "About:" msgstr "" @@ -3737,7 +3747,7 @@ msgid "The nickname was blocked from registration by the nodes admin." msgstr "" #: src/Model/User.php:1290 src/Model/User.php:1296 -#: src/Module/User/Import.php:230 +#: src/Module/User/Import.php:231 msgid "Cannot use that email." msgstr "" @@ -3950,8 +3960,8 @@ msgstr "" #: src/Module/Settings/Account.php:507 src/Module/Settings/Addons.php:64 #: src/Module/Settings/Connectors.php:143 #: src/Module/Settings/Connectors.php:228 -#: src/Module/Settings/ContactImport.php:110 -#: src/Module/Settings/Delegation.php:179 src/Module/Settings/Display.php:393 +#: src/Module/Settings/ContactImport.php:111 +#: src/Module/Settings/Delegation.php:179 src/Module/Settings/Display.php:422 #: src/Module/Settings/Features.php:90 #: src/Module/Settings/Profile/Index.php:272 msgid "Save Settings" @@ -4025,14 +4035,14 @@ msgid "Attempt to execute this update step automatically" msgstr "" #: src/Module/Admin/Features.php:53 -#: src/Module/Notifications/Introductions.php:136 +#: src/Module/Notifications/Introductions.php:140 #: src/Module/OAuth/Acknowledge.php:41 src/Module/Register.php:128 #: src/Module/Settings/TwoFactor/Trusted.php:115 msgid "No" msgstr "" #: src/Module/Admin/Features.php:53 src/Module/Contact/Revoke.php:91 -#: src/Module/Notifications/Introductions.php:136 +#: src/Module/Notifications/Introductions.php:140 #: src/Module/OAuth/Acknowledge.php:40 src/Module/Register.php:127 #: src/Module/Settings/TwoFactor/Trusted.php:115 msgid "Yes" @@ -4191,7 +4201,7 @@ msgid "Search in logs" msgstr "" #: src/Module/Admin/Logs/View.php:76 -#: src/Module/Notifications/Notifications.php:132 +#: src/Module/Notifications/Notifications.php:134 msgid "Show all" msgstr "" @@ -4303,11 +4313,11 @@ msgstr "" msgid "%s is no valid input for maximum image size" msgstr "" -#: src/Module/Admin/Site.php:364 src/Module/Settings/Display.php:224 +#: src/Module/Admin/Site.php:364 src/Module/Settings/Display.php:232 msgid "No special theme for mobile devices" msgstr "" -#: src/Module/Admin/Site.php:381 src/Module/Settings/Display.php:234 +#: src/Module/Admin/Site.php:381 src/Module/Settings/Display.php:242 #, php-format msgid "%s - (Experimental)" msgstr "" @@ -5234,7 +5244,7 @@ msgid "Can be \"all\" or \"tags\". \"all\" means that every public post should b msgstr "" #: src/Module/Admin/Site.php:596 src/Module/Contact/Profile.php:354 -#: src/Module/Settings/Display.php:269 +#: src/Module/Settings/Display.php:277 #: src/Module/Settings/TwoFactor/Index.php:132 msgid "Disabled" msgstr "" @@ -5513,7 +5523,7 @@ msgid "Screenshot" msgstr "" #: src/Module/Admin/Themes/Details.php:83 src/Module/Admin/Themes/Index.php:104 -#: src/Module/BaseAdmin.php:78 src/Module/Settings/Display.php:396 +#: src/Module/BaseAdmin.php:78 src/Module/Settings/Display.php:425 msgid "Themes" msgstr "" @@ -5592,24 +5602,24 @@ msgstr "" msgid "Only starting posts can be bookmarked" msgstr "" -#: src/Module/Api/Mastodon/Statuses/Mute.php:37 +#: src/Module/Api/Mastodon/Statuses/Mute.php:36 msgid "Only starting posts can be muted" msgstr "" -#: src/Module/Api/Mastodon/Statuses/Reblog.php:44 +#: src/Module/Api/Mastodon/Statuses/Reblog.php:43 #, php-format msgid "Posts from %s can't be shared" msgstr "" -#: src/Module/Api/Mastodon/Statuses/Unbookmark.php:37 +#: src/Module/Api/Mastodon/Statuses/Unbookmark.php:36 msgid "Only starting posts can be unbookmarked" msgstr "" -#: src/Module/Api/Mastodon/Statuses/Unmute.php:37 +#: src/Module/Api/Mastodon/Statuses/Unmute.php:36 msgid "Only starting posts can be unmuted" msgstr "" -#: src/Module/Api/Mastodon/Statuses/Unreblog.php:50 +#: src/Module/Api/Mastodon/Statuses/Unreblog.php:49 #, php-format msgid "Posts from %s can't be unshared" msgstr "" @@ -5703,26 +5713,26 @@ msgstr "" msgid "User registrations waiting for confirmation" msgstr "" -#: src/Module/BaseApi.php:442 src/Module/BaseApi.php:458 -#: src/Module/BaseApi.php:474 +#: src/Module/BaseApi.php:431 src/Module/BaseApi.php:447 +#: src/Module/BaseApi.php:463 msgid "Too Many Requests" msgstr "" -#: src/Module/BaseApi.php:443 +#: src/Module/BaseApi.php:432 #, php-format msgid "Daily posting limit of %d post reached. The post was rejected." msgid_plural "Daily posting limit of %d posts reached. The post was rejected." msgstr[0] "" msgstr[1] "" -#: src/Module/BaseApi.php:459 +#: src/Module/BaseApi.php:448 #, php-format msgid "Weekly posting limit of %d post reached. The post was rejected." msgid_plural "Weekly posting limit of %d posts reached. The post was rejected." msgstr[0] "" msgstr[1] "" -#: src/Module/BaseApi.php:475 +#: src/Module/BaseApi.php:464 #, php-format msgid "Monthly posting limit of %d post reached. The post was rejected." msgid_plural "Monthly posting limit of %d posts reached. The post was rejected." @@ -5852,7 +5862,7 @@ msgstr "" #: src/Module/BaseSettings.php:155 #: src/Module/Moderation/Blocklist/Contact/Import.php:108 -#: src/Module/Settings/ContactImport.php:109 +#: src/Module/Settings/ContactImport.php:110 msgid "Import Contacts" msgstr "" @@ -5920,7 +5930,7 @@ msgstr "" #: src/Module/Moderation/Blocklist/Server/Index.php:105 #: src/Module/Moderation/Item/Delete.php:53 src/Module/Register.php:153 #: src/Module/Security/TwoFactor/Verify.php:87 -#: src/Module/Settings/Channels.php:176 src/Module/Settings/Channels.php:202 +#: src/Module/Settings/Channels.php:184 src/Module/Settings/Channels.php:210 #: src/Module/Settings/TwoFactor/Index.php:147 #: src/Module/Settings/TwoFactor/Verify.php:144 msgid "Required" @@ -6001,7 +6011,7 @@ msgstr "" msgid "New Event" msgstr "" -#: src/Module/Calendar/Show.php:121 src/Module/Settings/Display.php:381 +#: src/Module/Calendar/Show.php:121 src/Module/Settings/Display.php:410 msgid "list" msgstr "" @@ -6384,13 +6394,13 @@ msgstr "" #: src/Module/Contact/Unfollow.php:115 #: src/Module/Moderation/Blocklist/Contact.php:122 #: src/Module/Moderation/Reports.php:117 -#: src/Module/Notifications/Introductions.php:121 -#: src/Module/Notifications/Introductions.php:192 +#: src/Module/Notifications/Introductions.php:125 +#: src/Module/Notifications/Introductions.php:198 msgid "Profile URL" msgstr "" #: src/Module/Contact/Follow.php:156 src/Module/Contact/Profile.php:466 -#: src/Module/Notifications/Introductions.php:185 +#: src/Module/Notifications/Introductions.php:191 #: src/Module/Profile/Profile.php:248 msgid "Tags:" msgstr "" @@ -6602,7 +6612,7 @@ msgid "Manage remote servers" msgstr "" #: src/Module/Contact/Profile.php:446 -#: src/Module/Notifications/Introductions.php:186 +#: src/Module/Notifications/Introductions.php:192 msgid "Hide this contact from others" msgstr "" @@ -6798,11 +6808,11 @@ msgstr "" msgid "Network feed not available." msgstr "" -#: src/Module/Conversation/Timeline.php:194 +#: src/Module/Conversation/Timeline.php:192 msgid "Include" msgstr "" -#: src/Module/Conversation/Timeline.php:195 +#: src/Module/Conversation/Timeline.php:193 msgid "Hide" msgstr "" @@ -6979,7 +6989,7 @@ msgstr "" #: src/Module/Friendica.php:107 #: src/Module/Moderation/Blocklist/Server/Index.php:76 #: src/Module/Moderation/Blocklist/Server/Index.php:100 -#: src/Module/Settings/Channels.php:223 +#: src/Module/Settings/Channels.php:231 msgid "Reason for the block" msgstr "" @@ -7751,7 +7761,7 @@ msgstr "" #: src/Module/Moderation/Blocklist/Server/Index.php:75 #: src/Module/Moderation/Blocklist/Server/Index.php:99 -#: src/Module/Settings/Channels.php:222 +#: src/Module/Settings/Channels.php:230 msgid "Blocked server domain pattern" msgstr "" @@ -8286,64 +8296,64 @@ msgstr "" msgid "Deny" msgstr "" -#: src/Module/Notifications/Introductions.php:91 +#: src/Module/Notifications/Introductions.php:93 msgid "Show Ignored Requests" msgstr "" -#: src/Module/Notifications/Introductions.php:91 +#: src/Module/Notifications/Introductions.php:93 msgid "Hide Ignored Requests" msgstr "" -#: src/Module/Notifications/Introductions.php:107 -#: src/Module/Notifications/Introductions.php:172 +#: src/Module/Notifications/Introductions.php:111 +#: src/Module/Notifications/Introductions.php:178 msgid "Notification type:" msgstr "" -#: src/Module/Notifications/Introductions.php:110 +#: src/Module/Notifications/Introductions.php:114 msgid "Suggested by:" msgstr "" -#: src/Module/Notifications/Introductions.php:127 -#: src/Module/Notifications/Introductions.php:164 +#: src/Module/Notifications/Introductions.php:131 +#: src/Module/Notifications/Introductions.php:168 #: src/Module/Post/Tag/Remove.php:95 #: src/Module/Settings/TwoFactor/Trusted.php:133 msgid "Remove" msgstr "" -#: src/Module/Notifications/Introductions.php:135 +#: src/Module/Notifications/Introductions.php:139 msgid "Claims to be known to you: " msgstr "" -#: src/Module/Notifications/Introductions.php:144 +#: src/Module/Notifications/Introductions.php:148 #, php-format msgid "Accept %s as a friend or follower?" msgstr "" -#: src/Module/Notifications/Introductions.php:145 +#: src/Module/Notifications/Introductions.php:149 msgid "Allows them to follow your posts." msgstr "" -#: src/Module/Notifications/Introductions.php:146 +#: src/Module/Notifications/Introductions.php:150 msgid "You will also follow them and receive their posts." msgstr "" -#: src/Module/Notifications/Introductions.php:147 +#: src/Module/Notifications/Introductions.php:151 msgid "You won't follow them and won't receive their posts." msgstr "" -#: src/Module/Notifications/Introductions.php:149 +#: src/Module/Notifications/Introductions.php:153 msgid "Friend (Follow them back)" msgstr "" -#: src/Module/Notifications/Introductions.php:150 +#: src/Module/Notifications/Introductions.php:154 msgid "Follower" msgstr "" -#: src/Module/Notifications/Introductions.php:198 +#: src/Module/Notifications/Introductions.php:204 msgid "Accept request" msgstr "" -#: src/Module/Notifications/Introductions.php:210 +#: src/Module/Notifications/Introductions.php:216 #: src/Module/Notifications/Notifications.php:127 #, php-format msgid "No more %s notifications." @@ -8369,7 +8379,7 @@ msgstr "" msgid "Home Notifications" msgstr "" -#: src/Module/Notifications/Notifications.php:132 +#: src/Module/Notifications/Notifications.php:134 msgid "Show unread" msgstr "" @@ -8576,19 +8586,19 @@ msgid "No contacts." msgstr "" #: src/Module/Profile/Conversations.php:96 src/Module/Profile/Profile.php:366 -#: src/Protocol/Feed.php:1104 +#: src/Protocol/Feed.php:1105 #, php-format msgid "%s's posts" msgstr "" #: src/Module/Profile/Conversations.php:97 src/Module/Profile/Profile.php:367 -#: src/Protocol/Feed.php:1107 +#: src/Protocol/Feed.php:1108 #, php-format msgid "%s's comments" msgstr "" #: src/Module/Profile/Conversations.php:98 src/Module/Profile/Profile.php:368 -#: src/Protocol/Feed.php:1100 +#: src/Protocol/Feed.php:1101 #, php-format msgid "%s's timeline" msgstr "" @@ -8754,7 +8764,7 @@ msgstr "" msgid "Only parent users can create additional accounts." msgstr "" -#: src/Module/Register.php:96 src/Module/User/Import.php:99 +#: src/Module/Register.php:96 src/Module/User/Import.php:100 msgid "This site has exceeded the number of allowed daily account registrations. Please try again tomorrow." msgstr "" @@ -8825,7 +8835,7 @@ msgstr "" msgid "Choose a nickname: " msgstr "" -#: src/Module/Register.php:178 src/Module/User/Import.php:105 +#: src/Module/Register.php:178 src/Module/User/Import.php:106 msgid "Import" msgstr "" @@ -9549,151 +9559,151 @@ msgstr "" msgid "None of the addons installed on this server have any settings." msgstr "" -#: src/Module/Settings/Channels.php:134 +#: src/Module/Settings/Channels.php:142 msgid "This page can be used to define the channels that will automatically be reshared by your account." msgstr "" -#: src/Module/Settings/Channels.php:139 +#: src/Module/Settings/Channels.php:147 msgid "This page can be used to define your own channels." msgstr "" -#: src/Module/Settings/Channels.php:168 +#: src/Module/Settings/Channels.php:176 msgid "Publish" msgstr "" -#: src/Module/Settings/Channels.php:168 +#: src/Module/Settings/Channels.php:176 msgid "When selected, the channel results are reshared. This only works for public ActivityPub posts from the public timeline or the user defined circles." msgstr "" -#: src/Module/Settings/Channels.php:176 src/Module/Settings/Channels.php:202 -#: src/Module/Settings/Display.php:437 +#: src/Module/Settings/Channels.php:184 src/Module/Settings/Channels.php:210 +#: src/Module/Settings/Display.php:466 msgid "Label" msgstr "" -#: src/Module/Settings/Channels.php:177 src/Module/Settings/Channels.php:203 -#: src/Module/Settings/Display.php:438 +#: src/Module/Settings/Channels.php:185 src/Module/Settings/Channels.php:211 +#: src/Module/Settings/Display.php:467 #: src/Module/Settings/TwoFactor/AppSpecific.php:123 msgid "Description" msgstr "" -#: src/Module/Settings/Channels.php:178 src/Module/Settings/Channels.php:204 +#: src/Module/Settings/Channels.php:186 src/Module/Settings/Channels.php:212 msgid "Access Key" msgstr "" -#: src/Module/Settings/Channels.php:179 src/Module/Settings/Channels.php:205 +#: src/Module/Settings/Channels.php:187 src/Module/Settings/Channels.php:213 msgid "Circle/Channel" msgstr "" -#: src/Module/Settings/Channels.php:180 src/Module/Settings/Channels.php:206 +#: src/Module/Settings/Channels.php:188 src/Module/Settings/Channels.php:214 msgid "Include Tags" msgstr "" -#: src/Module/Settings/Channels.php:181 src/Module/Settings/Channels.php:207 +#: src/Module/Settings/Channels.php:189 src/Module/Settings/Channels.php:215 msgid "Exclude Tags" msgstr "" -#: src/Module/Settings/Channels.php:182 src/Module/Settings/Channels.php:208 +#: src/Module/Settings/Channels.php:190 src/Module/Settings/Channels.php:216 msgid "Minimum Size" msgstr "" -#: src/Module/Settings/Channels.php:183 src/Module/Settings/Channels.php:209 +#: src/Module/Settings/Channels.php:191 src/Module/Settings/Channels.php:217 msgid "Maximum Size" msgstr "" -#: src/Module/Settings/Channels.php:184 src/Module/Settings/Channels.php:210 +#: src/Module/Settings/Channels.php:192 src/Module/Settings/Channels.php:218 msgid "Full Text Search" msgstr "" -#: src/Module/Settings/Channels.php:188 src/Module/Settings/Channels.php:214 +#: src/Module/Settings/Channels.php:196 src/Module/Settings/Channels.php:222 msgid "Languages" msgstr "" -#: src/Module/Settings/Channels.php:188 +#: src/Module/Settings/Channels.php:196 msgid "Select all languages that you want to see in this channel. \"Unspecified\" describes all posts for which no language information was detected (e.g. posts with just an image or too little text to be sure of the language). If you want to see all languages, you will need to select all items in the list." msgstr "" -#: src/Module/Settings/Channels.php:190 +#: src/Module/Settings/Channels.php:198 msgid "Delete channel" msgstr "" -#: src/Module/Settings/Channels.php:190 +#: src/Module/Settings/Channels.php:198 msgid "Check to delete this entry from the channel list" msgstr "" -#: src/Module/Settings/Channels.php:196 +#: src/Module/Settings/Channels.php:204 msgid "Comma separated list of tags. If a post contain any of these tags, then it will not be part of this channel." msgstr "" -#: src/Module/Settings/Channels.php:198 +#: src/Module/Settings/Channels.php:206 msgid "Comma separated list of tags. If a post contain any of these tags, then it will not be part of nthis channel." msgstr "" -#: src/Module/Settings/Channels.php:202 +#: src/Module/Settings/Channels.php:210 msgid "Short name for the channel. It is displayed on the channels widget." msgstr "" -#: src/Module/Settings/Channels.php:203 +#: src/Module/Settings/Channels.php:211 msgid "This should describe the content of the channel in a few word." msgstr "" -#: src/Module/Settings/Channels.php:204 +#: src/Module/Settings/Channels.php:212 msgid "When you want to access this channel via an access key, you can define it here. Pay attention to not use an already used one." msgstr "" -#: src/Module/Settings/Channels.php:205 +#: src/Module/Settings/Channels.php:213 msgid "Select a circle or channel, that your channel should be based on." msgstr "" -#: src/Module/Settings/Channels.php:206 +#: src/Module/Settings/Channels.php:214 msgid "Comma separated list of tags. A post will be used when it contains any of the listed tags." msgstr "" -#: src/Module/Settings/Channels.php:208 +#: src/Module/Settings/Channels.php:216 msgid "Minimum post size. Leave empty for no minimum size. The size is calculated without links, attached posts, mentions or hashtags." msgstr "" -#: src/Module/Settings/Channels.php:209 +#: src/Module/Settings/Channels.php:217 msgid "Maximum post size. Leave empty for no maximum size. The size is calculated without links, attached posts, mentions or hashtags." msgstr "" -#: src/Module/Settings/Channels.php:210 +#: src/Module/Settings/Channels.php:218 #, php-format msgid "Search terms for the body, supports the \"boolean mode\" operators from MariaDB. See the help for a complete list of operators and additional keywords: %s" msgstr "" -#: src/Module/Settings/Channels.php:211 +#: src/Module/Settings/Channels.php:219 msgid "Check to display images in the channel." msgstr "" -#: src/Module/Settings/Channels.php:212 +#: src/Module/Settings/Channels.php:220 msgid "Check to display videos in the channel." msgstr "" -#: src/Module/Settings/Channels.php:213 +#: src/Module/Settings/Channels.php:221 msgid "Check to display audio in the channel." msgstr "" -#: src/Module/Settings/Channels.php:214 +#: src/Module/Settings/Channels.php:222 msgid "Select all languages that you want to see in this channel." msgstr "" -#: src/Module/Settings/Channels.php:218 +#: src/Module/Settings/Channels.php:226 msgid "Add new entry to the channel list" msgstr "" -#: src/Module/Settings/Channels.php:219 +#: src/Module/Settings/Channels.php:227 msgid "Add" msgstr "" -#: src/Module/Settings/Channels.php:221 +#: src/Module/Settings/Channels.php:229 msgid "Current Entries in the channel list" msgstr "" -#: src/Module/Settings/Channels.php:224 +#: src/Module/Settings/Channels.php:232 msgid "Delete entry from the channel list" msgstr "" -#: src/Module/Settings/Channels.php:225 +#: src/Module/Settings/Channels.php:233 msgid "Delete entry from the channel list?" msgstr "" @@ -9869,27 +9879,27 @@ msgstr "" msgid "Move to folder:" msgstr "" -#: src/Module/Settings/ContactImport.php:63 +#: src/Module/Settings/ContactImport.php:64 msgid "Contact CSV file upload error" msgstr "" -#: src/Module/Settings/ContactImport.php:82 +#: src/Module/Settings/ContactImport.php:83 msgid "Importing Contacts done" msgstr "" -#: src/Module/Settings/ContactImport.php:112 +#: src/Module/Settings/ContactImport.php:113 msgid "Upload a CSV file that contains the handle of your followed accounts in the first column you exported from the old account." msgstr "" -#: src/Module/Settings/ContactImport.php:113 +#: src/Module/Settings/ContactImport.php:114 msgid "Upload File" msgstr "" -#: src/Module/Settings/ContactImport.php:115 +#: src/Module/Settings/ContactImport.php:116 msgid "Your legacy ActivityPub/GNU Social account" msgstr "" -#: src/Module/Settings/ContactImport.php:115 +#: src/Module/Settings/ContactImport.php:116 msgid "If you enter your old account name from an ActivityPub based system or your GNU Social/Statusnet account name here (in the format user@domain.tld), your contacts will be added automatically. The field will be emptied when done." msgstr "" @@ -9958,252 +9968,269 @@ msgstr "" msgid "No entries." msgstr "" -#: src/Module/Settings/Display.php:192 +#: src/Module/Settings/Display.php:200 msgid "The theme you chose isn't available." msgstr "" -#: src/Module/Settings/Display.php:232 +#: src/Module/Settings/Display.php:240 #, php-format msgid "%s - (Unsupported)" msgstr "" -#: src/Module/Settings/Display.php:270 +#: src/Module/Settings/Display.php:278 msgid "Color/Black" msgstr "" -#: src/Module/Settings/Display.php:271 view/theme/frio/php/scheme.php:95 +#: src/Module/Settings/Display.php:279 view/theme/frio/php/scheme.php:95 msgid "Black" msgstr "" -#: src/Module/Settings/Display.php:272 +#: src/Module/Settings/Display.php:280 msgid "Color/White" msgstr "" -#: src/Module/Settings/Display.php:273 +#: src/Module/Settings/Display.php:281 msgid "White" msgstr "" -#: src/Module/Settings/Display.php:278 +#: src/Module/Settings/Display.php:286 msgid "No preview" msgstr "" -#: src/Module/Settings/Display.php:279 +#: src/Module/Settings/Display.php:287 msgid "No image" msgstr "" -#: src/Module/Settings/Display.php:280 +#: src/Module/Settings/Display.php:288 msgid "Small Image" msgstr "" -#: src/Module/Settings/Display.php:281 +#: src/Module/Settings/Display.php:289 msgid "Large Image" msgstr "" -#: src/Module/Settings/Display.php:282 +#: src/Module/Settings/Display.php:290 msgid "Automatic image size" msgstr "" -#: src/Module/Settings/Display.php:392 +#: src/Module/Settings/Display.php:421 msgid "Display Settings" msgstr "" -#: src/Module/Settings/Display.php:394 +#: src/Module/Settings/Display.php:423 msgid "Content Settings" msgstr "" -#: src/Module/Settings/Display.php:395 view/theme/duepuntozero/config.php:74 +#: src/Module/Settings/Display.php:424 view/theme/duepuntozero/config.php:74 #: view/theme/frio/config.php:159 view/theme/quattro/config.php:76 #: view/theme/vier/config.php:124 msgid "Theme settings" msgstr "" -#: src/Module/Settings/Display.php:397 +#: src/Module/Settings/Display.php:426 #, php-format msgid "Settings for %s" msgstr "" -#: src/Module/Settings/Display.php:398 +#: src/Module/Settings/Display.php:427 msgid "Note: If you switch the theme, you need to save changes before you can see the settings for the new theme below." msgstr "" -#: src/Module/Settings/Display.php:399 +#: src/Module/Settings/Display.php:428 msgid "Timelines" msgstr "" -#: src/Module/Settings/Display.php:402 src/Module/Settings/Features.php:83 +#: src/Module/Settings/Display.php:431 src/Module/Settings/Features.php:83 msgid "Drag to reorder or tab to item with keyboard and move up/down with arrow keys" msgstr "" -#: src/Module/Settings/Display.php:405 src/Module/Settings/Display.php:409 +#: src/Module/Settings/Display.php:434 src/Module/Settings/Display.php:438 #: src/Module/Settings/Features.php:87 msgid "Reset order" msgstr "" -#: src/Module/Settings/Display.php:415 +#: src/Module/Settings/Display.php:444 msgid "Display theme" msgstr "" -#: src/Module/Settings/Display.php:416 +#: src/Module/Settings/Display.php:445 msgid "Mobile theme" msgstr "" -#: src/Module/Settings/Display.php:419 +#: src/Module/Settings/Display.php:448 msgid "Number of items to display per page:" msgstr "" -#: src/Module/Settings/Display.php:419 src/Module/Settings/Display.php:420 +#: src/Module/Settings/Display.php:448 src/Module/Settings/Display.php:449 msgid "Maximum of 100 items" msgstr "" -#: src/Module/Settings/Display.php:420 +#: src/Module/Settings/Display.php:449 msgid "Number of items to display per page when viewed from mobile device:" msgstr "" -#: src/Module/Settings/Display.php:421 +#: src/Module/Settings/Display.php:450 msgid "Regularly update the page content" msgstr "" -#: src/Module/Settings/Display.php:421 +#: src/Module/Settings/Display.php:450 msgid "When enabled, new content on network, community and channels are added on top." msgstr "" -#: src/Module/Settings/Display.php:422 +#: src/Module/Settings/Display.php:451 msgid "Display emoticons" msgstr "" -#: src/Module/Settings/Display.php:422 +#: src/Module/Settings/Display.php:451 msgid "When enabled, emoticons are replaced with matching symbols." msgstr "" -#: src/Module/Settings/Display.php:423 +#: src/Module/Settings/Display.php:452 msgid "Infinite scroll" msgstr "" -#: src/Module/Settings/Display.php:423 +#: src/Module/Settings/Display.php:452 msgid "Automatic fetch new items when reaching the page end." msgstr "" -#: src/Module/Settings/Display.php:424 +#: src/Module/Settings/Display.php:453 msgid "Enable Smart Threading" msgstr "" -#: src/Module/Settings/Display.php:424 +#: src/Module/Settings/Display.php:453 msgid "Enable the automatic suppression of extraneous thread indentation." msgstr "" -#: src/Module/Settings/Display.php:425 +#: src/Module/Settings/Display.php:454 msgid "Display the Dislike feature" msgstr "" -#: src/Module/Settings/Display.php:425 +#: src/Module/Settings/Display.php:454 msgid "Display the Dislike button and dislike reactions on posts and comments." msgstr "" -#: src/Module/Settings/Display.php:426 +#: src/Module/Settings/Display.php:455 msgid "Display the resharer" msgstr "" -#: src/Module/Settings/Display.php:426 +#: src/Module/Settings/Display.php:455 msgid "Display the first resharer as icon and text on a reshared item." msgstr "" -#: src/Module/Settings/Display.php:427 +#: src/Module/Settings/Display.php:456 msgid "Stay local" msgstr "" -#: src/Module/Settings/Display.php:427 +#: src/Module/Settings/Display.php:456 msgid "Don't go to a remote system when following a contact link." msgstr "" -#: src/Module/Settings/Display.php:428 +#: src/Module/Settings/Display.php:457 msgid "Show the post deletion checkbox" msgstr "" -#: src/Module/Settings/Display.php:428 +#: src/Module/Settings/Display.php:457 msgid "Display the checkbox for the post deletion on the network page." msgstr "" -#: src/Module/Settings/Display.php:429 +#: src/Module/Settings/Display.php:458 msgid "DIsplay the event list" msgstr "" -#: src/Module/Settings/Display.php:429 +#: src/Module/Settings/Display.php:458 msgid "Display the birthday reminder and event list on the network page." msgstr "" -#: src/Module/Settings/Display.php:430 +#: src/Module/Settings/Display.php:459 msgid "Link preview mode" msgstr "" -#: src/Module/Settings/Display.php:430 +#: src/Module/Settings/Display.php:459 msgid "Appearance of the link preview that is added to each post with a link." msgstr "" -#: src/Module/Settings/Display.php:431 +#: src/Module/Settings/Display.php:460 msgid "Hide pictures with empty alternative text" msgstr "" -#: src/Module/Settings/Display.php:431 +#: src/Module/Settings/Display.php:460 msgid "Don't display pictures that are missing the alternative text." msgstr "" -#: src/Module/Settings/Display.php:432 +#: src/Module/Settings/Display.php:461 msgid "Hide custom emojis" msgstr "" -#: src/Module/Settings/Display.php:432 +#: src/Module/Settings/Display.php:461 msgid "Don't display custom emojis." msgstr "" -#: src/Module/Settings/Display.php:433 +#: src/Module/Settings/Display.php:462 msgid "Platform icons style" msgstr "" -#: src/Module/Settings/Display.php:433 +#: src/Module/Settings/Display.php:462 msgid "Style of the platform icons" msgstr "" -#: src/Module/Settings/Display.php:434 +#: src/Module/Settings/Display.php:463 msgid "Embed remote media" msgstr "" -#: src/Module/Settings/Display.php:434 +#: src/Module/Settings/Display.php:463 msgid "When enabled, remote media will be embedded in the post, like for example YouTube videos." msgstr "" -#: src/Module/Settings/Display.php:435 +#: src/Module/Settings/Display.php:464 msgid "Embed supported media" msgstr "" -#: src/Module/Settings/Display.php:435 +#: src/Module/Settings/Display.php:464 msgid "When enabled, remote media will be embedded in the post instead of using the local player if this is supported by the remote system. This is useful for media where the remote player is better than the local one, like for example Peertube videos." msgstr "" -#: src/Module/Settings/Display.php:439 +#: src/Module/Settings/Display.php:468 msgid "Channels Widget" msgstr "" -#: src/Module/Settings/Display.php:440 +#: src/Module/Settings/Display.php:469 msgid "Top Menu" msgstr "" -#: src/Module/Settings/Display.php:442 +#: src/Module/Settings/Display.php:471 msgid "Enable timelines that you want to see in the channels widget. Bookmark timelines that you want to see in the top menu." msgstr "" -#: src/Module/Settings/Display.php:444 +#: src/Module/Settings/Display.php:473 msgid "Channel languages:" msgstr "" -#: src/Module/Settings/Display.php:444 +#: src/Module/Settings/Display.php:473 msgid "Select all the languages you want to see in your channels. \"Unspecified\" describes all posts for which no language information was detected (e.g. posts with just an image or too little text to be sure of the language). If you want to see all languages, you will need to select all items in the list." msgstr "" -#: src/Module/Settings/Display.php:446 +#: src/Module/Settings/Display.php:474 +msgid "Timeline channels:" +msgstr "" + +#: src/Module/Settings/Display.php:474 +msgid "Select all the channels that you want to see in your network timeline." +msgstr "" + +#: src/Module/Settings/Display.php:476 +msgid "Filter channels:" +msgstr "" + +#: src/Module/Settings/Display.php:476 +#, php-format +msgid "Select all the channels that you want to use as a filter for your network timeline. All posts from these channels will be hidden. For technical reasons postings that are older than %s will not be filtered." +msgstr "" + +#: src/Module/Settings/Display.php:479 msgid "Beginning of week:" msgstr "" -#: src/Module/Settings/Display.php:447 +#: src/Module/Settings/Display.php:480 msgid "Default calendar view:" msgstr "" @@ -10899,67 +10926,67 @@ msgstr "" msgid "Select an identity to manage: " msgstr "" -#: src/Module/User/Import.php:91 +#: src/Module/User/Import.php:92 msgid "User imports on closed servers can only be done by an administrator." msgstr "" -#: src/Module/User/Import.php:107 +#: src/Module/User/Import.php:108 msgid "Move account" msgstr "" -#: src/Module/User/Import.php:108 +#: src/Module/User/Import.php:109 msgid "You can import an account from another Friendica server." msgstr "" -#: src/Module/User/Import.php:109 +#: src/Module/User/Import.php:110 msgid "You need to export your account from the old server and upload it here. We will recreate your old account here with all your contacts. We will try also to inform your friends that you moved here." msgstr "" -#: src/Module/User/Import.php:110 +#: src/Module/User/Import.php:111 msgid "This feature is experimental. We can't import contacts from the OStatus network (GNU Social/Statusnet) or from Diaspora" msgstr "" -#: src/Module/User/Import.php:111 +#: src/Module/User/Import.php:112 msgid "Account file" msgstr "" -#: src/Module/User/Import.php:111 +#: src/Module/User/Import.php:112 msgid "To export your account, go to \"Settings->Export your personal data\" and select \"Export account\"" msgstr "" -#: src/Module/User/Import.php:206 +#: src/Module/User/Import.php:207 msgid "Account file size is too high" msgstr "" -#: src/Module/User/Import.php:212 +#: src/Module/User/Import.php:213 msgid "Error decoding account file" msgstr "" -#: src/Module/User/Import.php:217 +#: src/Module/User/Import.php:218 msgid "Error! No version data in file! This is not a Friendica account file?" msgstr "" -#: src/Module/User/Import.php:225 +#: src/Module/User/Import.php:226 #, php-format msgid "User '%s' already exists on this server!" msgstr "" -#: src/Module/User/Import.php:267 +#: src/Module/User/Import.php:268 msgid "User creation error" msgstr "" -#: src/Module/User/Import.php:316 +#: src/Module/User/Import.php:317 #, php-format msgid "%d contact not imported" msgid_plural "%d contacts not imported" msgstr[0] "" msgstr[1] "" -#: src/Module/User/Import.php:365 +#: src/Module/User/Import.php:366 msgid "User profile creation error" msgstr "" -#: src/Module/User/Import.php:416 +#: src/Module/User/Import.php:425 msgid "Done. You can now login with your username and password" msgstr "" diff --git a/view/templates/settings/display.tpl b/view/templates/settings/display.tpl index ce9fce88ab..4025041d67 100644 --- a/view/templates/settings/display.tpl +++ b/view/templates/settings/display.tpl @@ -59,6 +59,13 @@

    {{$channel_title}}

    {{include file="field_select.tpl" field=$channel_languages}} + {{if $has_timeline_channels}} + {{include file="field_select.tpl" field=$timeline_channels}} + {{/if}} + {{if $has_filter_channels}} + {{include file="field_select.tpl" field=$filter_channels}} + {{/if}} +

    {{$calendar_title}}

    {{include file="field_select.tpl" field=$first_day_of_week}} {{include file="field_select.tpl" field=$calendar_default_view}} diff --git a/view/theme/frio/templates/settings/display.tpl b/view/theme/frio/templates/settings/display.tpl index cd314e3739..ac963e9350 100644 --- a/view/theme/frio/templates/settings/display.tpl +++ b/view/theme/frio/templates/settings/display.tpl @@ -123,6 +123,16 @@
    {{include file="field_select.tpl" field=$channel_languages}}
    + {{if $has_timeline_channels}} +
    + {{include file="field_select.tpl" field=$timeline_channels}} +
    + {{/if}} + {{if $has_filter_channels}} +
    + {{include file="field_select.tpl" field=$filter_channels}} +
    + {{/if}} diff --git a/view/theme/frio/templates/sub/direction.tpl b/view/theme/frio/templates/sub/direction.tpl index c3944d1c6c..71e6273efe 100644 --- a/view/theme/frio/templates/sub/direction.tpl +++ b/view/theme/frio/templates/sub/direction.tpl @@ -27,6 +27,8 @@ {{elseif $direction.direction == 10}} + {{elseif $direction.direction == 11}} + {{/if}} {{/if}} \ No newline at end of file From a250969e11214e7eec2398de29a4aff1093f15e8 Mon Sep 17 00:00:00 2001 From: loma-one <44441246+loma-one@users.noreply.github.com> Date: Tue, 3 Feb 2026 20:37:03 +0100 Subject: [PATCH 027/197] Optimization of the editor toolbar and enhancement of the preview function This pull request implements structural improvements to the editor (compose) to enhance usability and visual clarity: Toolbar Reorganization: Buttons have been grouped into logical Bootstrap btn-group units. Media buttons (image, attachment) are now positioned on the left (pull-left), while formatting options and special features (Emoji, CW, Code) are arranged in two distinct groups on the right (pull-right). Enhanced Preview Logic: Added a toggle functionality to the preview button. When the preview is active, the button text changes to "Close Preview" (or local equivalent) to provide a more intuitive user experience. --- view/templates/item/compose.tpl | 385 ++++++++++++++++---------------- 1 file changed, 196 insertions(+), 189 deletions(-) diff --git a/view/templates/item/compose.tpl b/view/templates/item/compose.tpl index cf54b3258a..89bae5aa6e 100644 --- a/view/templates/item/compose.tpl +++ b/view/templates/item/compose.tpl @@ -1,226 +1,233 @@ {{* - * Copyright (C) 2010-2024, the Friendica project + * Copyright (C) 2010-2026, the Friendica project * SPDX-FileCopyrightText: 2010-2024 the Friendica project * * SPDX-License-Identifier: AGPL-3.0-or-later *}}
    -

    {{$l10n.compose_title}}

    - {{if $l10n.always_open_compose}} -

    {{$l10n.always_open_compose nofilter}}

    - {{/if}} -
    -
    - {{**}} - - - +

    {{$l10n.compose_title}}

    + {{if $l10n.always_open_compose}} +

    {{$l10n.always_open_compose nofilter}}

    + {{/if}} +
    + + {{**}} + + + -
    - -
    - {{if $l10n.placeholdercategory}} -
    - -
    - {{/if}} +
    + +
    + {{if $l10n.placeholdercategory}} +
    + +
    + {{/if}} -

    - - - - - - - - - - - - - - -

    -
    -

    - -

    -
    -

    - {{if $type == 'post'}} - - - - - - {{/if}} - - - - - - - - -

    +
    From cda1925affa7156b28bc2217436fa06cbe723980 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 3 Feb 2026 20:51:01 +0000 Subject: [PATCH 028/197] Fixes "Argument #3 ($author_id) must be of type int, null given --- src/Protocol/ActivityPub/Processor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 63d5ec1c28..57849e9cde 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -229,7 +229,7 @@ class Processor */ public static function updateItem(array $activity) { - $item = Post::selectFirst(['uri', 'uri-id', 'guid', 'thr-parent', 'gravity', 'post-type', 'private'], ['uri' => $activity['id']]); + $item = Post::selectFirst(['uri', 'uri-id', 'guid', 'thr-parent', 'gravity', 'post-type', 'private', 'author-id', 'owner-id', 'author-link', 'owner-link', 'parent-uri-id', 'thr-parent-id', 'replies'], ['uri' => $activity['id']]); if (!DBA::isResult($item)) { DI::logger()->notice('No existing item, item will be created', ['uri' => $activity['id']]); $item = self::createItem($activity, false); From acc195116dd8928e81fe9832296ed91c0ca164ce Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 3 Feb 2026 20:57:54 +0000 Subject: [PATCH 029/197] Fixes "DOMDocument::loadHTML(): Argument #1 ($source) must not be empty" --- src/Content/Post/Repository/PostMedia.php | 3 +++ src/Protocol/ATProtocol/Jetstream.php | 3 +++ src/Util/ParseUrl.php | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/src/Content/Post/Repository/PostMedia.php b/src/Content/Post/Repository/PostMedia.php index 080bc74927..1d0c5e3703 100644 --- a/src/Content/Post/Repository/PostMedia.php +++ b/src/Content/Post/Repository/PostMedia.php @@ -461,6 +461,9 @@ class PostMedia extends BaseRepository } else { $player = $this->getLinkAttachment($media); } + if ($player === '') { + continue; + } @$tmp->loadHTML(mb_convert_encoding($player, 'HTML-ENTITIES', "UTF-8"), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); $div = $tmp->documentElement; $imported = $doc->importNode($div, true); diff --git a/src/Protocol/ATProtocol/Jetstream.php b/src/Protocol/ATProtocol/Jetstream.php index d37b8b3720..487806dad1 100755 --- a/src/Protocol/ATProtocol/Jetstream.php +++ b/src/Protocol/ATProtocol/Jetstream.php @@ -155,6 +155,9 @@ class Jetstream $this->logger->error('Error while trying to receive a message', ['code' => $e->getCode(), 'message' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine()]); break; } + } catch (\Exception $e) { + $this->logger->error('General error while trying to receive a message', ['capped' => $this->capped, 'code' => $e->getCode(), 'message' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine()]); + break; } $last_timeout = time(); } diff --git a/src/Util/ParseUrl.php b/src/Util/ParseUrl.php index 58b622b0a8..84f907c89e 100644 --- a/src/Util/ParseUrl.php +++ b/src/Util/ParseUrl.php @@ -1751,6 +1751,10 @@ class ParseUrl return $siteinfo; } + if ($data['html'] == '') { + return $siteinfo; + } + $dom = new DOMDocument(); if (!@$dom->loadHTML($data['html'])) { return $siteinfo; From 3c36efd4c5ffd29d179449dab9299bf26ee4f8b3 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Wed, 4 Feb 2026 08:16:55 +0100 Subject: [PATCH 030/197] fix missing space in DE translation closes #15464 --- view/lang/de/messages.po | 804 ++++++++++++++++++++------------------- view/lang/de/strings.php | 4 +- 2 files changed, 423 insertions(+), 385 deletions(-) diff --git a/view/lang/de/messages.po b/view/lang/de/messages.po index e32c218a94..e4ccacabe7 100644 --- a/view/lang/de/messages.po +++ b/view/lang/de/messages.po @@ -58,7 +58,7 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-01-04 20:49+0100\n" +"POT-Creation-Date: 2026-01-06 15:55+0100\n" "PO-Revision-Date: 2011-05-05 10:19+0000\n" "Last-Translator: Tobias Diekershoff , 2016-2026\n" "Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" @@ -88,13 +88,13 @@ msgstr "Eintrag konnte nicht geholt werden." msgid "Empty post discarded." msgstr "Leerer Beitrag wurde verworfen." -#: mod/item.php:437 src/Module/Admin/Themes/Details.php:31 +#: mod/item.php:439 src/Module/Admin/Themes/Details.php:31 #: src/Module/Admin/Themes/Index.php:51 src/Module/Debug/ItemBody.php:34 #: src/Module/Debug/ItemBody.php:42 src/Module/Item/Feed.php:66 msgid "Item not found." msgstr "Beitrag nicht gefunden." -#: mod/item.php:461 mod/message.php:56 mod/message.php:102 mod/notes.php:34 +#: mod/item.php:463 mod/message.php:56 mod/message.php:102 mod/notes.php:34 #: mod/photos.php:132 mod/photos.php:624 src/Model/Event.php:511 #: src/Module/Attach.php:40 src/Module/BaseApi.php:90 #: src/Module/BaseNotifications.php:83 src/Module/BaseSettings.php:38 @@ -116,11 +116,11 @@ msgstr "Beitrag nicht gefunden." #: src/Module/Register.php:87 src/Module/Register.php:216 #: src/Module/Register.php:255 src/Module/Search/Directory.php:23 #: src/Module/Settings/Account.php:34 src/Module/Settings/Account.php:337 -#: src/Module/Settings/Channels.php:52 src/Module/Settings/Channels.php:127 -#: src/Module/Settings/ContactImport.php:49 -#: src/Module/Settings/ContactImport.php:96 -#: src/Module/Settings/Delegation.php:76 src/Module/Settings/Display.php:81 -#: src/Module/Settings/Display.php:206 +#: src/Module/Settings/Channels.php:54 src/Module/Settings/Channels.php:135 +#: src/Module/Settings/ContactImport.php:50 +#: src/Module/Settings/ContactImport.php:97 +#: src/Module/Settings/Delegation.php:76 src/Module/Settings/Display.php:85 +#: src/Module/Settings/Display.php:214 #: src/Module/Settings/Profile/Photo/Crop.php:148 #: src/Module/Settings/Profile/Photo/Index.php:96 #: src/Module/Settings/RemoveMe.php:103 src/Module/Settings/UserExport.php:64 @@ -128,7 +128,7 @@ msgstr "Beitrag nicht gefunden." #: src/Module/Settings/UserExport.php:199 #: src/Module/Settings/UserExport.php:219 #: src/Module/Settings/UserExport.php:284 src/Module/User/Delegation.php:146 -#: src/Module/User/Import.php:72 src/Module/User/Import.php:79 +#: src/Module/User/Import.php:73 src/Module/User/Import.php:80 msgid "Permission denied." msgstr "Zugriff verweigert." @@ -328,7 +328,7 @@ msgstr "Betreff:" msgid "Your message:" msgstr "Deine Nachricht:" -#: mod/message.php:188 mod/message.php:345 src/Content/Conversation.php:364 +#: mod/message.php:188 mod/message.php:345 src/Content/Conversation.php:371 #: src/Module/Post/Edit.php:129 msgid "Upload photo" msgstr "Foto hochladen" @@ -338,7 +338,7 @@ msgid "Insert web link" msgstr "Einen Link einfügen" #: mod/message.php:190 mod/message.php:348 mod/photos.php:1256 -#: src/Content/Conversation.php:395 src/Content/Conversation.php:1574 +#: src/Content/Conversation.php:402 src/Content/Conversation.php:1611 #: src/Module/Item/Compose.php:205 src/Module/Post/Edit.php:143 #: src/Object/Post.php:617 msgid "Please wait" @@ -360,11 +360,11 @@ msgstr "Nachricht nicht verfügbar." msgid "Delete message" msgstr "Nachricht löschen" -#: mod/message.php:316 mod/message.php:444 +#: mod/message.php:316 mod/message.php:439 msgid "D, d M Y - g:i A" msgstr "D, d. M Y - H:i" -#: mod/message.php:331 mod/message.php:441 +#: mod/message.php:331 mod/message.php:436 msgid "Delete conversation" msgstr "Unterhaltung löschen" @@ -378,22 +378,22 @@ msgstr "Sichere Kommunikation ist nicht verfügbar. Eventuell k msgid "Send Reply" msgstr "Antwort senden" -#: mod/message.php:415 +#: mod/message.php:410 #, php-format msgid "Unknown sender - %s" msgstr "Unbekannter Absender - %s" -#: mod/message.php:417 +#: mod/message.php:412 #, php-format msgid "You and %s" msgstr "Du und %s" -#: mod/message.php:419 +#: mod/message.php:414 #, php-format msgid "%s and You" msgstr "%s und du" -#: mod/message.php:447 +#: mod/message.php:442 #, php-format msgid "%d message" msgid_plural "%d messages" @@ -410,7 +410,7 @@ msgstr "Persönliche Notizen sind nur für dich sichtbar." #: mod/notes.php:46 src/Module/Admin/Storage.php:128 #: src/Module/Filer/SaveTag.php:60 src/Module/Post/Edit.php:127 -#: src/Module/Settings/Channels.php:220 +#: src/Module/Settings/Channels.php:228 msgid "Save" msgstr "Speichern" @@ -507,7 +507,7 @@ msgstr "oder wähle ein bestehendes Album:" msgid "Do not show a status post for this upload" msgstr "Keine Status-Mitteilung für diesen Beitrag anzeigen" -#: mod/photos.php:691 mod/photos.php:1051 src/Content/Conversation.php:397 +#: mod/photos.php:691 mod/photos.php:1051 src/Content/Conversation.php:404 #: src/Module/Calendar/Event/Form.php:239 src/Module/Post/Edit.php:181 msgid "Permissions" msgstr "Berechtigungen" @@ -520,7 +520,7 @@ msgstr "Möchtest du wirklich dieses Foto-Album und all seine Foto löschen?" msgid "Delete Album" msgstr "Album löschen" -#: mod/photos.php:758 mod/photos.php:857 src/Content/Conversation.php:412 +#: mod/photos.php:758 mod/photos.php:857 src/Content/Conversation.php:419 #: src/Module/Contact/Follow.php:158 src/Module/Contact/Revoke.php:92 #: src/Module/Contact/Unfollow.php:112 #: src/Module/Media/Attachment/Browser.php:64 @@ -647,24 +647,24 @@ msgid "Comment" msgstr "Kommentar" #: mod/photos.php:1098 mod/photos.php:1154 mod/photos.php:1234 -#: src/Content/Conversation.php:409 src/Module/Calendar/Event/Form.php:234 +#: src/Content/Conversation.php:416 src/Module/Calendar/Event/Form.php:234 #: src/Module/Item/Compose.php:200 src/Module/Post/Edit.php:163 #: src/Object/Post.php:1176 msgid "Preview" msgstr "Vorschau" -#: mod/photos.php:1099 src/Content/Conversation.php:363 +#: mod/photos.php:1099 src/Content/Conversation.php:370 #: src/Content/Nav.php:113 src/Module/Post/Edit.php:128 #: src/Object/Post.php:1164 msgid "Loading..." msgstr "lädt..." -#: mod/photos.php:1191 src/Content/Conversation.php:1496 +#: mod/photos.php:1191 src/Content/Conversation.php:1533 #: src/Object/Post.php:263 msgid "Select" msgstr "Auswählen" -#: mod/photos.php:1192 mod/photos.php:1279 src/Content/Conversation.php:1497 +#: mod/photos.php:1192 mod/photos.php:1279 src/Content/Conversation.php:1534 #: src/Module/Moderation/Users/Active.php:92 #: src/Module/Moderation/Users/Blocked.php:92 #: src/Module/Moderation/Users/Index.php:100 @@ -847,12 +847,12 @@ msgstr "Alle Kontakte" #: src/Content/Widget.php:257 src/Core/ACL.php:185 src/Module/Contact.php:399 #: src/Module/Privacy/PermissionTooltip.php:181 #: src/Module/Privacy/PermissionTooltip.php:203 -#: src/Module/Settings/Channels.php:146 +#: src/Module/Settings/Channels.php:154 msgid "Followers" msgstr "Folgende" #: src/BaseModule.php:445 src/Content/Widget.php:258 -#: src/Module/Contact.php:402 src/Module/Settings/Channels.php:145 +#: src/Module/Contact.php:402 src/Module/Settings/Channels.php:153 msgid "Following" msgstr "Gefolgte" @@ -1205,375 +1205,385 @@ msgstr "Bluesky" msgid "%s (via %s)" msgstr "%s (via %s)" -#: src/Content/Conversation.php:215 +#: src/Content/Conversation.php:222 msgid "and" msgstr "und" -#: src/Content/Conversation.php:218 +#: src/Content/Conversation.php:225 #, php-format msgid "and %d other people" msgstr "und %dandere" -#: src/Content/Conversation.php:224 +#: src/Content/Conversation.php:231 #, php-format msgid "%2$s likes this." msgid_plural "%2$s like this." msgstr[0] "%2$s mag das." msgstr[1] "%2$s mögen das." -#: src/Content/Conversation.php:226 +#: src/Content/Conversation.php:233 #, php-format msgid "%2$s doesn't like this." msgid_plural "%2$s don't like this." msgstr[0] "%2$s mag das nicht." msgstr[1] "%2$s mögen das nicht." -#: src/Content/Conversation.php:228 +#: src/Content/Conversation.php:235 #, php-format msgid "%2$s attends." msgid_plural "%2$s attend." msgstr[0] "%2$s nimmt teil." msgstr[1] "%2$s nehmen teil." -#: src/Content/Conversation.php:230 +#: src/Content/Conversation.php:237 #, php-format msgid "%2$s doesn't attend." msgid_plural "%2$s don't attend." msgstr[0] "%2$s nimmt nicht teil." msgstr[1] "%2$s nehmen nicht teil." -#: src/Content/Conversation.php:232 +#: src/Content/Conversation.php:239 #, php-format msgid "%2$s attends maybe." msgid_plural "%2$s attend maybe." msgstr[0] "%2$s nimmt eventuell teil." msgstr[1] "%2$s nehmen eventuell teil." -#: src/Content/Conversation.php:234 +#: src/Content/Conversation.php:241 #, php-format msgid "%2$s reshared this." msgid_plural "%2$s reshared this." msgstr[0] "%2$s hat dies geteilt." msgstr[1] "%2$s haben dies geteilt." -#: src/Content/Conversation.php:265 +#: src/Content/Conversation.php:272 #, php-format msgid " likes this" msgid_plural " like this" msgstr[0] " mag das" msgstr[1] " mögen das" -#: src/Content/Conversation.php:274 +#: src/Content/Conversation.php:281 #, php-format msgid " attends" msgid_plural " attend" msgstr[0] " besucht" msgstr[1] " besuchen" -#: src/Content/Conversation.php:277 +#: src/Content/Conversation.php:284 #, php-format msgid " doesn't attend" msgid_plural " don't attend" msgstr[0] " besucht nicht" msgstr[1] " besuchen nicht" -#: src/Content/Conversation.php:280 +#: src/Content/Conversation.php:287 #, php-format msgid " attends maybe" msgid_plural " attend maybe" msgstr[0] " besucht vielleicht" msgstr[1] " besuchen vielleicht" -#: src/Content/Conversation.php:283 +#: src/Content/Conversation.php:290 #, php-format msgid " reshared this" msgid_plural " reshared this" msgstr[0] " teilte dies erneut" msgstr[1] " teilten dies erneut" -#: src/Content/Conversation.php:329 +#: src/Content/Conversation.php:336 msgid "Visible to everybody" msgstr "Für jedermann sichtbar" -#: src/Content/Conversation.php:330 src/Module/Item/Compose.php:199 +#: src/Content/Conversation.php:337 src/Module/Item/Compose.php:199 #: src/Object/Post.php:1175 msgid "Please enter a image/video/audio/webpage URL:" msgstr "Bitte gib eine Bild/Video/Audio/Webseiten-URL ein:" -#: src/Content/Conversation.php:331 +#: src/Content/Conversation.php:338 msgid "Tag term:" msgstr "Tag:" -#: src/Content/Conversation.php:332 +#: src/Content/Conversation.php:339 msgid "Save to Folder" msgstr "In Ordner speichern" -#: src/Content/Conversation.php:333 +#: src/Content/Conversation.php:340 msgid "Where are you right now?" msgstr "Wo hältst du dich jetzt gerade auf?" -#: src/Content/Conversation.php:334 +#: src/Content/Conversation.php:341 msgid "Delete item(s)?" msgstr "Einträge löschen?" -#: src/Content/Conversation.php:335 src/Module/Post/Edit.php:105 +#: src/Content/Conversation.php:342 src/Module/Post/Edit.php:105 msgid "Post published." msgstr "Beitrag gesendet." -#: src/Content/Conversation.php:336 src/Module/Post/Edit.php:106 +#: src/Content/Conversation.php:343 src/Module/Post/Edit.php:106 msgid "Go to post" msgstr "Gehe zum Beitrag." -#: src/Content/Conversation.php:349 src/Module/Item/Compose.php:174 +#: src/Content/Conversation.php:356 src/Module/Item/Compose.php:174 msgid "Created at" msgstr "Erstellt am" -#: src/Content/Conversation.php:359 +#: src/Content/Conversation.php:366 msgid "New Post" msgstr "Neuer Beitrag" -#: src/Content/Conversation.php:362 +#: src/Content/Conversation.php:369 msgid "Share" msgstr "Teilen" -#: src/Content/Conversation.php:365 src/Module/Post/Edit.php:130 +#: src/Content/Conversation.php:372 src/Module/Post/Edit.php:130 msgid "upload photo" msgstr "Bild hochladen" -#: src/Content/Conversation.php:366 src/Module/Post/Edit.php:131 +#: src/Content/Conversation.php:373 src/Module/Post/Edit.php:131 msgid "Attach file" msgstr "Datei anhängen" -#: src/Content/Conversation.php:367 src/Module/Post/Edit.php:132 +#: src/Content/Conversation.php:374 src/Module/Post/Edit.php:132 msgid "attach file" msgstr "Datei anhängen" -#: src/Content/Conversation.php:368 src/Module/Item/Compose.php:189 +#: src/Content/Conversation.php:375 src/Module/Item/Compose.php:189 #: src/Module/Post/Edit.php:169 src/Object/Post.php:1165 msgid "Bold" msgstr "Fett" -#: src/Content/Conversation.php:369 src/Module/Item/Compose.php:190 +#: src/Content/Conversation.php:376 src/Module/Item/Compose.php:190 #: src/Module/Post/Edit.php:170 src/Object/Post.php:1166 msgid "Italic" msgstr "Kursiv" -#: src/Content/Conversation.php:370 src/Module/Item/Compose.php:191 +#: src/Content/Conversation.php:377 src/Module/Item/Compose.php:191 #: src/Module/Post/Edit.php:171 src/Object/Post.php:1167 msgid "Underline" msgstr "Unterstrichen" -#: src/Content/Conversation.php:371 src/Module/Item/Compose.php:192 +#: src/Content/Conversation.php:378 src/Module/Item/Compose.php:192 #: src/Module/Post/Edit.php:172 src/Object/Post.php:1169 msgid "Quote" msgstr "Zitat" -#: src/Content/Conversation.php:372 src/Module/Item/Compose.php:193 +#: src/Content/Conversation.php:379 src/Module/Item/Compose.php:193 #: src/Module/Post/Edit.php:173 src/Object/Post.php:1170 msgid "Add emojis" msgstr "Emojis hinzufügen" -#: src/Content/Conversation.php:373 src/Module/Item/Compose.php:194 +#: src/Content/Conversation.php:380 src/Module/Item/Compose.php:194 #: src/Object/Post.php:1168 msgid "Content Warning" msgstr "Inhaltswarnung" -#: src/Content/Conversation.php:374 src/Module/Item/Compose.php:195 +#: src/Content/Conversation.php:381 src/Module/Item/Compose.php:195 #: src/Module/Post/Edit.php:174 src/Object/Post.php:1171 msgid "Code" msgstr "Code" -#: src/Content/Conversation.php:375 src/Module/Item/Compose.php:196 +#: src/Content/Conversation.php:382 src/Module/Item/Compose.php:196 #: src/Object/Post.php:1172 msgid "Image" msgstr "Bild" -#: src/Content/Conversation.php:376 src/Module/Item/Compose.php:197 +#: src/Content/Conversation.php:383 src/Module/Item/Compose.php:197 #: src/Module/Post/Edit.php:175 src/Object/Post.php:1173 msgid "Link" msgstr "Link" -#: src/Content/Conversation.php:377 src/Module/Item/Compose.php:198 +#: src/Content/Conversation.php:384 src/Module/Item/Compose.php:198 #: src/Module/Post/Edit.php:176 src/Object/Post.php:1174 msgid "Link or Media" msgstr "Link oder Mediendatei" -#: src/Content/Conversation.php:378 +#: src/Content/Conversation.php:385 msgid "Video" msgstr "Video" -#: src/Content/Conversation.php:379 src/Module/Item/Compose.php:201 +#: src/Content/Conversation.php:386 src/Module/Item/Compose.php:201 #: src/Module/Post/Edit.php:139 msgid "Set your location" msgstr "Deinen Standort festlegen" -#: src/Content/Conversation.php:380 src/Module/Post/Edit.php:140 +#: src/Content/Conversation.php:387 src/Module/Post/Edit.php:140 msgid "set location" msgstr "Ort setzen" -#: src/Content/Conversation.php:381 src/Module/Post/Edit.php:141 +#: src/Content/Conversation.php:388 src/Module/Post/Edit.php:141 msgid "Clear browser location" msgstr "Browser-Standort leeren" -#: src/Content/Conversation.php:382 src/Module/Post/Edit.php:142 +#: src/Content/Conversation.php:389 src/Module/Post/Edit.php:142 msgid "clear location" msgstr "Ort löschen" -#: src/Content/Conversation.php:384 src/Module/Item/Compose.php:206 +#: src/Content/Conversation.php:391 src/Module/Item/Compose.php:206 #: src/Module/Post/Edit.php:155 msgid "Set title" msgstr "Titel setzen" -#: src/Content/Conversation.php:386 src/Module/Item/Compose.php:207 +#: src/Content/Conversation.php:393 src/Module/Item/Compose.php:207 #: src/Module/Post/Edit.php:157 msgid "Categories (comma-separated list)" msgstr "Kategorien (kommasepariert)" -#: src/Content/Conversation.php:391 src/Module/Item/Compose.php:227 +#: src/Content/Conversation.php:398 src/Module/Item/Compose.php:227 msgid "Scheduled at" msgstr "Geplant für" -#: src/Content/Conversation.php:396 src/Module/Post/Edit.php:144 +#: src/Content/Conversation.php:403 src/Module/Post/Edit.php:144 msgid "Permission settings" msgstr "Berechtigungseinstellungen" -#: src/Content/Conversation.php:405 src/Module/Post/Edit.php:153 +#: src/Content/Conversation.php:412 src/Module/Post/Edit.php:153 msgid "Public post" msgstr "Öffentlicher Beitrag" -#: src/Content/Conversation.php:419 src/Content/Item.php:442 -#: src/Content/Widget/VCard.php:120 src/Model/Contact.php:1304 +#: src/Content/Conversation.php:426 src/Content/Item.php:442 +#: src/Content/Widget/VCard.php:120 src/Model/Contact.php:1307 #: src/Model/Profile.php:460 src/Module/Admin/Logs/View.php:80 #: src/Module/Post/Edit.php:179 msgid "Message" msgstr "Nachricht" -#: src/Content/Conversation.php:420 src/Module/Post/Edit.php:180 +#: src/Content/Conversation.php:427 src/Module/Post/Edit.php:180 msgid "Add file" msgstr "Dateien" -#: src/Content/Conversation.php:422 src/Module/Post/Edit.php:183 +#: src/Content/Conversation.php:429 src/Module/Post/Edit.php:183 msgid "Open Compose page" msgstr "Composer Seite öffnen" -#: src/Content/Conversation.php:592 +#: src/Content/Conversation.php:599 msgid "remove" msgstr "löschen" -#: src/Content/Conversation.php:596 +#: src/Content/Conversation.php:603 msgid "Delete Selected Items" msgstr "Lösche die markierten Beiträge" -#: src/Content/Conversation.php:720 src/Content/Conversation.php:723 -#: src/Content/Conversation.php:726 src/Content/Conversation.php:729 -#: src/Content/Conversation.php:732 +#: src/Content/Conversation.php:735 src/Content/Conversation.php:738 +#: src/Content/Conversation.php:741 src/Content/Conversation.php:744 +#: src/Content/Conversation.php:747 #, php-format msgid "You had been addressed (%s)." msgstr "Du wurdest angeschrieben (%s)." -#: src/Content/Conversation.php:735 +#: src/Content/Conversation.php:750 #, php-format msgid "You are following %s." msgstr "Du folgst %s." -#: src/Content/Conversation.php:740 +#: src/Content/Conversation.php:755 #, php-format msgid "You subscribed to %s." msgstr "Du hast %s abonniert." -#: src/Content/Conversation.php:742 +#: src/Content/Conversation.php:757 msgid "You subscribed to one or more tags in this post." msgstr "Du folgst einem oder mehreren Hashtags dieses Beitrags." -#: src/Content/Conversation.php:762 +#: src/Content/Conversation.php:777 #, php-format msgid "%s reshared this." msgstr "%s hat dies geteilt" -#: src/Content/Conversation.php:764 +#: src/Content/Conversation.php:779 msgid "Reshared" msgstr "Geteilt" -#: src/Content/Conversation.php:764 +#: src/Content/Conversation.php:779 #, php-format msgid "Reshared by %s <%s>" msgstr "Geteilt von %s <%s>" -#: src/Content/Conversation.php:767 +#: src/Content/Conversation.php:782 #, php-format msgid "%s is participating in this thread." msgstr "%s ist an der Unterhaltung beteiligt." -#: src/Content/Conversation.php:770 +#: src/Content/Conversation.php:785 msgid "Stored for general reasons" msgstr "Aus allgemeinen Gründen aufbewahrt" -#: src/Content/Conversation.php:773 +#: src/Content/Conversation.php:788 msgid "Global post" msgstr "Globaler Beitrag" -#: src/Content/Conversation.php:776 +#: src/Content/Conversation.php:791 msgid "Sent via an relay server" msgstr "Über einen Relay-Server gesendet" -#: src/Content/Conversation.php:776 +#: src/Content/Conversation.php:791 #, php-format msgid "Sent via the relay server %s <%s>" msgstr "Über den Relay-Server %s <%s> gesendet" -#: src/Content/Conversation.php:779 +#: src/Content/Conversation.php:794 msgid "Fetched" msgstr "Abgerufen" -#: src/Content/Conversation.php:779 +#: src/Content/Conversation.php:794 #, php-format msgid "Fetched because of %s <%s>" msgstr "Wegen %s <%s> abgerufen" -#: src/Content/Conversation.php:782 +#: src/Content/Conversation.php:797 msgid "Stored because of a child post to complete this thread." msgstr "Gespeichert wegen eines untergeordneten Beitrags zur Vervollständigung dieses Themas." -#: src/Content/Conversation.php:785 +#: src/Content/Conversation.php:800 msgid "Local delivery" msgstr "Lokale Zustellung" -#: src/Content/Conversation.php:788 +#: src/Content/Conversation.php:803 msgid "Stored because of your activity (like, comment, star, ...)" msgstr "Gespeichert aufgrund Ihrer Aktivität (Like, Kommentar, Stern, ...)" -#: src/Content/Conversation.php:791 +#: src/Content/Conversation.php:806 msgid "Distributed" msgstr "Verteilt" -#: src/Content/Conversation.php:794 +#: src/Content/Conversation.php:809 msgid "Pushed to us" msgstr "Zu uns gepusht" -#: src/Content/Conversation.php:1516 src/Object/Post.php:250 +#: src/Content/Conversation.php:816 +#, php-format +msgid "Channel \"%s\": %s" +msgstr "" + +#: src/Content/Conversation.php:818 +#, php-format +msgid "Channel \"%s\"" +msgstr "" + +#: src/Content/Conversation.php:1553 src/Object/Post.php:250 msgid "Pinned item" msgstr "Angehefteter Beitrag" -#: src/Content/Conversation.php:1533 src/Object/Post.php:552 +#: src/Content/Conversation.php:1570 src/Object/Post.php:552 #: src/Object/Post.php:553 #, php-format msgid "View %s's profile @ %s" msgstr "Das Profil von %s auf %s betrachten." -#: src/Content/Conversation.php:1547 src/Object/Post.php:540 +#: src/Content/Conversation.php:1584 src/Object/Post.php:540 msgid "Categories:" msgstr "Kategorien:" -#: src/Content/Conversation.php:1548 src/Object/Post.php:541 +#: src/Content/Conversation.php:1585 src/Object/Post.php:541 msgid "Filed under:" msgstr "Abgelegt unter:" -#: src/Content/Conversation.php:1556 src/Object/Post.php:568 +#: src/Content/Conversation.php:1593 src/Object/Post.php:568 #, php-format msgid "%s from %s" msgstr "%s von %s" -#: src/Content/Conversation.php:1572 +#: src/Content/Conversation.php:1609 msgid "View in context" msgstr "Im Zusammenhang betrachten" @@ -1627,7 +1637,7 @@ msgid "Posts from accounts that you follow but who don't post very often" msgstr "Beiträge von Konten, denen du folgst, die jedoch nicht sehr oft posten." #: src/Content/Conversation/Factory/Channel.php:36 -#: src/Module/Settings/Channels.php:185 src/Module/Settings/Channels.php:211 +#: src/Module/Settings/Channels.php:193 src/Module/Settings/Channels.php:219 msgid "Images" msgstr "Bilder" @@ -1636,7 +1646,7 @@ msgid "Posts with images" msgstr "Beiträge mit Bildern" #: src/Content/Conversation/Factory/Channel.php:37 -#: src/Module/Settings/Channels.php:187 src/Module/Settings/Channels.php:213 +#: src/Module/Settings/Channels.php:195 src/Module/Settings/Channels.php:221 msgid "Audio" msgstr "Audio" @@ -1645,7 +1655,7 @@ msgid "Posts with audio" msgstr "Beiträge mit Audio" #: src/Content/Conversation/Factory/Channel.php:38 -#: src/Module/Settings/Channels.php:186 src/Module/Settings/Channels.php:212 +#: src/Module/Settings/Channels.php:194 src/Module/Settings/Channels.php:220 msgid "Videos" msgstr "Videos" @@ -1662,7 +1672,7 @@ msgid "Posts from local users on this server" msgstr "Beiträge von Nutzern dieses Servers" #: src/Content/Conversation/Factory/Community.php:33 -#: src/Module/Settings/Channels.php:136 src/Module/Settings/Channels.php:141 +#: src/Module/Settings/Channels.php:144 src/Module/Settings/Channels.php:149 msgid "Global Community" msgstr "Globale Gemeinschaft" @@ -1671,7 +1681,7 @@ msgid "Posts from users of the whole federated network" msgstr "Beiträge von Nutzern des gesamten föderalen Netzwerks" #: src/Content/Conversation/Factory/Network.php:24 -#: src/Module/Settings/Channels.php:142 +#: src/Module/Settings/Channels.php:150 msgid "Latest Activity" msgstr "Neu - Aktivität" @@ -1680,7 +1690,7 @@ msgid "Sort by latest activity" msgstr "Sortiere nach neueste Aktivität" #: src/Content/Conversation/Factory/Network.php:25 -#: src/Module/Settings/Channels.php:143 +#: src/Module/Settings/Channels.php:151 msgid "Latest Posts" msgstr "Neu - Empfangen" @@ -1689,7 +1699,7 @@ msgid "Sort by post received date" msgstr "Nach Empfangsdatum der Beiträge sortiert" #: src/Content/Conversation/Factory/Network.php:26 -#: src/Module/Settings/Channels.php:144 +#: src/Module/Settings/Channels.php:152 msgid "Latest Creation" msgstr "Neu - Erstellung" @@ -1828,7 +1838,7 @@ msgstr "Anzeige der Beiträge, die von Konten mit dem ausgewählten Kontotyp ers #: src/Content/Feature.php:132 src/Content/Widget.php:626 #: src/Module/Admin/Site.php:474 src/Module/BaseSettings.php:113 -#: src/Module/Settings/Channels.php:216 src/Module/Settings/Display.php:400 +#: src/Module/Settings/Channels.php:224 src/Module/Settings/Display.php:429 msgid "Channels" msgstr "Kanäle" @@ -1852,7 +1862,7 @@ msgstr "Gespeicherte Ordner" msgid "Display a list of folders in which posts are stored." msgstr "Ordnerliste anzeigen in denen Beiträge gespeichert sind." -#: src/Content/Feature.php:135 src/Module/Conversation/Timeline.php:190 +#: src/Content/Feature.php:135 src/Module/Conversation/Timeline.php:188 msgid "Own Contacts" msgstr "Eigene Kontakte" @@ -1925,7 +1935,7 @@ msgstr "Neue Gruppe erstellen" msgid "Find groups to join" msgstr "Finde Gruppe zum Folgen" -#: src/Content/Item.php:336 src/Model/Item.php:2787 +#: src/Content/Item.php:336 src/Model/Item.php:2834 msgid "event" msgstr "Veranstaltung" @@ -1933,7 +1943,7 @@ msgstr "Veranstaltung" msgid "status" msgstr "Status" -#: src/Content/Item.php:345 src/Model/Item.php:2789 +#: src/Content/Item.php:345 src/Model/Item.php:2836 #: src/Module/Post/Tag/Add.php:112 msgid "photo" msgstr "Foto" @@ -1951,28 +1961,28 @@ msgstr "Folge der Unterhaltung" msgid "Complete Thread" msgstr "Vollständiger Thread" -#: src/Content/Item.php:437 src/Model/Contact.php:1299 +#: src/Content/Item.php:437 src/Model/Contact.php:1302 msgid "View Status" msgstr "Status anschauen" #: src/Content/Item.php:438 src/Content/Item.php:461 -#: src/Model/Contact.php:1234 src/Model/Contact.php:1290 -#: src/Model/Contact.php:1300 src/Module/Directory.php:143 +#: src/Model/Contact.php:1237 src/Model/Contact.php:1293 +#: src/Model/Contact.php:1303 src/Module/Directory.php:143 #: src/Module/Settings/Profile/Index.php:279 msgid "View Profile" msgstr "Profil anschauen" -#: src/Content/Item.php:439 src/Model/Contact.php:1301 +#: src/Content/Item.php:439 src/Model/Contact.php:1304 msgid "View Photos" msgstr "Bilder anschauen" -#: src/Content/Item.php:440 src/Model/Contact.php:1268 +#: src/Content/Item.php:440 src/Model/Contact.php:1271 #: src/Model/Profile.php:443 msgid "Network Posts" msgstr "Netzwerkbeiträge" -#: src/Content/Item.php:441 src/Model/Contact.php:1292 -#: src/Model/Contact.php:1303 +#: src/Content/Item.php:441 src/Model/Contact.php:1295 +#: src/Model/Contact.php:1306 msgid "View Contact" msgstr "Kontakt anzeigen" @@ -1986,8 +1996,8 @@ msgstr "Sperren" #: src/Content/Item.php:444 src/Module/Contact.php:454 #: src/Module/Contact/Profile.php:587 -#: src/Module/Notifications/Introductions.php:126 -#: src/Module/Notifications/Introductions.php:200 +#: src/Module/Notifications/Introductions.php:130 +#: src/Module/Notifications/Introductions.php:206 msgid "Ignore" msgstr "Ignorieren" @@ -2010,7 +2020,7 @@ msgid "Raw content" msgstr "Rohdaten" #: src/Content/Item.php:458 src/Content/Widget.php:65 -#: src/Model/Contact.php:1293 src/Model/Contact.php:1305 +#: src/Model/Contact.php:1296 src/Model/Contact.php:1308 #: src/Module/Contact/Follow.php:152 view/theme/vier/theme.php:182 msgid "Connect/Follow" msgstr "Verbinden/Folgen" @@ -2117,7 +2127,7 @@ msgstr "Deine Beiträge die Medien beinhalten" #: src/Content/Nav.php:231 src/Content/Nav.php:291 #: src/Module/BaseProfile.php:70 src/Module/BaseProfile.php:73 #: src/Module/BaseProfile.php:81 src/Module/BaseProfile.php:84 -#: src/Module/Settings/Display.php:401 view/theme/frio/theme.php:224 +#: src/Module/Settings/Display.php:430 view/theme/frio/theme.php:224 #: view/theme/frio/theme.php:228 msgid "Calendar" msgstr "Kalender" @@ -2245,7 +2255,7 @@ msgid "Friend Requests" msgstr "Kontaktanfragen" #: src/Content/Nav.php:311 src/Module/BaseNotifications.php:134 -#: src/Module/Notifications/Introductions.php:61 +#: src/Module/Notifications/Introductions.php:63 msgid "Notifications" msgstr "Benachrichtigungen" @@ -2353,8 +2363,8 @@ msgstr "letzte" msgid "%2$s %3$s" msgstr "%2$s%3$s" -#: src/Content/Text/BBCode.php:945 src/Model/Item.php:3677 -#: src/Model/Item.php:3683 src/Model/Item.php:3684 +#: src/Content/Text/BBCode.php:945 src/Model/Item.php:3724 +#: src/Model/Item.php:3730 src/Model/Item.php:3731 msgid "Link to source" msgstr "Link zum Originalbeitrag" @@ -2508,7 +2518,7 @@ msgstr "Personen" msgid "Organisations" msgstr "Organisationen" -#: src/Content/Widget.php:557 src/Model/Contact.php:1811 +#: src/Content/Widget.php:557 src/Model/Contact.php:1814 msgid "News" msgstr "Nachrichten" @@ -2570,12 +2580,12 @@ msgstr "Mehr anzeigen" msgid "Show Less" msgstr "Weniger anzeigen" -#: src/Content/Widget/VCard.php:94 src/Model/Contact.php:1262 +#: src/Content/Widget/VCard.php:94 src/Model/Contact.php:1265 #: src/Model/Profile.php:437 msgid "Post to group" msgstr "Beitrag an Gruppe" -#: src/Content/Widget/VCard.php:99 src/Model/Contact.php:1266 +#: src/Content/Widget/VCard.php:99 src/Model/Contact.php:1269 #: src/Model/Profile.php:441 src/Module/Moderation/Item/Source.php:81 msgid "Mention" msgstr "Mention" @@ -2593,13 +2603,13 @@ msgstr "Matrix:" #: src/Content/Widget/VCard.php:111 src/Model/Event.php:68 #: src/Model/Event.php:95 src/Model/Event.php:462 src/Model/Event.php:953 #: src/Model/Profile.php:351 src/Module/Contact/Profile.php:458 -#: src/Module/Directory.php:133 src/Module/Notifications/Introductions.php:181 +#: src/Module/Directory.php:133 src/Module/Notifications/Introductions.php:187 #: src/Module/Profile/Profile.php:235 msgid "Location:" msgstr "Ort:" #: src/Content/Widget/VCard.php:114 src/Model/Profile.php:467 -#: src/Module/Notifications/Introductions.php:195 +#: src/Module/Notifications/Introductions.php:201 msgid "Network:" msgstr "Netzwerk:" @@ -2608,13 +2618,13 @@ msgstr "Netzwerk:" msgid "Follow" msgstr "Folge" -#: src/Content/Widget/VCard.php:118 src/Model/Contact.php:1294 -#: src/Model/Contact.php:1306 src/Model/Profile.php:456 +#: src/Content/Widget/VCard.php:118 src/Model/Contact.php:1297 +#: src/Model/Contact.php:1309 src/Model/Profile.php:456 #: src/Module/Contact/Profile.php:521 msgid "Unfollow" msgstr "Entfolgen" -#: src/Content/Widget/VCard.php:124 src/Model/Contact.php:1264 +#: src/Content/Widget/VCard.php:124 src/Model/Contact.php:1267 #: src/Model/Profile.php:439 msgid "View group" msgstr "Gruppe betrachten" @@ -3017,37 +3027,37 @@ msgid "%s (%s)" msgstr "%s (%s)" #: src/Core/L10n.php:512 src/Model/Event.php:421 -#: src/Module/Settings/Display.php:368 +#: src/Module/Settings/Display.php:397 msgid "Monday" msgstr "Montag" #: src/Core/L10n.php:512 src/Model/Event.php:422 -#: src/Module/Settings/Display.php:369 +#: src/Module/Settings/Display.php:398 msgid "Tuesday" msgstr "Dienstag" #: src/Core/L10n.php:512 src/Model/Event.php:423 -#: src/Module/Settings/Display.php:370 +#: src/Module/Settings/Display.php:399 msgid "Wednesday" msgstr "Mittwoch" #: src/Core/L10n.php:512 src/Model/Event.php:424 -#: src/Module/Settings/Display.php:371 +#: src/Module/Settings/Display.php:400 msgid "Thursday" msgstr "Donnerstag" #: src/Core/L10n.php:512 src/Model/Event.php:425 -#: src/Module/Settings/Display.php:372 +#: src/Module/Settings/Display.php:401 msgid "Friday" msgstr "Freitag" #: src/Core/L10n.php:512 src/Model/Event.php:426 -#: src/Module/Settings/Display.php:373 +#: src/Module/Settings/Display.php:402 msgid "Saturday" msgstr "Samstag" #: src/Core/L10n.php:512 src/Model/Event.php:420 -#: src/Module/Settings/Display.php:367 +#: src/Module/Settings/Display.php:396 msgid "Sunday" msgstr "Sonntag" @@ -3385,89 +3395,89 @@ msgstr "Kreis Name: " msgid "Edit circles" msgstr "Kreis bearbeiten" -#: src/Model/Contact.php:1313 src/Module/Moderation/Users/Pending.php:88 -#: src/Module/Notifications/Introductions.php:124 +#: src/Model/Contact.php:1316 src/Module/Moderation/Users/Pending.php:88 +#: src/Module/Notifications/Introductions.php:128 msgid "Approve" msgstr "Genehmigen" -#: src/Model/Contact.php:1655 src/Model/Contact.php:1727 +#: src/Model/Contact.php:1658 src/Model/Contact.php:1730 #: src/Module/Contact/Profile.php:399 #, php-format msgid "%s has blocked you" msgstr "%s hat dich blockiert" -#: src/Model/Contact.php:1807 +#: src/Model/Contact.php:1810 msgid "Organisation" msgstr "Organisation" -#: src/Model/Contact.php:1815 +#: src/Model/Contact.php:1818 msgid "Group" msgstr "Gruppe" -#: src/Model/Contact.php:1819 src/Module/Moderation/BaseUsers.php:150 +#: src/Model/Contact.php:1822 src/Module/Moderation/BaseUsers.php:150 msgid "Relay" msgstr "Relais" -#: src/Model/Contact.php:3149 +#: src/Model/Contact.php:3152 msgid "Disallowed profile URL." msgstr "Nicht erlaubte Profil-URL." -#: src/Model/Contact.php:3154 src/Module/Friendica.php:106 +#: src/Model/Contact.php:3157 src/Module/Friendica.php:106 msgid "Blocked domain" msgstr "Blockierte Domain" -#: src/Model/Contact.php:3159 +#: src/Model/Contact.php:3162 msgid "Connect URL missing." msgstr "Connect-URL fehlt" -#: src/Model/Contact.php:3172 +#: src/Model/Contact.php:3175 msgid "" "The contact could not be added. Please check the relevant network " "credentials in your Settings -> Social Networks page." msgstr "Der Kontakt konnte nicht hinzugefügt werden. Bitte überprüfe die Einstellungen unter Einstellungen -> Soziale Netzwerke" -#: src/Model/Contact.php:3190 +#: src/Model/Contact.php:3193 #, php-format msgid "Expected network %s does not match actual network %s" msgstr "Erwartetes Netzwerk %s stimmt nicht mit dem tatsächlichen Netzwerk überein %s" -#: src/Model/Contact.php:3207 +#: src/Model/Contact.php:3210 msgid "This seems to be a relay account. They can't be followed by users." msgstr "Dies scheint ein Relais-Konto zu sein. Diese können nicht von Nutzern gefolgt werden." -#: src/Model/Contact.php:3214 +#: src/Model/Contact.php:3217 msgid "The profile address specified does not provide adequate information." msgstr "Die angegebene Profiladresse liefert unzureichende Informationen." -#: src/Model/Contact.php:3216 +#: src/Model/Contact.php:3219 msgid "No compatible communication protocols or feeds were discovered." msgstr "Es wurden keine kompatiblen Kommunikationsprotokolle oder Feeds gefunden." -#: src/Model/Contact.php:3219 +#: src/Model/Contact.php:3222 msgid "An author or name was not found." msgstr "Es wurde kein Autor oder Name gefunden." -#: src/Model/Contact.php:3222 +#: src/Model/Contact.php:3225 msgid "No browser URL could be matched to this address." msgstr "Zu dieser Adresse konnte keine passende Browser-URL gefunden werden." -#: src/Model/Contact.php:3225 +#: src/Model/Contact.php:3228 msgid "" "Unable to match @-style Identity Address with a known protocol or email " "contact." msgstr "Konnte die @-Adresse mit keinem der bekannten Protokolle oder Email-Kontakte abgleichen." -#: src/Model/Contact.php:3226 +#: src/Model/Contact.php:3229 msgid "Use mailto: in front of address to force email check." msgstr "Verwende mailto: vor der E-Mail-Adresse, um eine Überprüfung der E-Mail-Adresse zu erzwingen." -#: src/Model/Contact.php:3232 +#: src/Model/Contact.php:3235 msgid "" "Limited profile. This person will be unable to receive direct/personal " "notifications from you." msgstr "Eingeschränktes Profil. Diese Person wird keine direkten/privaten Nachrichten von dir erhalten können." -#: src/Model/Contact.php:3291 +#: src/Model/Contact.php:3294 msgid "Unable to retrieve contact information." msgstr "Konnte die Kontaktinformationen nicht empfangen." @@ -3499,17 +3509,17 @@ msgid "today" msgstr "Heute" #: src/Model/Event.php:454 src/Module/Calendar/Show.php:118 -#: src/Module/Settings/Display.php:378 src/Util/Temporal.php:343 +#: src/Module/Settings/Display.php:407 src/Util/Temporal.php:343 msgid "month" msgstr "Monat" #: src/Model/Event.php:455 src/Module/Calendar/Show.php:119 -#: src/Module/Settings/Display.php:379 src/Util/Temporal.php:344 +#: src/Module/Settings/Display.php:408 src/Util/Temporal.php:344 msgid "week" msgstr "Woche" #: src/Model/Event.php:456 src/Module/Calendar/Show.php:120 -#: src/Module/Settings/Display.php:380 src/Util/Temporal.php:345 +#: src/Module/Settings/Display.php:409 src/Util/Temporal.php:345 msgid "day" msgstr "Tag" @@ -3576,88 +3586,88 @@ msgstr "%ss Geburtstag" msgid "Happy Birthday %s" msgstr "Herzlichen Glückwunsch, %s" -#: src/Model/Item.php:2791 +#: src/Model/Item.php:2838 msgid "activity" msgstr "Aktivität" -#: src/Model/Item.php:2793 +#: src/Model/Item.php:2840 msgid "comment" msgstr "Kommentar" -#: src/Model/Item.php:2796 src/Module/Post/Tag/Add.php:112 +#: src/Model/Item.php:2843 src/Module/Post/Tag/Add.php:112 msgid "post" msgstr "Beitrag" -#: src/Model/Item.php:2985 +#: src/Model/Item.php:3032 #, php-format msgid "%s is blocked" msgstr "%s ist blockiert" -#: src/Model/Item.php:2987 +#: src/Model/Item.php:3034 #, php-format msgid "%s is ignored" msgstr "%s ist ignoriert" -#: src/Model/Item.php:2989 +#: src/Model/Item.php:3036 #, php-format msgid "Content from %s is collapsed" msgstr "Inhalt vom %s ist zugeklappt" -#: src/Model/Item.php:2993 +#: src/Model/Item.php:3040 msgid "Sensitive content" msgstr "Sensitiver Inhalt" -#: src/Model/Item.php:3547 +#: src/Model/Item.php:3594 msgid "bytes" msgstr "Byte" -#: src/Model/Item.php:3581 +#: src/Model/Item.php:3628 #, php-format msgid "" "The media in this post is not displayed to visitors. To view it, please go " "to the original post." msgstr "Die Medien in diesem Beitrag werden Besuchern nicht angezeigt. Um sie anzusehen, gehe bitte zum Originalbeitrag." -#: src/Model/Item.php:3583 +#: src/Model/Item.php:3630 msgid "" "The media in this post is not displayed to visitors. To view it, please log " "in." msgstr "Die Medien in diesem Beitrag werden Besuchern nicht angezeigt. Um sie anzuzeigen, melden Sie sich bitte an." -#: src/Model/Item.php:3608 +#: src/Model/Item.php:3655 #, php-format msgid "%2$s (%3$d%%, %1$d vote)" msgid_plural "%2$s (%3$d%%, %1$d votes)" msgstr[0] "%2$s (%3$d%%, %1$d Stimme)" msgstr[1] "%2$s (%3$d%%, %1$d Stimmen)" -#: src/Model/Item.php:3610 +#: src/Model/Item.php:3657 #, php-format msgid "%2$s (%1$d vote)" msgid_plural "%2$s (%1$d votes)" msgstr[0] "%2$s (%1$d Stimme)" msgstr[1] "%2$s (%1$d Stimmen)" -#: src/Model/Item.php:3615 +#: src/Model/Item.php:3662 #, php-format msgid "%d voter. Poll end: %s" msgid_plural "%d voters. Poll end: %s" msgstr[0] "%d Stimme, Abstimmung endet: %s" msgstr[1] "%d Stimmen, Abstimmung endet: %s" -#: src/Model/Item.php:3617 +#: src/Model/Item.php:3664 #, php-format msgid "%d voter." msgid_plural "%d voters." msgstr[0] "%d Stimme." msgstr[1] "%d Stimmen." -#: src/Model/Item.php:3619 +#: src/Model/Item.php:3666 #, php-format msgid "Poll end: %s" msgstr "Abstimmung endet: %s" -#: src/Model/Item.php:3660 src/Model/Item.php:3661 +#: src/Model/Item.php:3707 src/Model/Item.php:3708 msgid "View on separate page" msgstr "Auf separater Seite ansehen" @@ -3679,7 +3689,7 @@ msgid "Homepage:" msgstr "Homepage:" #: src/Model/Profile.php:355 src/Module/Contact/Profile.php:464 -#: src/Module/Notifications/Introductions.php:183 +#: src/Module/Notifications/Introductions.php:189 msgid "About:" msgstr "Über:" @@ -3763,7 +3773,7 @@ msgstr "Dislikes:" msgid "Title/Description:" msgstr "Titel/Beschreibung:" -#: src/Model/Profile.php:803 src/Module/Admin/Summary.php:184 +#: src/Model/Profile.php:803 src/Module/Admin/Summary.php:208 #: src/Module/Moderation/Report/Create.php:282 #: src/Module/Moderation/Summary.php:65 msgid "Summary" @@ -3912,7 +3922,7 @@ msgid "The nickname was blocked from registration by the nodes admin." msgstr "Die Administrator:innen des Knotens hat den Spitznamen für die Registrierung gesperrt." #: src/Model/User.php:1290 src/Model/User.php:1296 -#: src/Module/User/Import.php:230 +#: src/Module/User/Import.php:231 msgid "Cannot use that email." msgstr "Konnte diese E-Mail-Adresse nicht verwenden." @@ -4086,7 +4096,7 @@ msgstr "Ungültiges Addon gefunden." #: src/Module/Admin/Addons/Index.php:83 src/Module/Admin/Federation.php:218 #: src/Module/Admin/Logs/Settings.php:74 src/Module/Admin/Logs/View.php:71 #: src/Module/Admin/Queue.php:59 src/Module/Admin/Site.php:457 -#: src/Module/Admin/Storage.php:124 src/Module/Admin/Summary.php:183 +#: src/Module/Admin/Storage.php:124 src/Module/Admin/Summary.php:207 #: src/Module/Admin/Themes/Details.php:82 #: src/Module/Admin/Themes/Index.php:103 src/Module/Admin/Tos.php:63 #: src/Module/Moderation/Users/Pending.php:82 @@ -4129,8 +4139,8 @@ msgstr "Addon %s konnte nicht installiert werden" #: src/Module/Settings/Account.php:507 src/Module/Settings/Addons.php:64 #: src/Module/Settings/Connectors.php:143 #: src/Module/Settings/Connectors.php:228 -#: src/Module/Settings/ContactImport.php:110 -#: src/Module/Settings/Delegation.php:179 src/Module/Settings/Display.php:393 +#: src/Module/Settings/ContactImport.php:111 +#: src/Module/Settings/Delegation.php:179 src/Module/Settings/Display.php:422 #: src/Module/Settings/Features.php:90 #: src/Module/Settings/Profile/Index.php:272 msgid "Save Settings" @@ -4207,14 +4217,14 @@ msgid "Attempt to execute this update step automatically" msgstr "Versuchen, diesen Schritt automatisch auszuführen" #: src/Module/Admin/Features.php:53 -#: src/Module/Notifications/Introductions.php:136 +#: src/Module/Notifications/Introductions.php:140 #: src/Module/OAuth/Acknowledge.php:41 src/Module/Register.php:128 #: src/Module/Settings/TwoFactor/Trusted.php:115 msgid "No" msgstr "Nein" #: src/Module/Admin/Features.php:53 src/Module/Contact/Revoke.php:91 -#: src/Module/Notifications/Introductions.php:136 +#: src/Module/Notifications/Introductions.php:140 #: src/Module/OAuth/Acknowledge.php:40 src/Module/Register.php:127 #: src/Module/Settings/TwoFactor/Trusted.php:115 msgid "Yes" @@ -4394,7 +4404,7 @@ msgid "Search in logs" msgstr "Logs durchsuchen" #: src/Module/Admin/Logs/View.php:76 -#: src/Module/Notifications/Notifications.php:132 +#: src/Module/Notifications/Notifications.php:134 msgid "Show all" msgstr "Alle anzeigen" @@ -4510,11 +4520,11 @@ msgstr "%s ist keine gültige Angabe der maximalen Größe von Medien" msgid "%s is no valid input for maximum image size" msgstr "%s ist keine gültige Angabe der maximalen Größe von Bildern" -#: src/Module/Admin/Site.php:364 src/Module/Settings/Display.php:224 +#: src/Module/Admin/Site.php:364 src/Module/Settings/Display.php:232 msgid "No special theme for mobile devices" msgstr "Kein spezielles Theme für mobile Geräte verwenden." -#: src/Module/Admin/Site.php:381 src/Module/Settings/Display.php:234 +#: src/Module/Admin/Site.php:381 src/Module/Settings/Display.php:242 #, php-format msgid "%s - (Experimental)" msgstr "%s - (Experimentell)" @@ -5618,7 +5628,7 @@ msgid "" msgstr "Der Wert kann entweder 'Alle' oder 'Schlagwörter' sein. 'Alle' bedeutet, dass alle öffentliche Beiträge empfangen werden sollen. 'Schlagwörter' schränkt dem Empfang auf Beiträge ein, die bestimmte Schlagwörter beinhalten." #: src/Module/Admin/Site.php:596 src/Module/Contact/Profile.php:354 -#: src/Module/Settings/Display.php:269 +#: src/Module/Settings/Display.php:277 #: src/Module/Settings/TwoFactor/Index.php:132 msgid "Disabled" msgstr "Deaktiviert" @@ -5800,12 +5810,12 @@ msgstr "Das Ändern des aktuellen Backends ist nicht möglich, da es durch eine msgid "Database (legacy)" msgstr "Datenbank (legacy)" -#: src/Module/Admin/Summary.php:39 +#: src/Module/Admin/Summary.php:40 #, php-format msgid "Template engine (%s) error: %s" msgstr "Template engine (%s) Fehler: %s" -#: src/Module/Admin/Summary.php:43 +#: src/Module/Admin/Summary.php:44 #, php-format msgid "" "Your DB still runs with MyISAM tables. You should change the engine type to " @@ -5816,7 +5826,7 @@ msgid "" " an automatic conversion.
    " msgstr "Deine DB verwendet derzeit noch MyISAM Tabellen. Du solltest die Datenbank Engine auf InnoDB umstellen, da Friendica in Zukunft InnoDB-Features verwenden wird. Eine Anleitung zur Umstellung der Datenbank kannst du hier finden. Du kannst außerdem mit dem Befehl php bin/console.php dbstructure toinnodb auf der Kommandozeile die Umstellung automatisch vornehmen lassen." -#: src/Module/Admin/Summary.php:48 +#: src/Module/Admin/Summary.php:49 #, php-format msgid "" "Your DB still runs with InnoDB tables in the Antelope file format. You " @@ -5827,7 +5837,7 @@ msgid "" " installation for an automatic conversion.
    " msgstr "Deine DB verwendet derzeit noch InnoDB Tabellen im Antelope Dateiformat. Du solltest diese auf das Barracuda Format ändern. Friendica verwendet einige Features, die nicht vom Antelope Format unterstützt werden. Hier findest du eine Anleitung für die Umstellung. Alternativ kannst du auch den Befehl php bin/console.php dbstructure toinnodb In der Kommandozeile deiner Friendica Instanz verwenden um die Formate automatisch anzupassen.
    " -#: src/Module/Admin/Summary.php:58 +#: src/Module/Admin/Summary.php:59 #, php-format msgid "" "Your table_definition_cache is too low (%d). This can lead to the database " @@ -5835,46 +5845,46 @@ msgid "" " to %d. See here for more information.
    " msgstr "Der Wert table_definition_cache ist zu niedrig (%d). Dadurch können Datenbank Fehler \"Prepared statement needs to be re-prepared\" hervor gerufen werden. Bitte setze den Wert auf mindestens %d. Weiterführende Informationen findest du hier." -#: src/Module/Admin/Summary.php:66 +#: src/Module/Admin/Summary.php:67 #, php-format msgid "" "There is a new version of Friendica available for download. Your current " "version is %1$s, upstream version is %2$s" msgstr "Es gibt eine neue Version von Friendica. Du verwendest derzeit die Version %1$s, die aktuelle Version ist %2$s." -#: src/Module/Admin/Summary.php:74 +#: src/Module/Admin/Summary.php:75 msgid "" "The database update failed. Please run \"php bin/console.php dbstructure " "update\" from the command line and have a look at the errors that might " "appear." msgstr "Das Update der Datenbank ist fehlgeschlagen. Bitte führe 'php bin/console.php dbstructure update' in der Kommandozeile aus und achte auf eventuell auftretende Fehlermeldungen." -#: src/Module/Admin/Summary.php:78 +#: src/Module/Admin/Summary.php:79 msgid "" "The last update failed. Please run \"php bin/console.php dbstructure " "update\" from the command line and have a look at the errors that might " "appear. (Some of the errors are possibly inside the logfile.)" msgstr "Das letzte Update ist fehlgeschlagen. Bitte führe \"php bin/console.php dbstructure update\" auf der Kommandozeile aus und werfe einen Blick auf eventuell auftretende Fehler. (Zusätzliche Informationen zu Fehlern könnten in den Logdateien stehen.)" -#: src/Module/Admin/Summary.php:82 +#: src/Module/Admin/Summary.php:83 msgid "" "The system.url entry is missing. This is a low level setting and can lead to" " unexpected behavior. Please add a valid entry as soon as possible in the " "config file or per console command!" msgstr "Der Eintrag system.url fehlt. Dies ist eine Einstellung auf niedriger Ebene und kann zu unerwartetem Verhalten führen. Bitt füge so bald wie möglich einen gültigen Eintrag in der Konfigurationsdatei oder per Konsolenbefehl hinzu!" -#: src/Module/Admin/Summary.php:87 +#: src/Module/Admin/Summary.php:88 msgid "The worker was never executed. Please check your database structure!" msgstr "Der Hintergrundprozess (worker) wurde noch nie gestartet. Bitte überprüfe deine Datenbankstruktur." -#: src/Module/Admin/Summary.php:89 +#: src/Module/Admin/Summary.php:90 #, php-format msgid "" "The last worker execution was on %s UTC. This is older than one hour. Please" " check your crontab settings." msgstr "Der Hintergrundprozess (worker) wurde zuletzt um %s UTC ausgeführt. Das war vor mehr als einer Stunde. Bitte überprüfe deine crontab-Einstellungen." -#: src/Module/Admin/Summary.php:94 +#: src/Module/Admin/Summary.php:95 #, php-format msgid "" "Friendica's configuration now is stored in config/local.config.php, please " @@ -5883,7 +5893,7 @@ msgid "" "help with the transition." msgstr "Die Konfiguration von Friendica befindet sich ab jetzt in der 'config/local.config.php' Datei. Kopiere bitte die Datei 'config/local-sample.config.php' nach 'config/local.config.php' und setze die Konfigurationvariablen so wie in der alten .htconfig.php. Wie die Übertragung der Werte aussehen muss, kannst du der Konfiguration Hilfeseite entnehmen." -#: src/Module/Admin/Summary.php:98 +#: src/Module/Admin/Summary.php:99 #, php-format msgid "" "Friendica's configuration now is stored in config/local.config.php, please " @@ -5892,7 +5902,7 @@ msgid "" "page for help with the transition." msgstr "Die Konfiguration von Friendica befindet sich ab jetzt in der 'config/local.config.php' Datei. Kopiere bitte die Datei 'config/local-sample.config.php' nach 'config/local.config.php' und setze die Konfigurationvariablen so wie in der alten config/local.ini.php. Wie die Übertragung der Werte aussehen muss, kannst du der Konfiguration Hilfeseite entnehmen." -#: src/Module/Admin/Summary.php:105 +#: src/Module/Admin/Summary.php:106 #, php-format msgid "" "%s is not reachable on your system. This is a severe " @@ -5900,43 +5910,47 @@ msgid "" "href=\"%s\">the installation page for help." msgstr "%s konnte von deinem System nicht aufgerufen werden. Dies deutet auf ein schwerwiegendes Problem deiner Konfiguration hin. Bitte konsultiere die Installations-Dokumentation zum Beheben des Problems." -#: src/Module/Admin/Summary.php:133 +#: src/Module/Admin/Summary.php:134 #, php-format msgid "" "Friendica's system.basepath was updated from '%s' to '%s'. Please remove the" " system.basepath from your db to avoid differences." msgstr "Friendica's system.basepath wurde aktualisiert '%s' von '%s'. Bitte entferne system.basepath aus der Datenbank um Unterschiede zu vermeiden." -#: src/Module/Admin/Summary.php:143 +#: src/Module/Admin/Summary.php:144 #, php-format msgid "" "Friendica's current system.basepath '%s' is wrong and the config file '%s' " "isn't used." msgstr "Friendica's aktueller system.basepath '%s' ist verkehrt und die config file '%s' wird nicht benutzt." -#: src/Module/Admin/Summary.php:153 +#: src/Module/Admin/Summary.php:154 #, php-format msgid "" "Friendica's current system.basepath '%s' is not equal to the config file " "'%s'. Please fix your configuration." msgstr "Friendica's aktueller system.basepath '%s' ist nicht gleich wie die config file '%s'. Bitte korrigiere deine Konfiguration." -#: src/Module/Admin/Summary.php:165 +#: src/Module/Admin/Summary.php:166 msgid "Message queues" msgstr "Nachrichten-Warteschlangen" -#: src/Module/Admin/Summary.php:168 +#: src/Module/Admin/Summary.php:169 msgid "Server Settings" msgstr "Servereinstellungen" -#: src/Module/Admin/Summary.php:186 +#: src/Module/Admin/Summary.php:210 msgid "Version" msgstr "Version" -#: src/Module/Admin/Summary.php:190 +#: src/Module/Admin/Summary.php:214 msgid "Active addons" msgstr "Aktivierte Addons" +#: src/Module/Admin/Summary.php:217 +msgid "Enable new addons" +msgstr "" + #: src/Module/Admin/Themes/Details.php:49 src/Module/Admin/Themes/Index.php:57 #, php-format msgid "Theme %s disabled." @@ -5958,7 +5972,7 @@ msgstr "Bildschirmfoto" #: src/Module/Admin/Themes/Details.php:83 #: src/Module/Admin/Themes/Index.php:104 src/Module/BaseAdmin.php:78 -#: src/Module/Settings/Display.php:396 +#: src/Module/Settings/Display.php:425 msgid "Themes" msgstr "Themen" @@ -6044,24 +6058,24 @@ msgstr "Fehlende Parameter" msgid "Only starting posts can be bookmarked" msgstr "Lesezeichen können nur für den ersten Beitrag einer Unterhaltung angelegt werden" -#: src/Module/Api/Mastodon/Statuses/Mute.php:37 +#: src/Module/Api/Mastodon/Statuses/Mute.php:36 msgid "Only starting posts can be muted" msgstr "Nur die ersten Beiträge von Unterhaltungen können stumm geschaltet werden" -#: src/Module/Api/Mastodon/Statuses/Reblog.php:44 +#: src/Module/Api/Mastodon/Statuses/Reblog.php:43 #, php-format msgid "Posts from %s can't be shared" msgstr "Beiträge von %s können nicht geteilt werden" -#: src/Module/Api/Mastodon/Statuses/Unbookmark.php:37 +#: src/Module/Api/Mastodon/Statuses/Unbookmark.php:36 msgid "Only starting posts can be unbookmarked" msgstr "Lesezeichen können nur für die ersten Beiträge einer Unterhaltung entfernt werden" -#: src/Module/Api/Mastodon/Statuses/Unmute.php:37 +#: src/Module/Api/Mastodon/Statuses/Unmute.php:36 msgid "Only starting posts can be unmuted" msgstr "Nur die ersten Beiträge einer Unterhaltung können wieder auf laut gestellt werden" -#: src/Module/Api/Mastodon/Statuses/Unreblog.php:50 +#: src/Module/Api/Mastodon/Statuses/Unreblog.php:49 #, php-format msgid "Posts from %s can't be unshared" msgstr "Beiträge von %s können nicht ungeteilt werden" @@ -6157,19 +6171,19 @@ msgstr "Addon Features" msgid "User registrations waiting for confirmation" msgstr "Nutzeranmeldungen, die auf Bestätigung warten" -#: src/Module/BaseApi.php:442 src/Module/BaseApi.php:458 -#: src/Module/BaseApi.php:474 +#: src/Module/BaseApi.php:431 src/Module/BaseApi.php:447 +#: src/Module/BaseApi.php:463 msgid "Too Many Requests" msgstr "Zu viele Abfragen" -#: src/Module/BaseApi.php:443 +#: src/Module/BaseApi.php:432 #, php-format msgid "Daily posting limit of %d post reached. The post was rejected." msgid_plural "Daily posting limit of %d posts reached. The post was rejected." msgstr[0] "Das tägliche Limit von %d Beitrag wurde erreicht. Die Nachricht wurde verworfen." msgstr[1] "Das tägliche Limit von %d Beiträgen wurde erreicht. Der Beitrag wurde verworfen." -#: src/Module/BaseApi.php:459 +#: src/Module/BaseApi.php:448 #, php-format msgid "Weekly posting limit of %d post reached. The post was rejected." msgid_plural "" @@ -6177,7 +6191,7 @@ msgid_plural "" msgstr[0] "Das wöchentliche Limit von %d Beitrag wurde erreicht. Die Nachricht wurde verworfen." msgstr[1] "Das wöchentliche Limit von %d Beiträgen wurde erreicht. Der Beitrag wurde verworfen." -#: src/Module/BaseApi.php:475 +#: src/Module/BaseApi.php:464 #, php-format msgid "Monthly posting limit of %d post reached. The post was rejected." msgid_plural "" @@ -6316,7 +6330,7 @@ msgstr "Remote Instanzen" #: src/Module/BaseSettings.php:155 #: src/Module/Moderation/Blocklist/Contact/Import.php:108 -#: src/Module/Settings/ContactImport.php:109 +#: src/Module/Settings/ContactImport.php:110 msgid "Import Contacts" msgstr "Kontakte Importieren" @@ -6384,7 +6398,7 @@ msgstr "Veranstaltungsbeginn:" #: src/Module/Moderation/Blocklist/Server/Index.php:105 #: src/Module/Moderation/Item/Delete.php:53 src/Module/Register.php:153 #: src/Module/Security/TwoFactor/Verify.php:87 -#: src/Module/Settings/Channels.php:176 src/Module/Settings/Channels.php:202 +#: src/Module/Settings/Channels.php:184 src/Module/Settings/Channels.php:210 #: src/Module/Settings/TwoFactor/Index.php:147 #: src/Module/Settings/TwoFactor/Verify.php:144 msgid "Required" @@ -6465,7 +6479,7 @@ msgstr "Ansehen" msgid "New Event" msgstr "Neue Veranstaltung" -#: src/Module/Calendar/Show.php:121 src/Module/Settings/Display.php:381 +#: src/Module/Calendar/Show.php:121 src/Module/Settings/Display.php:410 msgid "list" msgstr "Liste" @@ -6851,13 +6865,13 @@ msgstr "Adresse Deines Profils:" #: src/Module/Contact/Unfollow.php:115 #: src/Module/Moderation/Blocklist/Contact.php:122 #: src/Module/Moderation/Reports.php:117 -#: src/Module/Notifications/Introductions.php:121 -#: src/Module/Notifications/Introductions.php:192 +#: src/Module/Notifications/Introductions.php:125 +#: src/Module/Notifications/Introductions.php:198 msgid "Profile URL" msgstr "Profil URL" #: src/Module/Contact/Follow.php:156 src/Module/Contact/Profile.php:466 -#: src/Module/Notifications/Introductions.php:185 +#: src/Module/Notifications/Introductions.php:191 #: src/Module/Profile/Profile.php:248 msgid "Tags:" msgstr "Tags:" @@ -7072,7 +7086,7 @@ msgid "Manage remote servers" msgstr "Verwaltung entfernter Instanzen" #: src/Module/Contact/Profile.php:446 -#: src/Module/Notifications/Introductions.php:186 +#: src/Module/Notifications/Introductions.php:192 msgid "Hide this contact from others" msgstr "Verbirg diesen Kontakt vor Anderen" @@ -7292,11 +7306,11 @@ msgstr "Fehler %d (%s) beim Abruf der Timeline." msgid "Network feed not available." msgstr "Netzwerkfeed nicht verfügbar." -#: src/Module/Conversation/Timeline.php:194 +#: src/Module/Conversation/Timeline.php:192 msgid "Include" msgstr "Einschließen" -#: src/Module/Conversation/Timeline.php:195 +#: src/Module/Conversation/Timeline.php:193 msgid "Hide" msgstr "Verbergen" @@ -7478,7 +7492,7 @@ msgstr "Auf diesem Server werden die folgenden, entfernten Server blockiert." #: src/Module/Friendica.php:107 #: src/Module/Moderation/Blocklist/Server/Index.php:76 #: src/Module/Moderation/Blocklist/Server/Index.php:100 -#: src/Module/Settings/Channels.php:223 +#: src/Module/Settings/Channels.php:231 msgid "Reason for the block" msgstr "Begründung für die Blockierung" @@ -8320,7 +8334,7 @@ msgstr "Ersetzt die aktuelle Blockliste durch die importierten Muster." #: src/Module/Moderation/Blocklist/Server/Index.php:75 #: src/Module/Moderation/Blocklist/Server/Index.php:99 -#: src/Module/Settings/Channels.php:222 +#: src/Module/Settings/Channels.php:230 msgid "Blocked server domain pattern" msgstr "Blockierte Server Domain Muster" @@ -8703,6 +8717,10 @@ msgstr "Registrierte Personen" msgid "Pending registrations" msgstr "Anstehende Anmeldungen" +#: src/Module/Moderation/Summary.php:70 +msgid "Registered accounts by type" +msgstr "" + #: src/Module/Moderation/Users/Active.php:29 #: src/Module/Moderation/Users/Index.php:29 #, php-format @@ -8899,64 +8917,64 @@ msgstr "Hinweis vom Nutzer" msgid "Deny" msgstr "Verwehren" -#: src/Module/Notifications/Introductions.php:91 +#: src/Module/Notifications/Introductions.php:93 msgid "Show Ignored Requests" msgstr "Zeige ignorierte Anfragen" -#: src/Module/Notifications/Introductions.php:91 +#: src/Module/Notifications/Introductions.php:93 msgid "Hide Ignored Requests" msgstr "Verberge ignorierte Anfragen" -#: src/Module/Notifications/Introductions.php:107 -#: src/Module/Notifications/Introductions.php:172 +#: src/Module/Notifications/Introductions.php:111 +#: src/Module/Notifications/Introductions.php:178 msgid "Notification type:" msgstr "Art der Benachrichtigung:" -#: src/Module/Notifications/Introductions.php:110 +#: src/Module/Notifications/Introductions.php:114 msgid "Suggested by:" msgstr "Vorgeschlagen von:" -#: src/Module/Notifications/Introductions.php:127 -#: src/Module/Notifications/Introductions.php:164 +#: src/Module/Notifications/Introductions.php:131 +#: src/Module/Notifications/Introductions.php:168 #: src/Module/Post/Tag/Remove.php:95 #: src/Module/Settings/TwoFactor/Trusted.php:133 msgid "Remove" msgstr "Entfernen" -#: src/Module/Notifications/Introductions.php:135 +#: src/Module/Notifications/Introductions.php:139 msgid "Claims to be known to you: " msgstr "Behauptet, dich zu kennen: " -#: src/Module/Notifications/Introductions.php:144 +#: src/Module/Notifications/Introductions.php:148 #, php-format msgid "Accept %s as a friend or follower?" msgstr "Akzeptiere %s als Freund oder Folgenden? " -#: src/Module/Notifications/Introductions.php:145 +#: src/Module/Notifications/Introductions.php:149 msgid "Allows them to follow your posts." msgstr "Ermöglicht es ihnen, Ihren Beiträgen zu folgen." -#: src/Module/Notifications/Introductions.php:146 +#: src/Module/Notifications/Introductions.php:150 msgid "You will also follow them and receive their posts." msgstr "Sie werden ihnen ebenfalls folgen und ihre Beiträge erhalten." -#: src/Module/Notifications/Introductions.php:147 +#: src/Module/Notifications/Introductions.php:151 msgid "You won't follow them and won't receive their posts." msgstr "Sie werden ihnen nicht folgen und keine Beiträge von ihnen erhalten." -#: src/Module/Notifications/Introductions.php:149 +#: src/Module/Notifications/Introductions.php:153 msgid "Friend (Follow them back)" msgstr "Freund (Zurückfolgen)" -#: src/Module/Notifications/Introductions.php:150 +#: src/Module/Notifications/Introductions.php:154 msgid "Follower" msgstr "Folgende" -#: src/Module/Notifications/Introductions.php:198 +#: src/Module/Notifications/Introductions.php:204 msgid "Accept request" msgstr "Anfrage annehmen" -#: src/Module/Notifications/Introductions.php:210 +#: src/Module/Notifications/Introductions.php:216 #: src/Module/Notifications/Notifications.php:127 #, php-format msgid "No more %s notifications." @@ -8982,7 +9000,7 @@ msgstr "Persönliche Benachrichtigungen" msgid "Home Notifications" msgstr "Pinnwandbenachrichtigungen" -#: src/Module/Notifications/Notifications.php:132 +#: src/Module/Notifications/Notifications.php:134 msgid "Show unread" msgstr "Ungelesene anzeigen" @@ -9193,19 +9211,19 @@ msgid "No contacts." msgstr "Keine Kontakte." #: src/Module/Profile/Conversations.php:96 src/Module/Profile/Profile.php:366 -#: src/Protocol/Feed.php:1104 +#: src/Protocol/Feed.php:1105 #, php-format msgid "%s's posts" msgstr "Beiträge von %s" #: src/Module/Profile/Conversations.php:97 src/Module/Profile/Profile.php:367 -#: src/Protocol/Feed.php:1107 +#: src/Protocol/Feed.php:1108 #, php-format msgid "%s's comments" msgstr "Kommentare von %s" #: src/Module/Profile/Conversations.php:98 src/Module/Profile/Profile.php:368 -#: src/Protocol/Feed.php:1100 +#: src/Protocol/Feed.php:1101 #, php-format msgid "%s's timeline" msgstr "Timeline von %s" @@ -9385,7 +9403,7 @@ msgstr "Beitrag entfernen" msgid "Only parent users can create additional accounts." msgstr "Zusätzliche Nutzerkonten können nur von Verwaltern angelegt werden." -#: src/Module/Register.php:96 src/Module/User/Import.php:99 +#: src/Module/Register.php:96 src/Module/User/Import.php:100 msgid "" "This site has exceeded the number of allowed daily account registrations. " "Please try again tomorrow." @@ -9467,7 +9485,7 @@ msgstr "Wähle einen Spitznamen für dein Profil. Dieser muss mit einem Buchstab msgid "Choose a nickname: " msgstr "Spitznamen wählen: " -#: src/Module/Register.php:178 src/Module/User/Import.php:105 +#: src/Module/Register.php:178 src/Module/User/Import.php:106 msgid "Import" msgstr "Import" @@ -10265,70 +10283,70 @@ msgstr "Addon Einstellungen" msgid "None of the addons installed on this server have any settings." msgstr "Keines der auf diesem Server installierten Add-ons verfügt über Einstellungen." -#: src/Module/Settings/Channels.php:134 +#: src/Module/Settings/Channels.php:142 msgid "" "This page can be used to define the channels that will automatically be " "reshared by your account." msgstr "Diese Seite kann verwendet werden, um die Kanäle zu definieren, die automatisch von Deinem Konto geteilt werden." -#: src/Module/Settings/Channels.php:139 +#: src/Module/Settings/Channels.php:147 msgid "This page can be used to define your own channels." msgstr "Auf dieser Seite kannst du deine eigenen Kanäle definieren." -#: src/Module/Settings/Channels.php:168 +#: src/Module/Settings/Channels.php:176 msgid "Publish" msgstr "Veröffentlichen" -#: src/Module/Settings/Channels.php:168 +#: src/Module/Settings/Channels.php:176 msgid "" "When selected, the channel results are reshared. This only works for public " "ActivityPub posts from the public timeline or the user defined circles." msgstr "Wenn ausgewählt, werden die Kanalergebnisse erneut geteilt. Dies funktioniert nur für öffentliche ActivityPub-Beiträge aus der öffentlichen Timeline oder den vom Benutzer definierten Kreis." -#: src/Module/Settings/Channels.php:176 src/Module/Settings/Channels.php:202 -#: src/Module/Settings/Display.php:437 +#: src/Module/Settings/Channels.php:184 src/Module/Settings/Channels.php:210 +#: src/Module/Settings/Display.php:466 msgid "Label" msgstr "Bezeichnung" -#: src/Module/Settings/Channels.php:177 src/Module/Settings/Channels.php:203 -#: src/Module/Settings/Display.php:438 +#: src/Module/Settings/Channels.php:185 src/Module/Settings/Channels.php:211 +#: src/Module/Settings/Display.php:467 #: src/Module/Settings/TwoFactor/AppSpecific.php:123 msgid "Description" msgstr "Beschreibung" -#: src/Module/Settings/Channels.php:178 src/Module/Settings/Channels.php:204 +#: src/Module/Settings/Channels.php:186 src/Module/Settings/Channels.php:212 msgid "Access Key" msgstr "Zugriffsschlüssel" -#: src/Module/Settings/Channels.php:179 src/Module/Settings/Channels.php:205 +#: src/Module/Settings/Channels.php:187 src/Module/Settings/Channels.php:213 msgid "Circle/Channel" msgstr "Kreis/Kanal" -#: src/Module/Settings/Channels.php:180 src/Module/Settings/Channels.php:206 +#: src/Module/Settings/Channels.php:188 src/Module/Settings/Channels.php:214 msgid "Include Tags" msgstr "Tags einschließen" -#: src/Module/Settings/Channels.php:181 src/Module/Settings/Channels.php:207 +#: src/Module/Settings/Channels.php:189 src/Module/Settings/Channels.php:215 msgid "Exclude Tags" msgstr "Tags ausschließen" -#: src/Module/Settings/Channels.php:182 src/Module/Settings/Channels.php:208 +#: src/Module/Settings/Channels.php:190 src/Module/Settings/Channels.php:216 msgid "Minimum Size" msgstr "Mindestgröße" -#: src/Module/Settings/Channels.php:183 src/Module/Settings/Channels.php:209 +#: src/Module/Settings/Channels.php:191 src/Module/Settings/Channels.php:217 msgid "Maximum Size" msgstr "Maximale Größe" -#: src/Module/Settings/Channels.php:184 src/Module/Settings/Channels.php:210 +#: src/Module/Settings/Channels.php:192 src/Module/Settings/Channels.php:218 msgid "Full Text Search" msgstr "Volltextsuche" -#: src/Module/Settings/Channels.php:188 src/Module/Settings/Channels.php:214 +#: src/Module/Settings/Channels.php:196 src/Module/Settings/Channels.php:222 msgid "Languages" msgstr "Sprachen" -#: src/Module/Settings/Channels.php:188 +#: src/Module/Settings/Channels.php:196 msgid "" "Select all languages that you want to see in this channel. \"Unspecified\" " "describes all posts for which no language information was detected (e.g. " @@ -10337,63 +10355,63 @@ msgid "" "list." msgstr "Wählen Sie alle Sprachen aus, die Sie in diesem Kanal sehen möchten. „Unspecified“ beschreibt alle Beiträge, für die keine Sprachinformationen erkannt wurden (z. B. Beiträge, die nur ein Bild oder zu wenig Text enthalten, um die Sprache sicher zu bestimmen). Wenn Sie alle Sprachen sehen möchten, müssen Sie alle Elemente in der Liste auswählen." -#: src/Module/Settings/Channels.php:190 +#: src/Module/Settings/Channels.php:198 msgid "Delete channel" msgstr "Lösche Kanal" -#: src/Module/Settings/Channels.php:190 +#: src/Module/Settings/Channels.php:198 msgid "Check to delete this entry from the channel list" msgstr "Haken setzen, um diesen Eintrag aus der Kanalliste zu löschen" -#: src/Module/Settings/Channels.php:196 +#: src/Module/Settings/Channels.php:204 msgid "" "Comma separated list of tags. If a post contain any of these tags, then it " "will not be part of this channel." msgstr "Durch Kommas getrennte Liste von Tags. Wenn ein Beitrag eines dieser Tags enthält, wird er nicht in diesen Kanal aufgenommen." -#: src/Module/Settings/Channels.php:198 +#: src/Module/Settings/Channels.php:206 msgid "" "Comma separated list of tags. If a post contain any of these tags, then it " "will not be part of nthis channel." msgstr "Durch Kommata getrennte Liste von Tags. Wenn ein Beitrag eines dieser Tags enthält, wird er nicht Teil dieses Kanals sein." -#: src/Module/Settings/Channels.php:202 +#: src/Module/Settings/Channels.php:210 msgid "Short name for the channel. It is displayed on the channels widget." msgstr "Kurzname für den Kanal. Er wird im Widget für die Kanäle angezeigt." -#: src/Module/Settings/Channels.php:203 +#: src/Module/Settings/Channels.php:211 msgid "This should describe the content of the channel in a few word." msgstr "Dies sollte den Inhalt des Kanals in wenigen Worten beschreiben." -#: src/Module/Settings/Channels.php:204 +#: src/Module/Settings/Channels.php:212 msgid "" "When you want to access this channel via an access key, you can define it " "here. Pay attention to not use an already used one." msgstr "Wenn du auf diesen Kanal über einen Zugangsschlüssel zugreifen willst, kannst du ihn hier festlegen. Achte darauf, dass du nicht einen bereits verwendeten Schlüssel benutzt." -#: src/Module/Settings/Channels.php:205 +#: src/Module/Settings/Channels.php:213 msgid "Select a circle or channel, that your channel should be based on." msgstr "Wähle einen Kreis oder Kanal, auf dem Ihr Kanal basieren soll." -#: src/Module/Settings/Channels.php:206 +#: src/Module/Settings/Channels.php:214 msgid "" "Comma separated list of tags. A post will be used when it contains any of " "the listed tags." msgstr "Durch Kommata getrennte Liste von Tags. Ein Beitrag wird verwendet, wenn er eines der aufgeführten Tags enthält." -#: src/Module/Settings/Channels.php:208 +#: src/Module/Settings/Channels.php:216 msgid "" "Minimum post size. Leave empty for no minimum size. The size is calculated " "without links, attached posts, mentions or hashtags." msgstr "Mindestbeitragsgröße. Lass dieses Feld leer um die Mindestgröße nicht anzugeben. Die Größe wird ohne Links, angehängte Beiträge, Erwähnungen oder Hashtags berechnet." -#: src/Module/Settings/Channels.php:209 +#: src/Module/Settings/Channels.php:217 msgid "" "Maximum post size. Leave empty for no maximum size. The size is calculated " "without links, attached posts, mentions or hashtags." msgstr "Maximalbeitragsgröße. Lass dieses Feld leer um die Maximalgröße nicht anzugeben. Die Größe wird ohne Links, angehängte Beiträge, Erwähnungen oder Hashtags berechnet." -#: src/Module/Settings/Channels.php:210 +#: src/Module/Settings/Channels.php:218 #, php-format msgid "" "Search terms for the body, supports the \"boolean mode\" operators from " @@ -10401,39 +10419,39 @@ msgid "" "keywords: %s" msgstr "Suchbegriffe für den Body, unterstützt die \"boolean mode\"-Operatoren von MariaDB. In der Hilfe findest du eine vollständige Liste der Operatoren und zusätzliche Schlüsselwörter: %s" -#: src/Module/Settings/Channels.php:211 +#: src/Module/Settings/Channels.php:219 msgid "Check to display images in the channel." msgstr "Aktiviere diese Option, um Bilder im Kanal anzuzeigen." -#: src/Module/Settings/Channels.php:212 +#: src/Module/Settings/Channels.php:220 msgid "Check to display videos in the channel." msgstr "Aktiviere diese Option, um Videos im Kanal anzuzeigen." -#: src/Module/Settings/Channels.php:213 +#: src/Module/Settings/Channels.php:221 msgid "Check to display audio in the channel." msgstr "Aktiviere diese Option, um Audio im Kanal anzuzeigen." -#: src/Module/Settings/Channels.php:214 +#: src/Module/Settings/Channels.php:222 msgid "Select all languages that you want to see in this channel." msgstr "Wähle alle Sprachen aus, die du in diesem Kanal sehen willst." -#: src/Module/Settings/Channels.php:218 +#: src/Module/Settings/Channels.php:226 msgid "Add new entry to the channel list" msgstr "Neuen Eintrag zur Kanalliste hinzufügen" -#: src/Module/Settings/Channels.php:219 +#: src/Module/Settings/Channels.php:227 msgid "Add" msgstr "Hinzufügen" -#: src/Module/Settings/Channels.php:221 +#: src/Module/Settings/Channels.php:229 msgid "Current Entries in the channel list" msgstr "Aktuelle Einträge in der Kanalliste" -#: src/Module/Settings/Channels.php:224 +#: src/Module/Settings/Channels.php:232 msgid "Delete entry from the channel list" msgstr "Eintrag aus der Kanalliste löschen" -#: src/Module/Settings/Channels.php:225 +#: src/Module/Settings/Channels.php:233 msgid "Delete entry from the channel list?" msgstr "Eintrag aus der Kanalliste löschen?" @@ -10634,29 +10652,29 @@ msgstr "In einen Ordner verschieben" msgid "Move to folder:" msgstr "In diesen Ordner verschieben:" -#: src/Module/Settings/ContactImport.php:63 +#: src/Module/Settings/ContactImport.php:64 msgid "Contact CSV file upload error" msgstr "Fehler beim Hochladen der Kontakt CSV Datei" -#: src/Module/Settings/ContactImport.php:82 +#: src/Module/Settings/ContactImport.php:83 msgid "Importing Contacts done" msgstr "Kontakte wurden importiert." -#: src/Module/Settings/ContactImport.php:112 +#: src/Module/Settings/ContactImport.php:113 msgid "" "Upload a CSV file that contains the handle of your followed accounts in the " "first column you exported from the old account." msgstr "Lade eine CSV Datei hoch, die das Handle der Kontakte deines alten Nutzerkontos in der ersten Spalte enthält." -#: src/Module/Settings/ContactImport.php:113 +#: src/Module/Settings/ContactImport.php:114 msgid "Upload File" msgstr "Datei hochladen" -#: src/Module/Settings/ContactImport.php:115 +#: src/Module/Settings/ContactImport.php:116 msgid "Your legacy ActivityPub/GNU Social account" msgstr "Dein alter ActivityPub/GNU Social-Account" -#: src/Module/Settings/ContactImport.php:115 +#: src/Module/Settings/ContactImport.php:116 msgid "" "If you enter your old account name from an ActivityPub based system or your " "GNU Social/Statusnet account name here (in the format user@domain.tld), your" @@ -10737,233 +10755,233 @@ msgstr "Potentielle Bevollmächtigte" msgid "No entries." msgstr "Keine Einträge." -#: src/Module/Settings/Display.php:192 +#: src/Module/Settings/Display.php:200 msgid "The theme you chose isn't available." msgstr "Das gewählte Theme ist nicht verfügbar" -#: src/Module/Settings/Display.php:232 +#: src/Module/Settings/Display.php:240 #, php-format msgid "%s - (Unsupported)" msgstr "%s - (Nicht unterstützt)" -#: src/Module/Settings/Display.php:270 +#: src/Module/Settings/Display.php:278 msgid "Color/Black" msgstr "Farbe/Schwarz" -#: src/Module/Settings/Display.php:271 view/theme/frio/php/scheme.php:95 +#: src/Module/Settings/Display.php:279 view/theme/frio/php/scheme.php:95 msgid "Black" msgstr "Schwarz" -#: src/Module/Settings/Display.php:272 +#: src/Module/Settings/Display.php:280 msgid "Color/White" msgstr "Farbe/Weiß" -#: src/Module/Settings/Display.php:273 +#: src/Module/Settings/Display.php:281 msgid "White" msgstr "Weiß" -#: src/Module/Settings/Display.php:278 +#: src/Module/Settings/Display.php:286 msgid "No preview" msgstr "Keine Vorschau" -#: src/Module/Settings/Display.php:279 +#: src/Module/Settings/Display.php:287 msgid "No image" msgstr "Kein Bild" -#: src/Module/Settings/Display.php:280 +#: src/Module/Settings/Display.php:288 msgid "Small Image" msgstr "Kleines Bild" -#: src/Module/Settings/Display.php:281 +#: src/Module/Settings/Display.php:289 msgid "Large Image" msgstr "Große Bilder" -#: src/Module/Settings/Display.php:282 +#: src/Module/Settings/Display.php:290 msgid "Automatic image size" msgstr "Automatische Bildgröße" -#: src/Module/Settings/Display.php:392 +#: src/Module/Settings/Display.php:421 msgid "Display Settings" msgstr "Anzeige-Einstellungen" -#: src/Module/Settings/Display.php:394 +#: src/Module/Settings/Display.php:423 msgid "Content Settings" msgstr "Einstellungen zum Inhalt" -#: src/Module/Settings/Display.php:395 view/theme/duepuntozero/config.php:74 +#: src/Module/Settings/Display.php:424 view/theme/duepuntozero/config.php:74 #: view/theme/frio/config.php:159 view/theme/quattro/config.php:76 #: view/theme/vier/config.php:124 msgid "Theme settings" msgstr "Theme-Einstellungen" -#: src/Module/Settings/Display.php:397 +#: src/Module/Settings/Display.php:426 #, php-format msgid "Settings for %s" msgstr "Einstellungen für: %s" -#: src/Module/Settings/Display.php:398 +#: src/Module/Settings/Display.php:427 msgid "" "Note: If you switch the theme, you need to save changes before you can see " "the settings for the new theme below." msgstr "Hinweis: Wenn Sie das Design wechseln, müssen Sie die Änderungen speichern, bevor Sie die Einstellungen für das neue Design unten sehen können." -#: src/Module/Settings/Display.php:399 +#: src/Module/Settings/Display.php:428 msgid "Timelines" msgstr "Timelines" -#: src/Module/Settings/Display.php:402 src/Module/Settings/Features.php:83 +#: src/Module/Settings/Display.php:431 src/Module/Settings/Features.php:83 msgid "" "Drag to reorder or tab to item with keyboard and move up/down with arrow " "keys" msgstr "Ziehen Sie die Elemente mit der Tabulatortaste oder Maus zum jeweiligen Element, um sie nach oben/unten zu bewegen." -#: src/Module/Settings/Display.php:405 src/Module/Settings/Display.php:409 +#: src/Module/Settings/Display.php:434 src/Module/Settings/Display.php:438 #: src/Module/Settings/Features.php:87 msgid "Reset order" msgstr "Reihenfolge zurücksetzen" -#: src/Module/Settings/Display.php:415 +#: src/Module/Settings/Display.php:444 msgid "Display theme" msgstr "Anzeigethema" -#: src/Module/Settings/Display.php:416 +#: src/Module/Settings/Display.php:445 msgid "Mobile theme" msgstr "Mobiles Theme" -#: src/Module/Settings/Display.php:419 +#: src/Module/Settings/Display.php:448 msgid "Number of items to display per page:" msgstr "Zahl der Beiträge, die pro Netzwerkseite angezeigt werden sollen: " -#: src/Module/Settings/Display.php:419 src/Module/Settings/Display.php:420 +#: src/Module/Settings/Display.php:448 src/Module/Settings/Display.php:449 msgid "Maximum of 100 items" msgstr "Maximal 100 Beiträge" -#: src/Module/Settings/Display.php:420 +#: src/Module/Settings/Display.php:449 msgid "Number of items to display per page when viewed from mobile device:" msgstr "Zahl der Beiträge, die pro Netzwerkseite auf mobilen Geräten angezeigt werden sollen:" -#: src/Module/Settings/Display.php:421 +#: src/Module/Settings/Display.php:450 msgid "Regularly update the page content" msgstr "Den Seiteninhalt regelmäßig aktualisieren" -#: src/Module/Settings/Display.php:421 +#: src/Module/Settings/Display.php:450 msgid "" "When enabled, new content on network, community and channels are added on " "top." msgstr "Wenn diese Option aktiviert ist, werden neue Inhalte aus dem Netzwerk, der Community und den Kanälen oben hinzugefügt." -#: src/Module/Settings/Display.php:422 +#: src/Module/Settings/Display.php:451 msgid "Display emoticons" msgstr "Zeige Emoticons" -#: src/Module/Settings/Display.php:422 +#: src/Module/Settings/Display.php:451 msgid "When enabled, emoticons are replaced with matching symbols." msgstr "Wenn dies aktiviert ist, werden Text-Emoticons in Beiträgen durch Symbole ersetzt." -#: src/Module/Settings/Display.php:423 +#: src/Module/Settings/Display.php:452 msgid "Infinite scroll" msgstr "Endloses Scrollen" -#: src/Module/Settings/Display.php:423 +#: src/Module/Settings/Display.php:452 msgid "Automatic fetch new items when reaching the page end." msgstr "Automatisch neue Beiträge laden, wenn das Ende der Seite erreicht ist." -#: src/Module/Settings/Display.php:424 +#: src/Module/Settings/Display.php:453 msgid "Enable Smart Threading" msgstr "Intelligentes Threading aktivieren" -#: src/Module/Settings/Display.php:424 +#: src/Module/Settings/Display.php:453 msgid "Enable the automatic suppression of extraneous thread indentation." msgstr "Schaltet das automatische Unterdrücken von überflüssigen Thread-Einrückungen ein." -#: src/Module/Settings/Display.php:425 +#: src/Module/Settings/Display.php:454 msgid "Display the Dislike feature" msgstr "Das \"Nicht-mögen\" Feature anzeigen" -#: src/Module/Settings/Display.php:425 +#: src/Module/Settings/Display.php:454 msgid "" "Display the Dislike button and dislike reactions on posts and comments." msgstr "Einen \"Ich mag das nicht\" Button und die dislike Reaktion auf Beiträge und Kommentare anzeigen." -#: src/Module/Settings/Display.php:426 +#: src/Module/Settings/Display.php:455 msgid "Display the resharer" msgstr "Teilenden anzeigen" -#: src/Module/Settings/Display.php:426 +#: src/Module/Settings/Display.php:455 msgid "Display the first resharer as icon and text on a reshared item." msgstr "Zeige das Profilbild des ersten Kontakts von dem ein Beitrag geteilt wurde." -#: src/Module/Settings/Display.php:427 +#: src/Module/Settings/Display.php:456 msgid "Stay local" msgstr "Bleib lokal" -#: src/Module/Settings/Display.php:427 +#: src/Module/Settings/Display.php:456 msgid "Don't go to a remote system when following a contact link." msgstr "Gehe nicht zu einem Remote-System, wenn einem Kontaktlink gefolgt wird" -#: src/Module/Settings/Display.php:428 +#: src/Module/Settings/Display.php:457 msgid "Show the post deletion checkbox" msgstr "Die Checkbox zum Löschen von Beiträgen anzeigen" -#: src/Module/Settings/Display.php:428 +#: src/Module/Settings/Display.php:457 msgid "Display the checkbox for the post deletion on the network page." msgstr "Zeigt die Checkbox für das Löschen von Beiträgen auf der Netzwerkseite an." -#: src/Module/Settings/Display.php:429 +#: src/Module/Settings/Display.php:458 msgid "DIsplay the event list" msgstr "Anzeige der der anstehenden Ereignisse" -#: src/Module/Settings/Display.php:429 +#: src/Module/Settings/Display.php:458 msgid "Display the birthday reminder and event list on the network page." msgstr "Zeigt die Geburtstagserinnerungen und die anstehenden Veranstaltungen auf der Netzwerkseite an." -#: src/Module/Settings/Display.php:430 +#: src/Module/Settings/Display.php:459 msgid "Link preview mode" msgstr "Vorschau Modus für Links" -#: src/Module/Settings/Display.php:430 +#: src/Module/Settings/Display.php:459 msgid "Appearance of the link preview that is added to each post with a link." msgstr "Aussehen der Linkvorschau, die zu jedem Beitrag mit einem Link hinzugefügt wird." -#: src/Module/Settings/Display.php:431 +#: src/Module/Settings/Display.php:460 msgid "Hide pictures with empty alternative text" msgstr "Bilder ohne Alternativtext verbergen" -#: src/Module/Settings/Display.php:431 +#: src/Module/Settings/Display.php:460 msgid "Don't display pictures that are missing the alternative text." msgstr "Bilder die keinen beschreibenden Alternativtext besitzen werden nicht angezeigt." -#: src/Module/Settings/Display.php:432 +#: src/Module/Settings/Display.php:461 msgid "Hide custom emojis" msgstr "Benutzerdefinierte Emojis ausblenden" -#: src/Module/Settings/Display.php:432 +#: src/Module/Settings/Display.php:461 msgid "Don't display custom emojis." msgstr "Benutzerdefinierte Emojis werden nicht angezeigt." -#: src/Module/Settings/Display.php:433 +#: src/Module/Settings/Display.php:462 msgid "Platform icons style" msgstr "Stil der Plattform-Icons" -#: src/Module/Settings/Display.php:433 +#: src/Module/Settings/Display.php:462 msgid "Style of the platform icons" msgstr "Stil der verwendeten Plattform-Icons" -#: src/Module/Settings/Display.php:434 +#: src/Module/Settings/Display.php:463 msgid "Embed remote media" msgstr "Einbettete Remote-Medien" -#: src/Module/Settings/Display.php:434 +#: src/Module/Settings/Display.php:463 msgid "" "When enabled, remote media will be embedded in the post, like for example " "YouTube videos." msgstr "Wenn diese Option aktiviert ist, werden Remote-Medien in den Beitrag eingebettet, wie beispielsweise YouTube-Videos." -#: src/Module/Settings/Display.php:435 +#: src/Module/Settings/Display.php:464 msgid "Embed supported media" msgstr "Unterstützte einbettete Medien" -#: src/Module/Settings/Display.php:435 +#: src/Module/Settings/Display.php:464 msgid "" "When enabled, remote media will be embedded in the post instead of using the" " local player if this is supported by the remote system. This is useful for " @@ -10971,25 +10989,25 @@ msgid "" " Peertube videos." msgstr "Wenn diese Option aktiviert ist, werden Remote-Medien in den Beitrag eingebettet, anstatt den lokalen Player zu verwenden, sofern dies vom Remote-System unterstützt wird. Dies ist nützlich für Medien, bei denen der Remote-Player besser ist als der lokale, wie beispielsweise Peertube-Videos." -#: src/Module/Settings/Display.php:439 +#: src/Module/Settings/Display.php:468 msgid "Channels Widget" msgstr "Kanäle-Widget" -#: src/Module/Settings/Display.php:440 +#: src/Module/Settings/Display.php:469 msgid "Top Menu" msgstr "Hauptmenü" -#: src/Module/Settings/Display.php:442 +#: src/Module/Settings/Display.php:471 msgid "" "Enable timelines that you want to see in the channels widget. Bookmark " "timelines that you want to see in the top menu." msgstr "Aktiviere die Timelines, die Sie im Kanäle-Widget sehen möchten. Setze ein Lesezeichen für Timelines, die du im oberen Menü sehen willst." -#: src/Module/Settings/Display.php:444 +#: src/Module/Settings/Display.php:473 msgid "Channel languages:" msgstr "Kanal Sprachen:" -#: src/Module/Settings/Display.php:444 +#: src/Module/Settings/Display.php:473 msgid "" "Select all the languages you want to see in your channels. \"Unspecified\" " "describes all posts for which no language information was detected (e.g. " @@ -10998,11 +11016,31 @@ msgid "" "list." msgstr "Wählen Sie alle Sprachen aus, die Sie in Ihren Kanälen sehen möchten. „Unspecified“ beschreibt alle Beiträge, für die keine Sprachinformationen erkannt wurden (z. B. Beiträge, die nur ein Bild oder zu wenig Text enthalten, um die Sprache sicher zu bestimmen). Wenn Sie alle Sprachen sehen möchten, müssen Sie alle Elemente in der Liste auswählen." -#: src/Module/Settings/Display.php:446 +#: src/Module/Settings/Display.php:474 +msgid "Timeline channels:" +msgstr "" + +#: src/Module/Settings/Display.php:474 +msgid "Select all the channels that you want to see in your network timeline." +msgstr "" + +#: src/Module/Settings/Display.php:476 +msgid "Filter channels:" +msgstr "" + +#: src/Module/Settings/Display.php:476 +#, php-format +msgid "" +"Select all the channels that you want to use as a filter for your network " +"timeline. All posts from these channels will be hidden. For technical " +"reasons postings that are older than %s will not be filtered." +msgstr "" + +#: src/Module/Settings/Display.php:479 msgid "Beginning of week:" msgstr "Wochenbeginn:" -#: src/Module/Settings/Display.php:447 +#: src/Module/Settings/Display.php:480 msgid "Default calendar view:" msgstr "Standard-Kalenderansicht:" @@ -11782,74 +11820,74 @@ msgstr "Zwischen verschiedenen Identitäten oder Gemeinschafts-/Gruppenseiten we msgid "Select an identity to manage: " msgstr "Wähle eine Identität zum Verwalten aus: " -#: src/Module/User/Import.php:91 +#: src/Module/User/Import.php:92 msgid "User imports on closed servers can only be done by an administrator." msgstr "Auf geschlossenen Servern können ausschließlich die Administratoren:innen Benutzerkonten importieren." -#: src/Module/User/Import.php:107 +#: src/Module/User/Import.php:108 msgid "Move account" msgstr "Account umziehen" -#: src/Module/User/Import.php:108 +#: src/Module/User/Import.php:109 msgid "You can import an account from another Friendica server." msgstr "Du kannst einen Account von einem anderen Friendica Server importieren." -#: src/Module/User/Import.php:109 +#: src/Module/User/Import.php:110 msgid "" "You need to export your account from the old server and upload it here. We " "will recreate your old account here with all your contacts. We will try also" " to inform your friends that you moved here." msgstr "Du musst deinen Account vom alten Server exportieren und hier hochladen. Wir stellen deinen alten Account mit all deinen Kontakten wieder her. Wir werden auch versuchen, deine Kontakte darüber zu informieren, dass du hierher umgezogen bist." -#: src/Module/User/Import.php:110 +#: src/Module/User/Import.php:111 msgid "" "This feature is experimental. We can't import contacts from the OStatus " "network (GNU Social/Statusnet) or from Diaspora" msgstr "Dieses Feature ist experimentell. Wir können keine Kontakte vom OStatus-Netzwerk (GNU Social/Statusnet) oder von Diaspora importieren" -#: src/Module/User/Import.php:111 +#: src/Module/User/Import.php:112 msgid "Account file" msgstr "Account-Datei" -#: src/Module/User/Import.php:111 +#: src/Module/User/Import.php:112 msgid "" "To export your account, go to \"Settings->Export your personal data\" and " "select \"Export account\"" msgstr "Um Deinen Account zu exportieren, rufe \"Einstellungen -> Persönliche Daten exportieren\" auf und wähle \"Account exportieren\"" -#: src/Module/User/Import.php:206 +#: src/Module/User/Import.php:207 msgid "Account file size is too high" msgstr "Die Dateigröße des Kontos ist zu groß." -#: src/Module/User/Import.php:212 +#: src/Module/User/Import.php:213 msgid "Error decoding account file" msgstr "Fehler beim Verarbeiten der Account-Datei" -#: src/Module/User/Import.php:217 +#: src/Module/User/Import.php:218 msgid "Error! No version data in file! This is not a Friendica account file?" msgstr "Fehler! Keine Versionsdaten in der Datei! Ist das wirklich eine Friendica-Account-Datei?" -#: src/Module/User/Import.php:225 +#: src/Module/User/Import.php:226 #, php-format msgid "User '%s' already exists on this server!" msgstr "Nutzer '%s' existiert bereits auf diesem Server!" -#: src/Module/User/Import.php:267 +#: src/Module/User/Import.php:268 msgid "User creation error" msgstr "Fehler beim Anlegen des Nutzer-Accounts aufgetreten" -#: src/Module/User/Import.php:316 +#: src/Module/User/Import.php:317 #, php-format msgid "%d contact not imported" msgid_plural "%d contacts not imported" msgstr[0] "%d Kontakt nicht importiert" msgstr[1] "%d Kontakte nicht importiert" -#: src/Module/User/Import.php:365 +#: src/Module/User/Import.php:366 msgid "User profile creation error" msgstr "Fehler beim Anlegen des Nutzer-Profils" -#: src/Module/User/Import.php:416 +#: src/Module/User/Import.php:425 msgid "Done. You can now login with your username and password" msgstr "Erledigt. Du kannst dich jetzt mit deinem Nutzernamen und Passwort anmelden" @@ -12309,7 +12347,7 @@ msgstr "Bitte besuche %s, um die Kontaktanfrage anzunehmen oder abzulehnen." #: src/Navigation/Notifications/Repository/Notify.php:386 #, php-format msgid "%s You have a new friend" -msgstr "%sDu hast einen neuen Kontakt" +msgstr "%s Du hast einen neuen Kontakt" #: src/Navigation/Notifications/Repository/Notify.php:388 #: src/Navigation/Notifications/Repository/Notify.php:390 @@ -12320,7 +12358,7 @@ msgstr "%1$s ist dein Freund bei %2$s" #: src/Navigation/Notifications/Repository/Notify.php:397 #, php-format msgid "%s You have a new follower" -msgstr "%sDu hast einen neuen Kontakt" +msgstr "%s Du hast einen neuen Kontakt" #: src/Navigation/Notifications/Repository/Notify.php:399 #: src/Navigation/Notifications/Repository/Notify.php:401 diff --git a/view/lang/de/strings.php b/view/lang/de/strings.php index 6e2b681d6c..c786d9d2ee 100644 --- a/view/lang/de/strings.php +++ b/view/lang/de/strings.php @@ -3012,9 +3012,9 @@ $a->strings['You\'ve received an introduction from \'%1$s\' at %2$s'] = 'Du hast $a->strings['You\'ve received [url=%1$s]an introduction[/url] from %2$s.'] = 'Du hast eine [url=%1$s]Kontaktanfrage[/url] von %2$s erhalten.'; $a->strings['You may visit their profile at %s'] = 'Hier kannst du das Profil betrachten: %s'; $a->strings['Please visit %s to approve or reject the introduction.'] = 'Bitte besuche %s, um die Kontaktanfrage anzunehmen oder abzulehnen.'; -$a->strings['%s You have a new friend'] = '%sDu hast einen neuen Kontakt'; +$a->strings['%s You have a new friend'] = '%s Du hast einen neuen Kontakt'; $a->strings['%1$s is your friend at %2$s'] = '%1$s ist dein Freund bei %2$s'; -$a->strings['%s You have a new follower'] = '%sDu hast einen neuen Kontakt'; +$a->strings['%s You have a new follower'] = '%s Du hast einen neuen Kontakt'; $a->strings['You have a new follower at %2$s : %1$s'] = 'Du hast einen neuen Kontakt auf %2$s: %1$s'; $a->strings['%s Friend suggestion received'] = '%sKontaktvorschlag erhalten'; $a->strings['You\'ve received a friend suggestion from \'%1$s\' at %2$s'] = 'Du hast einen Kontakt-Vorschlag von \'%1$s\' auf %2$s erhalten'; From 270a9a7c7ab0326466727b856e602ee956850fce Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Wed, 4 Feb 2026 11:44:32 +0100 Subject: [PATCH 031/197] update DE translation fix missing space that @annando discovered --- view/lang/de/messages.po | 20 ++++++++++---------- view/lang/de/strings.php | 11 ++++++++++- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/view/lang/de/messages.po b/view/lang/de/messages.po index e4ccacabe7..bb05dd5124 100644 --- a/view/lang/de/messages.po +++ b/view/lang/de/messages.po @@ -1553,12 +1553,12 @@ msgstr "Zu uns gepusht" #: src/Content/Conversation.php:816 #, php-format msgid "Channel \"%s\": %s" -msgstr "" +msgstr "Kanal \"%s\": %s" #: src/Content/Conversation.php:818 #, php-format msgid "Channel \"%s\"" -msgstr "" +msgstr "Kanal \"%s\"" #: src/Content/Conversation.php:1553 src/Object/Post.php:250 msgid "Pinned item" @@ -3566,7 +3566,7 @@ msgstr "H:i" #: src/Model/Event.php:889 msgid "e" -msgstr "" +msgstr "e" #: src/Model/Event.php:954 src/Model/Event.php:956 msgid "Show map" @@ -5949,7 +5949,7 @@ msgstr "Aktivierte Addons" #: src/Module/Admin/Summary.php:217 msgid "Enable new addons" -msgstr "" +msgstr "Neue Addons aktivieren" #: src/Module/Admin/Themes/Details.php:49 src/Module/Admin/Themes/Index.php:57 #, php-format @@ -8719,7 +8719,7 @@ msgstr "Anstehende Anmeldungen" #: src/Module/Moderation/Summary.php:70 msgid "Registered accounts by type" -msgstr "" +msgstr "Registrierte Accounts nach Kontoart" #: src/Module/Moderation/Users/Active.php:29 #: src/Module/Moderation/Users/Index.php:29 @@ -11018,15 +11018,15 @@ msgstr "Wählen Sie alle Sprachen aus, die Sie in Ihren Kanälen sehen möchten. #: src/Module/Settings/Display.php:474 msgid "Timeline channels:" -msgstr "" +msgstr "Timeline Kanäle:" #: src/Module/Settings/Display.php:474 msgid "Select all the channels that you want to see in your network timeline." -msgstr "" +msgstr "Wähle alle Kanäle aus, die du in deinem Netzwerk Reiter sehen willst." #: src/Module/Settings/Display.php:476 msgid "Filter channels:" -msgstr "" +msgstr "Filter Kanäle" #: src/Module/Settings/Display.php:476 #, php-format @@ -11034,7 +11034,7 @@ msgid "" "Select all the channels that you want to use as a filter for your network " "timeline. All posts from these channels will be hidden. For technical " "reasons postings that are older than %s will not be filtered." -msgstr "" +msgstr "Wähle die Kanäle, die du als Filter für die Netzwerk Timeline verwenden willst. Die Beiträge in diesen Kanälen werden nicht angezeigt. Aus technischen Gründen werden Beiträge älter als %s nicht gefiltert." #: src/Module/Settings/Display.php:479 msgid "Beginning of week:" @@ -12369,7 +12369,7 @@ msgstr "Du hast einen neuen Kontakt auf %2$s: %1$s" #: src/Navigation/Notifications/Repository/Notify.php:414 #, php-format msgid "%s Friend suggestion received" -msgstr "%sKontaktvorschlag erhalten" +msgstr "%s Kontaktvorschlag erhalten" #: src/Navigation/Notifications/Repository/Notify.php:416 #, php-format diff --git a/view/lang/de/strings.php b/view/lang/de/strings.php index c786d9d2ee..5dd34b4e16 100644 --- a/view/lang/de/strings.php +++ b/view/lang/de/strings.php @@ -412,6 +412,8 @@ $a->strings['Local delivery'] = 'Lokale Zustellung'; $a->strings['Stored because of your activity (like, comment, star, ...)'] = 'Gespeichert aufgrund Ihrer Aktivität (Like, Kommentar, Stern, ...)'; $a->strings['Distributed'] = 'Verteilt'; $a->strings['Pushed to us'] = 'Zu uns gepusht'; +$a->strings['Channel "%s": %s'] = 'Kanal "%s": %s'; +$a->strings['Channel "%s"'] = 'Kanal "%s"'; $a->strings['Pinned item'] = 'Angehefteter Beitrag'; $a->strings['View %s\'s profile @ %s'] = 'Das Profil von %s auf %s betrachten.'; $a->strings['Categories:'] = 'Kategorien:'; @@ -877,6 +879,7 @@ $a->strings['Delete event'] = 'Veranstaltung löschen'; $a->strings['l F d, Y \@ g:i A'] = 'l, d. F Y\, H:i'; $a->strings['D g:i A'] = 'D H:i'; $a->strings['g:i A'] = 'H:i'; +$a->strings['e'] = 'e'; $a->strings['Show map'] = 'Karte anzeigen'; $a->strings['Hide map'] = 'Karte verbergen'; $a->strings['%s\'s birthday'] = '%ss Geburtstag'; @@ -1527,6 +1530,7 @@ $a->strings['Message queues'] = 'Nachrichten-Warteschlangen'; $a->strings['Server Settings'] = 'Servereinstellungen'; $a->strings['Version'] = 'Version'; $a->strings['Active addons'] = 'Aktivierte Addons'; +$a->strings['Enable new addons'] = 'Neue Addons aktivieren'; $a->strings['Theme %s disabled.'] = 'Theme %s deaktiviert.'; $a->strings['Theme %s successfully enabled.'] = 'Theme %s erfolgreich aktiviert.'; $a->strings['Theme %s failed to install.'] = 'Theme %s konnte nicht aktiviert werden.'; @@ -2187,6 +2191,7 @@ $a->strings['URL of the reported contact.'] = 'URL des gemeldeten Kontakts.'; $a->strings['Channel Relay'] = 'Kanalrelais'; $a->strings['Registered users'] = 'Registrierte Personen'; $a->strings['Pending registrations'] = 'Anstehende Anmeldungen'; +$a->strings['Registered accounts by type'] = 'Registrierte Accounts nach Kontoart'; $a->strings['%s user blocked'] = [ 0 => '%s Nutzer blockiert', 1 => '%s Nutzer blockiert', @@ -2704,6 +2709,10 @@ $a->strings['Top Menu'] = 'Hauptmenü'; $a->strings['Enable timelines that you want to see in the channels widget. Bookmark timelines that you want to see in the top menu.'] = 'Aktiviere die Timelines, die Sie im Kanäle-Widget sehen möchten. Setze ein Lesezeichen für Timelines, die du im oberen Menü sehen willst.'; $a->strings['Channel languages:'] = 'Kanal Sprachen:'; $a->strings['Select all the languages you want to see in your channels. "Unspecified" describes all posts for which no language information was detected (e.g. posts with just an image or too little text to be sure of the language). If you want to see all languages, you will need to select all items in the list.'] = 'Wählen Sie alle Sprachen aus, die Sie in Ihren Kanälen sehen möchten. „Unspecified“ beschreibt alle Beiträge, für die keine Sprachinformationen erkannt wurden (z. B. Beiträge, die nur ein Bild oder zu wenig Text enthalten, um die Sprache sicher zu bestimmen). Wenn Sie alle Sprachen sehen möchten, müssen Sie alle Elemente in der Liste auswählen.'; +$a->strings['Timeline channels:'] = 'Timeline Kanäle:'; +$a->strings['Select all the channels that you want to see in your network timeline.'] = 'Wähle alle Kanäle aus, die du in deinem Netzwerk Reiter sehen willst.'; +$a->strings['Filter channels:'] = 'Filter Kanäle'; +$a->strings['Select all the channels that you want to use as a filter for your network timeline. All posts from these channels will be hidden. For technical reasons postings that are older than %s will not be filtered.'] = 'Wähle die Kanäle, die du als Filter für die Netzwerk Timeline verwenden willst. Die Beiträge in diesen Kanälen werden nicht angezeigt. Aus technischen Gründen werden Beiträge älter als %s nicht gefiltert.'; $a->strings['Beginning of week:'] = 'Wochenbeginn:'; $a->strings['Default calendar view:'] = 'Standard-Kalenderansicht:'; $a->strings['Additional Features'] = 'Zusätzliche Features'; @@ -3016,7 +3025,7 @@ $a->strings['%s You have a new friend'] = '%s Du hast einen neuen Kontakt'; $a->strings['%1$s is your friend at %2$s'] = '%1$s ist dein Freund bei %2$s'; $a->strings['%s You have a new follower'] = '%s Du hast einen neuen Kontakt'; $a->strings['You have a new follower at %2$s : %1$s'] = 'Du hast einen neuen Kontakt auf %2$s: %1$s'; -$a->strings['%s Friend suggestion received'] = '%sKontaktvorschlag erhalten'; +$a->strings['%s Friend suggestion received'] = '%s Kontaktvorschlag erhalten'; $a->strings['You\'ve received a friend suggestion from \'%1$s\' at %2$s'] = 'Du hast einen Kontakt-Vorschlag von \'%1$s\' auf %2$s erhalten'; $a->strings['You\'ve received [url=%1$s]a friend suggestion[/url] for %2$s from %3$s.'] = 'Du hast einen [url=%1$s]Kontakt-Vorschlag[/url] %2$s von %3$s erhalten.'; $a->strings['Name:'] = 'Name:'; From 489ebb257efe213676e2d4f2a7377fc35514853d Mon Sep 17 00:00:00 2001 From: loma-one <44441246+loma-one@users.noreply.github.com> Date: Wed, 4 Feb 2026 16:40:57 +0100 Subject: [PATCH 032/197] Remove unnecessary placeholder in compose template Remove unnecessary placeholder in compose template --- view/templates/item/compose.tpl | 1 - 1 file changed, 1 deletion(-) diff --git a/view/templates/item/compose.tpl b/view/templates/item/compose.tpl index 89bae5aa6e..f5eaf5036b 100644 --- a/view/templates/item/compose.tpl +++ b/view/templates/item/compose.tpl @@ -11,7 +11,6 @@ {{/if}}
    - {{**}} From 540e046cd94125b310c9ee4d036e1661d8d553fa Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 4 Feb 2026 15:57:30 +0000 Subject: [PATCH 033/197] Fixes: Undefined array key "filter_channels" --- src/Module/Settings/Display.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Module/Settings/Display.php b/src/Module/Settings/Display.php index 1637d185d5..9f6e757131 100644 --- a/src/Module/Settings/Display.php +++ b/src/Module/Settings/Display.php @@ -95,8 +95,8 @@ class Display extends BaseSettings $enable = (array)$request['enable']; $bookmark = (array)$request['bookmark']; $channel_languages = (array)$request['channel_languages']; - $timeline_channels = (array)$request['timeline_channels']; - $filter_channels = (array)$request['filter_channels']; + $timeline_channels = isset($request['timeline_channels']) ? (array)$request['timeline_channels'] : null; + $filter_channels = isset($request['filter_channels']) ? (array)$request['filter_channels'] : null; $first_day_of_week = (int)$request['first_day_of_week']; $calendar_default_view = trim($request['calendar_default_view']); $infinite_scroll = (bool)$request['infinite_scroll']; @@ -176,8 +176,13 @@ class Display extends BaseSettings $this->pConfig->set($uid, 'system', 'network_timelines', $network_timelines); $this->pConfig->set($uid, 'system', 'enabled_timelines', $enabled_timelines); $this->pConfig->set($uid, 'channel', 'languages', $channel_languages); - $this->pConfig->set($uid, 'channel', 'timeline_channels', $timeline_channels); - $this->pConfig->set($uid, 'channel', 'filter_channels', $filter_channels); + + if (!is_null($timeline_channels)) { + $this->pConfig->set($uid, 'channel', 'timeline_channels', $timeline_channels); + } + if (!is_null($filter_channels)) { + $this->pConfig->set($uid, 'channel', 'filter_channels', $filter_channels); + } $this->pConfig->set($uid, 'accessibility', 'hide_empty_descriptions', $hide_empty_descriptions); $this->pConfig->set($uid, 'accessibility', 'hide_custom_emojis', $hide_custom_emojis); From c74180b96aa023bdb6d9ab796fed337e02cf4594 Mon Sep 17 00:00:00 2001 From: Sean Rhone Date: Wed, 4 Feb 2026 22:05:48 -0500 Subject: [PATCH 034/197] Update console.php (minor typo) - Shortened a tiny bit too --- bin/console.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/console.php b/bin/console.php index 88382e1665..39d93f3cbe 100755 --- a/bin/console.php +++ b/bin/console.php @@ -13,7 +13,7 @@ if (php_sapi_name() !== 'cli') { exit(); } -// Ensure that te console is executed from the base path of the installation +// Ensure the console is executed from the base path of the installation chdir(dirname(__DIR__)); require dirname(__DIR__) . '/vendor/autoload.php'; From 4218af5a1e9a36c9f6c087299d32149b9915e9d8 Mon Sep 17 00:00:00 2001 From: Sean Rhone Date: Wed, 4 Feb 2026 22:09:55 -0500 Subject: [PATCH 035/197] Update console.php - Even shorter (script itself is named console) --- bin/console.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/console.php b/bin/console.php index 39d93f3cbe..a4cc9e2ae6 100755 --- a/bin/console.php +++ b/bin/console.php @@ -13,7 +13,7 @@ if (php_sapi_name() !== 'cli') { exit(); } -// Ensure the console is executed from the base path of the installation +// Ensure console is executed from the base path of the installation chdir(dirname(__DIR__)); require dirname(__DIR__) . '/vendor/autoload.php'; From b99652d8c5394c086767259765b650fa62a7aa79 Mon Sep 17 00:00:00 2001 From: Marcus Funch Date: Sun, 4 Jan 2026 18:59:50 +0100 Subject: [PATCH 036/197] Add current page highlighting to frio, fix related logic --- src/Module/Calendar/Show.php | 5 ++++- src/Module/Contact.php | 2 +- src/Module/Contact/Conversations.php | 2 +- src/Module/Contact/Posts.php | 2 +- src/Module/Contact/Profile.php | 2 +- src/Module/Contact/Revoke.php | 2 +- view/theme/frio/css/style.css | 10 ++++++++++ view/theme/frio/templates/nav.tpl | 4 ++-- 8 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/Module/Calendar/Show.php b/src/Module/Calendar/Show.php index 7615426673..f5eb962607 100644 --- a/src/Module/Calendar/Show.php +++ b/src/Module/Calendar/Show.php @@ -90,7 +90,10 @@ class Show extends BaseModule '$i18n' => $i18n, ]); - Nav::setSelected($is_owner ? 'home' : 'calendar'); + // Only highlight the calendar link if you're on your own calendar + if ($is_owner) { + Nav::setSelected('calendar'); + } if ($is_owner) { // Removing the vCard added by Profile::load for owners diff --git a/src/Module/Contact.php b/src/Module/Contact.php index ac26295189..13baa3bb30 100644 --- a/src/Module/Contact.php +++ b/src/Module/Contact.php @@ -204,7 +204,7 @@ class Contact extends BaseModule DI::page()['htmlhead'] .= Renderer::replaceMacros($tpl, []); $o = ''; - Nav::setSelected('contact'); + Nav::setSelected('contacts'); $_SESSION['return_path'] = DI::args()->getQueryString(); diff --git a/src/Module/Contact/Conversations.php b/src/Module/Contact/Conversations.php index 28017f279c..4d10935303 100644 --- a/src/Module/Contact/Conversations.php +++ b/src/Module/Contact/Conversations.php @@ -96,7 +96,7 @@ class Conversations extends BaseModule $this->page['aside'] .= VCard::getHTML($contact, true); - Nav::setSelected('contact'); + Nav::setSelected('contacts'); $output = ''; diff --git a/src/Module/Contact/Posts.php b/src/Module/Contact/Posts.php index 26b855e670..2445b3b930 100644 --- a/src/Module/Contact/Posts.php +++ b/src/Module/Contact/Posts.php @@ -81,7 +81,7 @@ class Posts extends BaseModule $this->page['aside'] .= Widget\VCard::getHTML($contact); - Nav::setSelected('contact'); + Nav::setSelected('contacts'); Contact::setPageTitle($contact); diff --git a/src/Module/Contact/Profile.php b/src/Module/Contact/Profile.php index d322c9bc55..249b7bb856 100644 --- a/src/Module/Contact/Profile.php +++ b/src/Module/Contact/Profile.php @@ -280,7 +280,7 @@ class Profile extends BaseModule $this->page['aside'] .= $vcard_widget . $circles_widget; $o = ''; - Nav::setSelected('contact'); + Nav::setSelected('contacts'); $_SESSION['return_path'] = $this->args->getQueryString(); diff --git a/src/Module/Contact/Revoke.php b/src/Module/Contact/Revoke.php index 78574c4ef9..f96f79a6a0 100644 --- a/src/Module/Contact/Revoke.php +++ b/src/Module/Contact/Revoke.php @@ -82,7 +82,7 @@ class Revoke extends BaseModule return Login::form($_SERVER['REQUEST_URI']); } - Nav::setSelected('contact'); + Nav::setSelected('contacts'); return Renderer::replaceMacros(Renderer::getMarkupTemplate('contact_drop_confirm.tpl'), [ '$l10n' => [ diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index d8f65a2c40..5165bc075b 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -645,6 +645,16 @@ nav.navbar .nav > li > button:hover, nav.navbar .nav > li > button:focus { background-color: $nav_icon_hover_color; } +/* Current section highlighting */ +#topbar-first .nav > li > a.selected i, +#nav-notification.dropdown.open { + border-bottom: 3px solid $nav_icon_color; + padding-bottom: 7px; +} +/* Offset the overflow caused by the current section highlighting padding above by a lowered height */ +#topbar-first .nav > li > a.selected:hover { + height: 50px; +} #topbar-first .nav > .account { height: 50px; margin-left: 20px; diff --git a/view/theme/frio/templates/nav.tpl b/view/theme/frio/templates/nav.tpl index 00619a0f51..bcd699e553 100644 --- a/view/theme/frio/templates/nav.tpl +++ b/view/theme/frio/templates/nav.tpl @@ -95,9 +95,9 @@ {{/if}} {{if $nav.calendar}} - {{/if}} From 8043016e0e87b62dee055f58215cad763c831144 Mon Sep 17 00:00:00 2001 From: Marcus Funch Date: Sun, 4 Jan 2026 20:45:10 +0100 Subject: [PATCH 037/197] Fix missing link to calendar in Vier, and add calendar highlighting --- src/Module/Calendar/Show.php | 9 +- src/Module/Contact/Revoke.php | 2 +- view/lang/C/messages.po | 180 +++++++++++++++--------------- view/theme/frio/templates/nav.tpl | 2 +- view/theme/vier/templates/nav.tpl | 8 +- 5 files changed, 97 insertions(+), 104 deletions(-) diff --git a/src/Module/Calendar/Show.php b/src/Module/Calendar/Show.php index f5eb962607..5d46df6298 100644 --- a/src/Module/Calendar/Show.php +++ b/src/Module/Calendar/Show.php @@ -90,14 +90,11 @@ class Show extends BaseModule '$i18n' => $i18n, ]); - // Only highlight the calendar link if you're on your own calendar - if ($is_owner) { - Nav::setSelected('calendar'); - } - if ($is_owner) { // Removing the vCard added by Profile::load for owners $this->page['aside'] = ''; + // Only highlight the calendar link if you're on your own calendar + Nav::setSelected('calendar'); } $this->page['aside'] .= Widget\CalendarExport::getHTML($owner['uid']); @@ -113,7 +110,7 @@ class Show extends BaseModule $tpl = Renderer::getMarkupTemplate("calendar/calendar.tpl"); $o = Renderer::replaceMacros($tpl, [ '$tabs' => $tabs, - '$title' => $this->t('Events'), + '$title' => $this->t('Calendar'), '$view' => $this->t('View'), '$new_event' => ['calendar/event/new', $this->t('New Event'), '', ''], diff --git a/src/Module/Contact/Revoke.php b/src/Module/Contact/Revoke.php index f96f79a6a0..db92cbf730 100644 --- a/src/Module/Contact/Revoke.php +++ b/src/Module/Contact/Revoke.php @@ -39,7 +39,7 @@ class Revoke extends BaseModule { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); - $this->dba = $dba; + $this->dba = $dba; if (!DI::userSession()->getLocalUserId()) { return; diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index 55c3782771..01f7698fd2 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 2026.04-dev\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-01-06 15:55+0100\n" +"POT-Creation-Date: 2026-02-06 11:45+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -70,7 +70,7 @@ msgstr "" #: src/Module/Settings/ContactImport.php:50 #: src/Module/Settings/ContactImport.php:97 #: src/Module/Settings/Delegation.php:76 src/Module/Settings/Display.php:85 -#: src/Module/Settings/Display.php:214 +#: src/Module/Settings/Display.php:219 #: src/Module/Settings/Profile/Photo/Crop.php:148 #: src/Module/Settings/Profile/Photo/Index.php:96 #: src/Module/Settings/RemoveMe.php:103 src/Module/Settings/UserExport.php:64 @@ -1755,7 +1755,7 @@ msgstr "" #: src/Content/Feature.php:132 src/Content/Widget.php:626 #: src/Module/Admin/Site.php:474 src/Module/BaseSettings.php:113 -#: src/Module/Settings/Channels.php:224 src/Module/Settings/Display.php:429 +#: src/Module/Settings/Channels.php:224 src/Module/Settings/Display.php:434 msgid "Channels" msgstr "" @@ -2039,8 +2039,8 @@ msgstr "" #: src/Content/Nav.php:231 src/Content/Nav.php:291 #: src/Module/BaseProfile.php:70 src/Module/BaseProfile.php:73 #: src/Module/BaseProfile.php:81 src/Module/BaseProfile.php:84 -#: src/Module/Settings/Display.php:430 view/theme/frio/theme.php:224 -#: view/theme/frio/theme.php:228 +#: src/Module/Calendar/Show.php:113 src/Module/Settings/Display.php:435 +#: view/theme/frio/theme.php:224 view/theme/frio/theme.php:228 msgid "Calendar" msgstr "" @@ -2886,37 +2886,37 @@ msgid "%s (%s)" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:421 -#: src/Module/Settings/Display.php:397 +#: src/Module/Settings/Display.php:402 msgid "Monday" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:422 -#: src/Module/Settings/Display.php:398 +#: src/Module/Settings/Display.php:403 msgid "Tuesday" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:423 -#: src/Module/Settings/Display.php:399 +#: src/Module/Settings/Display.php:404 msgid "Wednesday" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:424 -#: src/Module/Settings/Display.php:400 +#: src/Module/Settings/Display.php:405 msgid "Thursday" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:425 -#: src/Module/Settings/Display.php:401 +#: src/Module/Settings/Display.php:406 msgid "Friday" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:426 -#: src/Module/Settings/Display.php:402 +#: src/Module/Settings/Display.php:407 msgid "Saturday" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:420 -#: src/Module/Settings/Display.php:396 +#: src/Module/Settings/Display.php:401 msgid "Sunday" msgstr "" @@ -3344,17 +3344,17 @@ msgid "today" msgstr "" #: src/Model/Event.php:454 src/Module/Calendar/Show.php:118 -#: src/Module/Settings/Display.php:407 src/Util/Temporal.php:343 +#: src/Module/Settings/Display.php:412 src/Util/Temporal.php:343 msgid "month" msgstr "" #: src/Model/Event.php:455 src/Module/Calendar/Show.php:119 -#: src/Module/Settings/Display.php:408 src/Util/Temporal.php:344 +#: src/Module/Settings/Display.php:413 src/Util/Temporal.php:344 msgid "week" msgstr "" #: src/Model/Event.php:456 src/Module/Calendar/Show.php:120 -#: src/Module/Settings/Display.php:409 src/Util/Temporal.php:345 +#: src/Module/Settings/Display.php:414 src/Util/Temporal.php:345 msgid "day" msgstr "" @@ -3961,7 +3961,7 @@ msgstr "" #: src/Module/Settings/Connectors.php:143 #: src/Module/Settings/Connectors.php:228 #: src/Module/Settings/ContactImport.php:111 -#: src/Module/Settings/Delegation.php:179 src/Module/Settings/Display.php:422 +#: src/Module/Settings/Delegation.php:179 src/Module/Settings/Display.php:427 #: src/Module/Settings/Features.php:90 #: src/Module/Settings/Profile/Index.php:272 msgid "Save Settings" @@ -4313,11 +4313,11 @@ msgstr "" msgid "%s is no valid input for maximum image size" msgstr "" -#: src/Module/Admin/Site.php:364 src/Module/Settings/Display.php:232 +#: src/Module/Admin/Site.php:364 src/Module/Settings/Display.php:237 msgid "No special theme for mobile devices" msgstr "" -#: src/Module/Admin/Site.php:381 src/Module/Settings/Display.php:242 +#: src/Module/Admin/Site.php:381 src/Module/Settings/Display.php:247 #, php-format msgid "%s - (Experimental)" msgstr "" @@ -5244,7 +5244,7 @@ msgid "Can be \"all\" or \"tags\". \"all\" means that every public post should b msgstr "" #: src/Module/Admin/Site.php:596 src/Module/Contact/Profile.php:354 -#: src/Module/Settings/Display.php:277 +#: src/Module/Settings/Display.php:282 #: src/Module/Settings/TwoFactor/Index.php:132 msgid "Disabled" msgstr "" @@ -5523,7 +5523,7 @@ msgid "Screenshot" msgstr "" #: src/Module/Admin/Themes/Details.php:83 src/Module/Admin/Themes/Index.php:104 -#: src/Module/BaseAdmin.php:78 src/Module/Settings/Display.php:425 +#: src/Module/BaseAdmin.php:78 src/Module/Settings/Display.php:430 msgid "Themes" msgstr "" @@ -5999,10 +5999,6 @@ msgstr "" msgid "calendar" msgstr "" -#: src/Module/Calendar/Show.php:113 -msgid "Events" -msgstr "" - #: src/Module/Calendar/Show.php:114 msgid "View" msgstr "" @@ -6011,7 +6007,7 @@ msgstr "" msgid "New Event" msgstr "" -#: src/Module/Calendar/Show.php:121 src/Module/Settings/Display.php:410 +#: src/Module/Calendar/Show.php:121 src/Module/Settings/Display.php:415 msgid "list" msgstr "" @@ -9576,12 +9572,12 @@ msgid "When selected, the channel results are reshared. This only works for publ msgstr "" #: src/Module/Settings/Channels.php:184 src/Module/Settings/Channels.php:210 -#: src/Module/Settings/Display.php:466 +#: src/Module/Settings/Display.php:471 msgid "Label" msgstr "" #: src/Module/Settings/Channels.php:185 src/Module/Settings/Channels.php:211 -#: src/Module/Settings/Display.php:467 +#: src/Module/Settings/Display.php:472 #: src/Module/Settings/TwoFactor/AppSpecific.php:123 msgid "Description" msgstr "" @@ -9968,269 +9964,269 @@ msgstr "" msgid "No entries." msgstr "" -#: src/Module/Settings/Display.php:200 +#: src/Module/Settings/Display.php:205 msgid "The theme you chose isn't available." msgstr "" -#: src/Module/Settings/Display.php:240 +#: src/Module/Settings/Display.php:245 #, php-format msgid "%s - (Unsupported)" msgstr "" -#: src/Module/Settings/Display.php:278 +#: src/Module/Settings/Display.php:283 msgid "Color/Black" msgstr "" -#: src/Module/Settings/Display.php:279 view/theme/frio/php/scheme.php:95 +#: src/Module/Settings/Display.php:284 view/theme/frio/php/scheme.php:95 msgid "Black" msgstr "" -#: src/Module/Settings/Display.php:280 +#: src/Module/Settings/Display.php:285 msgid "Color/White" msgstr "" -#: src/Module/Settings/Display.php:281 +#: src/Module/Settings/Display.php:286 msgid "White" msgstr "" -#: src/Module/Settings/Display.php:286 +#: src/Module/Settings/Display.php:291 msgid "No preview" msgstr "" -#: src/Module/Settings/Display.php:287 +#: src/Module/Settings/Display.php:292 msgid "No image" msgstr "" -#: src/Module/Settings/Display.php:288 +#: src/Module/Settings/Display.php:293 msgid "Small Image" msgstr "" -#: src/Module/Settings/Display.php:289 +#: src/Module/Settings/Display.php:294 msgid "Large Image" msgstr "" -#: src/Module/Settings/Display.php:290 +#: src/Module/Settings/Display.php:295 msgid "Automatic image size" msgstr "" -#: src/Module/Settings/Display.php:421 +#: src/Module/Settings/Display.php:426 msgid "Display Settings" msgstr "" -#: src/Module/Settings/Display.php:423 +#: src/Module/Settings/Display.php:428 msgid "Content Settings" msgstr "" -#: src/Module/Settings/Display.php:424 view/theme/duepuntozero/config.php:74 +#: src/Module/Settings/Display.php:429 view/theme/duepuntozero/config.php:74 #: view/theme/frio/config.php:159 view/theme/quattro/config.php:76 #: view/theme/vier/config.php:124 msgid "Theme settings" msgstr "" -#: src/Module/Settings/Display.php:426 +#: src/Module/Settings/Display.php:431 #, php-format msgid "Settings for %s" msgstr "" -#: src/Module/Settings/Display.php:427 +#: src/Module/Settings/Display.php:432 msgid "Note: If you switch the theme, you need to save changes before you can see the settings for the new theme below." msgstr "" -#: src/Module/Settings/Display.php:428 +#: src/Module/Settings/Display.php:433 msgid "Timelines" msgstr "" -#: src/Module/Settings/Display.php:431 src/Module/Settings/Features.php:83 +#: src/Module/Settings/Display.php:436 src/Module/Settings/Features.php:83 msgid "Drag to reorder or tab to item with keyboard and move up/down with arrow keys" msgstr "" -#: src/Module/Settings/Display.php:434 src/Module/Settings/Display.php:438 +#: src/Module/Settings/Display.php:439 src/Module/Settings/Display.php:443 #: src/Module/Settings/Features.php:87 msgid "Reset order" msgstr "" -#: src/Module/Settings/Display.php:444 +#: src/Module/Settings/Display.php:449 msgid "Display theme" msgstr "" -#: src/Module/Settings/Display.php:445 +#: src/Module/Settings/Display.php:450 msgid "Mobile theme" msgstr "" -#: src/Module/Settings/Display.php:448 +#: src/Module/Settings/Display.php:453 msgid "Number of items to display per page:" msgstr "" -#: src/Module/Settings/Display.php:448 src/Module/Settings/Display.php:449 +#: src/Module/Settings/Display.php:453 src/Module/Settings/Display.php:454 msgid "Maximum of 100 items" msgstr "" -#: src/Module/Settings/Display.php:449 +#: src/Module/Settings/Display.php:454 msgid "Number of items to display per page when viewed from mobile device:" msgstr "" -#: src/Module/Settings/Display.php:450 +#: src/Module/Settings/Display.php:455 msgid "Regularly update the page content" msgstr "" -#: src/Module/Settings/Display.php:450 +#: src/Module/Settings/Display.php:455 msgid "When enabled, new content on network, community and channels are added on top." msgstr "" -#: src/Module/Settings/Display.php:451 +#: src/Module/Settings/Display.php:456 msgid "Display emoticons" msgstr "" -#: src/Module/Settings/Display.php:451 +#: src/Module/Settings/Display.php:456 msgid "When enabled, emoticons are replaced with matching symbols." msgstr "" -#: src/Module/Settings/Display.php:452 +#: src/Module/Settings/Display.php:457 msgid "Infinite scroll" msgstr "" -#: src/Module/Settings/Display.php:452 +#: src/Module/Settings/Display.php:457 msgid "Automatic fetch new items when reaching the page end." msgstr "" -#: src/Module/Settings/Display.php:453 +#: src/Module/Settings/Display.php:458 msgid "Enable Smart Threading" msgstr "" -#: src/Module/Settings/Display.php:453 +#: src/Module/Settings/Display.php:458 msgid "Enable the automatic suppression of extraneous thread indentation." msgstr "" -#: src/Module/Settings/Display.php:454 +#: src/Module/Settings/Display.php:459 msgid "Display the Dislike feature" msgstr "" -#: src/Module/Settings/Display.php:454 +#: src/Module/Settings/Display.php:459 msgid "Display the Dislike button and dislike reactions on posts and comments." msgstr "" -#: src/Module/Settings/Display.php:455 +#: src/Module/Settings/Display.php:460 msgid "Display the resharer" msgstr "" -#: src/Module/Settings/Display.php:455 +#: src/Module/Settings/Display.php:460 msgid "Display the first resharer as icon and text on a reshared item." msgstr "" -#: src/Module/Settings/Display.php:456 +#: src/Module/Settings/Display.php:461 msgid "Stay local" msgstr "" -#: src/Module/Settings/Display.php:456 +#: src/Module/Settings/Display.php:461 msgid "Don't go to a remote system when following a contact link." msgstr "" -#: src/Module/Settings/Display.php:457 +#: src/Module/Settings/Display.php:462 msgid "Show the post deletion checkbox" msgstr "" -#: src/Module/Settings/Display.php:457 +#: src/Module/Settings/Display.php:462 msgid "Display the checkbox for the post deletion on the network page." msgstr "" -#: src/Module/Settings/Display.php:458 +#: src/Module/Settings/Display.php:463 msgid "DIsplay the event list" msgstr "" -#: src/Module/Settings/Display.php:458 +#: src/Module/Settings/Display.php:463 msgid "Display the birthday reminder and event list on the network page." msgstr "" -#: src/Module/Settings/Display.php:459 +#: src/Module/Settings/Display.php:464 msgid "Link preview mode" msgstr "" -#: src/Module/Settings/Display.php:459 +#: src/Module/Settings/Display.php:464 msgid "Appearance of the link preview that is added to each post with a link." msgstr "" -#: src/Module/Settings/Display.php:460 +#: src/Module/Settings/Display.php:465 msgid "Hide pictures with empty alternative text" msgstr "" -#: src/Module/Settings/Display.php:460 +#: src/Module/Settings/Display.php:465 msgid "Don't display pictures that are missing the alternative text." msgstr "" -#: src/Module/Settings/Display.php:461 +#: src/Module/Settings/Display.php:466 msgid "Hide custom emojis" msgstr "" -#: src/Module/Settings/Display.php:461 +#: src/Module/Settings/Display.php:466 msgid "Don't display custom emojis." msgstr "" -#: src/Module/Settings/Display.php:462 +#: src/Module/Settings/Display.php:467 msgid "Platform icons style" msgstr "" -#: src/Module/Settings/Display.php:462 +#: src/Module/Settings/Display.php:467 msgid "Style of the platform icons" msgstr "" -#: src/Module/Settings/Display.php:463 +#: src/Module/Settings/Display.php:468 msgid "Embed remote media" msgstr "" -#: src/Module/Settings/Display.php:463 +#: src/Module/Settings/Display.php:468 msgid "When enabled, remote media will be embedded in the post, like for example YouTube videos." msgstr "" -#: src/Module/Settings/Display.php:464 +#: src/Module/Settings/Display.php:469 msgid "Embed supported media" msgstr "" -#: src/Module/Settings/Display.php:464 +#: src/Module/Settings/Display.php:469 msgid "When enabled, remote media will be embedded in the post instead of using the local player if this is supported by the remote system. This is useful for media where the remote player is better than the local one, like for example Peertube videos." msgstr "" -#: src/Module/Settings/Display.php:468 +#: src/Module/Settings/Display.php:473 msgid "Channels Widget" msgstr "" -#: src/Module/Settings/Display.php:469 +#: src/Module/Settings/Display.php:474 msgid "Top Menu" msgstr "" -#: src/Module/Settings/Display.php:471 +#: src/Module/Settings/Display.php:476 msgid "Enable timelines that you want to see in the channels widget. Bookmark timelines that you want to see in the top menu." msgstr "" -#: src/Module/Settings/Display.php:473 +#: src/Module/Settings/Display.php:478 msgid "Channel languages:" msgstr "" -#: src/Module/Settings/Display.php:473 +#: src/Module/Settings/Display.php:478 msgid "Select all the languages you want to see in your channels. \"Unspecified\" describes all posts for which no language information was detected (e.g. posts with just an image or too little text to be sure of the language). If you want to see all languages, you will need to select all items in the list." msgstr "" -#: src/Module/Settings/Display.php:474 +#: src/Module/Settings/Display.php:479 msgid "Timeline channels:" msgstr "" -#: src/Module/Settings/Display.php:474 +#: src/Module/Settings/Display.php:479 msgid "Select all the channels that you want to see in your network timeline." msgstr "" -#: src/Module/Settings/Display.php:476 +#: src/Module/Settings/Display.php:481 msgid "Filter channels:" msgstr "" -#: src/Module/Settings/Display.php:476 +#: src/Module/Settings/Display.php:481 #, php-format msgid "Select all the channels that you want to use as a filter for your network timeline. All posts from these channels will be hidden. For technical reasons postings that are older than %s will not be filtered." msgstr "" -#: src/Module/Settings/Display.php:479 +#: src/Module/Settings/Display.php:484 msgid "Beginning of week:" msgstr "" -#: src/Module/Settings/Display.php:480 +#: src/Module/Settings/Display.php:485 msgid "Default calendar view:" msgstr "" diff --git a/view/theme/frio/templates/nav.tpl b/view/theme/frio/templates/nav.tpl index bcd699e553..5f36caf4d1 100644 --- a/view/theme/frio/templates/nav.tpl +++ b/view/theme/frio/templates/nav.tpl @@ -95,7 +95,7 @@ {{/if}} {{if $nav.calendar}} - {{/if}} - {{if $nav.events}} - {{/if}} {{if $nav.channel}} From 5555478b30db6c107f2042903bb2f470733188cf Mon Sep 17 00:00:00 2001 From: "Marcus F." Date: Wed, 28 Jan 2026 17:16:57 +0100 Subject: [PATCH 038/197] Make contact link to global directory pass on user language --- src/Content/Widget.php | 14 ++++++++++---- src/Core/L10n.php | 11 +++++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/Content/Widget.php b/src/Content/Widget.php index 6adb8c24b7..7cc0099771 100644 --- a/src/Content/Widget.php +++ b/src/Content/Widget.php @@ -48,6 +48,12 @@ class Widget */ public static function findPeople(): string { + // Langs in friendica are all lowercase and dash separated (e.g. da-dk) - in the directory + // they're underscore separated, with the latter part being uppercase (e.g. da_DK) + $directory_user_lang_string = ""; + if (DI::userSession()->get('language')) { + $directory_user_lang_string = "&lang=" . DI::l10n()->langToLocaleCode(DI::userSession()->get('language')); + } $global_dir = Search::getGlobalDirectory(); if (DI::config()->get('system', 'invitation_only')) { @@ -70,7 +76,7 @@ class Widget $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['global_dir'] = OpenWebAuth::getZrlUrl($global_dir, true) . $directory_user_lang_string; $nv['local_directory'] = DI::l10n()->t('Local Directory'); $aside = []; @@ -611,9 +617,9 @@ class Widget $widget_timelineorder = json_decode(DI::pConfig()->get($uid, 'system', 'widget_timeline_order')); if (!empty($widget_timelineorder)) { $tmp = []; - foreach($widget_timelineorder as $order) { - foreach($channels as $channel) { - if($channel['ref'] == $order) { + foreach ($widget_timelineorder as $order) { + foreach ($channels as $channel) { + if ($channel['ref'] == $order) { $tmp[] = $channel; } } diff --git a/src/Core/L10n.php b/src/Core/L10n.php index 33fa658836..9d16415e89 100644 --- a/src/Core/L10n.php +++ b/src/Core/L10n.php @@ -469,6 +469,17 @@ class L10n return $languages; } + /** + * Converts e.g. en-gb to en_GB and da-dk to da_DK, which is the format some other systems expect + * + * @param string $lang + * @return string + * */ + public function langToLocaleCode($lang) + { + return preg_replace_callback("/([a-z]+)-([a-z]+)/", fn ($m) => $m[1] . "_" . strtoupper($m[2]), $lang); + } + /** * Convert the language code to ISO639-1 * It also converts old codes to their new counterparts. From 0a58198ac2c40a975d853816f9fa449a6ce2b237 Mon Sep 17 00:00:00 2001 From: Akinniranye Samuel Tomiwa Date: Sat, 7 Feb 2026 17:12:53 +0100 Subject: [PATCH 039/197] Fix event participation responses not delivered to event organizers --- src/Protocol/ActivityPub/Transmitter.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index bbfd52e0e4..82ed04dc6c 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -763,7 +763,9 @@ class Transmitter // But comments to groups aren't directed to the followers collection // This rule is only valid when the actor isn't the group. // The group needs to transmit their content to their followers. - if (($profile['type'] == 'Group') && ($profile['url'] != ($actor_profile['url'] ?? ''))) { + // Event participation (Accept/Reject/TentativeAccept) must be directly addressed to the event organizer + $is_event_participation = in_array($item['verb'] ?? '', [Activity::ATTEND, Activity::ATTENDNO, Activity::ATTENDMAYBE]); + if (($profile['type'] == 'Group' && $profile['url'] != ($actor_profile['url'] ?? '')) || $is_event_participation) { $data['to'][] = $profile['url']; } else { $data['cc'][] = $profile['url']; From 6fec466bcc5c0f13be8dff4ad6c8f6358a99763d Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 7 Feb 2026 17:35:30 +0000 Subject: [PATCH 040/197] Ensure numeric content in numeric fields --- src/Util/ParseUrl.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Util/ParseUrl.php b/src/Util/ParseUrl.php index 84f907c89e..1d6d70293d 100644 --- a/src/Util/ParseUrl.php +++ b/src/Util/ParseUrl.php @@ -1282,22 +1282,22 @@ class ParseUrl } $content = JsonLD::fetchElement($jsonld, 'height'); - if (!empty($content) && is_string($content)) { + if (!empty($content) && is_string($content) && is_numeric($content)) { $media['height'] = trim($content); } $content = JsonLD::fetchElement($jsonld, 'width'); - if (!empty($content) && is_string($content)) { + if (!empty($content) && is_string($content) && is_numeric($content)) { $media['width'] = trim($content); } $content = JsonLD::fetchElement($jsonld, 'duration'); - if (!empty($content) && is_string($content)) { + if (!empty($content) && is_string($content) && is_numeric($content)) { $media['duration'] = trim($content); } $content = JsonLD::fetchElement($jsonld, 'contentSize'); - if (!empty($content) && is_string($content)) { + if (!empty($content) && is_string($content) && is_numeric($content)) { $media['size'] = trim($content); } From 0a3c537be599443c87484bf5c4bb077f8e180d9a Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 7 Feb 2026 17:47:32 +0000 Subject: [PATCH 041/197] Fix for empty circles --- database.sql | 2 ++ src/Module/Conversation/Network.php | 2 +- static/dbview.config.php | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/database.sql b/database.sql index c97446d23a..027b92c0d2 100644 --- a/database.sql +++ b/database.sql @@ -2106,6 +2106,7 @@ CREATE VIEW `channel-post-view` AS SELECT `channel-post`.`uid` AS `uid`, `channel-post`.`uri-id` AS `uri-id`, `channel-post`.`in-timeline` AS `in-timeline`, + `post-engagement`.`owner-id` AS `contact-id`, `post-engagement`.`owner-id` AS `owner-id`, `post-engagement`.`media-type` AS `media-type`, `post-engagement`.`language` AS `language`, @@ -2135,6 +2136,7 @@ CREATE VIEW `system-channel-post-view` AS SELECT `system-channel-post`.`uid` AS `uid`, `system-channel-post`.`uri-id` AS `uri-id`, `system-channel-post`.`in-timeline` AS `in-timeline`, + `post-engagement`.`owner-id` AS `contact-id`, `post-engagement`.`owner-id` AS `owner-id`, `post-engagement`.`media-type` AS `media-type`, `post-engagement`.`language` AS `language`, diff --git a/src/Module/Conversation/Network.php b/src/Module/Conversation/Network.php index d8752eee02..5bcde53783 100644 --- a/src/Module/Conversation/Network.php +++ b/src/Module/Conversation/Network.php @@ -552,7 +552,7 @@ class Network extends Timeline $commonCondition = DBA::mergeConditions($commonCondition, array_merge([$query], [$this->session->getLocalUserId()], $filterchannels)); } - $fields = ['uri-id', 'created', 'received', 'commented', 'channel']; + $fields = ['uri-id', 'created', 'received', 'commented', 'channel', 'contact-id']; $condition = DBA::mergeConditions($timelineCondition, $commonCondition); $timeline = $this->database->getSQL($this->circleId ? 'network-thread-circle-view' : 'network-thread-view', $fields, $condition, $params); diff --git a/static/dbview.config.php b/static/dbview.config.php index 97d33f2bfc..0d2615bffa 100644 --- a/static/dbview.config.php +++ b/static/dbview.config.php @@ -53,6 +53,7 @@ return [ "uid" => ["channel-post", "uid"], "uri-id" => ["channel-post", "uri-id"], "in-timeline" => ["channel-post", "in-timeline"], + "contact-id" => ["post-engagement", "owner-id"], "owner-id" => ["post-engagement", "owner-id"], "media-type" => ["post-engagement", "media-type"], "language" => ["post-engagement", "language"], @@ -80,6 +81,7 @@ return [ "uid" => ["system-channel-post", "uid"], "uri-id" => ["system-channel-post", "uri-id"], "in-timeline" => ["system-channel-post", "in-timeline"], + "contact-id" => ["post-engagement", "owner-id"], "owner-id" => ["post-engagement", "owner-id"], "media-type" => ["post-engagement", "media-type"], "language" => ["post-engagement", "language"], From f901252c2af3641ed7d33399cf1cb3285763e1c2 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 7 Feb 2026 17:30:08 +0000 Subject: [PATCH 042/197] Store "View" activity as "seen" marker. --- database.sql | 62 ++++++++++--------- doc/en/spec/database/db-post-engagement.md | 1 + .../Conversation/Factory/ChannelPost.php | 3 +- .../Factory/SystemChannelPost.php | 9 +-- .../Repository/UserDefinedChannel.php | 36 +++++++++++ src/Content/Item.php | 20 ++++++ src/Model/Contact/Relation.php | 50 +++++---------- src/Model/Item.php | 9 ++- src/Model/ItemHelper.php | 5 +- src/Model/Post/Engagement.php | 3 +- src/Module/Api/Mastodon/Statuses.php | 1 + src/Module/Conversation/Timeline.php | 12 ++-- src/Module/Item/Display.php | 6 +- static/dbstructure.config.php | 3 +- static/dbview.config.php | 57 +++++++++-------- 15 files changed, 173 insertions(+), 104 deletions(-) diff --git a/database.sql b/database.sql index 027b92c0d2..8062072567 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2026.04-dev (Blutwurz) --- DB_UPDATE_VERSION 1587 +-- DB_UPDATE_VERSION 1588 -- ------------------------------------------ @@ -1353,6 +1353,7 @@ CREATE TABLE IF NOT EXISTS `post-engagement` ( `restricted` boolean NOT NULL DEFAULT '0' COMMENT 'If true, this post is either unlisted or not from a federated network', `comments` mediumint unsigned COMMENT 'Number of comments', `activities` mediumint unsigned COMMENT 'Number of activities (like, dislike, ...)', + `views` mediumint unsigned COMMENT 'Number of views', PRIMARY KEY(`uri-id`), INDEX `owner-id` (`owner-id`), INDEX `created` (`created`), @@ -2118,8 +2119,9 @@ CREATE VIEW `channel-post-view` AS SELECT `post-engagement`.`network` AS `network`, `ownercontact`.`contact-type` AS `contact-type`, `post-engagement`.`restricted` AS `restricted`, - 0 AS `comments`, - 0 AS `activities` + `post-engagement`.`comments` AS `comments`, + `post-engagement`.`activities` AS `activities`, + `post-engagement`.`views` AS `views` FROM `channel-post` INNER JOIN `post-engagement` ON `post-engagement`.`uri-id` = `channel-post`.`uri-id` INNER JOIN `post-thread` ON `post-thread`.`uri-id` = `channel-post`.`uri-id` @@ -2148,8 +2150,9 @@ CREATE VIEW `system-channel-post-view` AS SELECT `post-engagement`.`network` AS `network`, `ownercontact`.`contact-type` AS `contact-type`, `post-engagement`.`restricted` AS `restricted`, - 0 AS `comments`, - 0 AS `activities` + `post-engagement`.`comments` AS `comments`, + `post-engagement`.`activities` AS `activities`, + `post-engagement`.`views` AS `views` FROM `system-channel-post` INNER JOIN `post-engagement` ON `post-engagement`.`uri-id` = `system-channel-post`.`uri-id` INNER JOIN `post-thread` ON `post-thread`.`uri-id` = `system-channel-post`.`uri-id` @@ -2220,8 +2223,9 @@ CREATE VIEW `post-engagement-user-view` AS SELECT `post-thread-user`.`network` AS `network`, `post-user`.`protocol` AS `protocol`, `post-engagement`.`restricted` AS `restricted`, - 0 AS `comments`, - 0 AS `activities` + `post-engagement`.`comments` AS `comments`, + `post-engagement`.`activities` AS `activities`, + `post-engagement`.`views` AS `views` FROM `post-thread-user` INNER JOIN `post-engagement` ON `post-engagement`.`uri-id` = `post-thread-user`.`uri-id` INNER JOIN `post-user` ON `post-user`.`id` = `post-thread-user`.`post-user-id` @@ -2245,9 +2249,9 @@ CREATE VIEW `post-timeline-view` AS SELECT `post-user`.`gravity` AS `gravity`, `post-user`.`created` AS `created`, `post-user`.`edited` AS `edited`, - `post-thread-user`.`commented` AS `commented`, + `post-thread`.`commented` AS `commented`, `post-user`.`received` AS `received`, - `post-thread-user`.`changed` AS `changed`, + `post-thread`.`changed` AS `changed`, `post-user`.`private` AS `private`, `post-user`.`visible` AS `visible`, `post-user`.`deleted` AS `deleted`, @@ -2273,11 +2277,11 @@ CREATE VIEW `post-timeline-view` AS SELECT `post-user`.`causer-id` AS `causer-id`, `causer`.`blocked` AS `causer-blocked`, `causer`.`gsid` AS `causer-gsid`, - `post-thread-user`.`network` AS `parent-network`, - `post-thread-user`.`owner-id` AS `parent-owner-id`, - `post-thread-user`.`author-id` AS `parent-author-id` + `post-thread`.`network` AS `parent-network`, + `post-thread`.`owner-id` AS `parent-owner-id`, + `post-thread`.`author-id` AS `parent-author-id` FROM `post-user` - LEFT JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid` + LEFT JOIN `post-thread` ON `post-thread`.`uri-id` = `post-user`.`parent-uri-id` STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-user`.`contact-id` STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `post-user`.`author-id` STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = `post-user`.`owner-id` @@ -2293,9 +2297,9 @@ CREATE VIEW `post-timeline-origin-view` AS SELECT `post-origin`.`gravity` AS `gravity`, `post-origin`.`created` AS `created`, `post-user`.`edited` AS `edited`, - `post-thread-user`.`commented` AS `commented`, + `post-thread`.`commented` AS `commented`, `post-origin`.`received` AS `received`, - `post-thread-user`.`changed` AS `changed`, + `post-thread`.`changed` AS `changed`, `post-origin`.`private` AS `private`, `post-user`.`visible` AS `visible`, `post-user`.`deleted` AS `deleted`, @@ -2323,7 +2327,7 @@ CREATE VIEW `post-timeline-origin-view` AS SELECT `causer`.`gsid` AS `causer-gsid` FROM `post-origin` INNER JOIN `post-user` ON `post-user`.`id` = `post-origin`.`id` - LEFT JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-origin`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-origin`.`uid` + LEFT JOIN `post-thread` ON `post-thread`.`uri-id` = `post-origin`.`parent-uri-id` STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-user`.`contact-id` STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `post-user`.`author-id` STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = `post-user`.`owner-id` @@ -2348,7 +2352,8 @@ CREATE VIEW `post-searchindex-user-view` AS SELECT `post-user`.`protocol` AS `protocol`, `post-searchindex`.`restricted` AS `restricted`, 0 AS `comments`, - 0 AS `activities` + 0 AS `activities`, + 0 AS `views` FROM `post-thread-user` INNER JOIN `post-searchindex` ON `post-searchindex`.`uri-id` = `post-thread-user`.`uri-id` INNER JOIN `post-user` ON `post-user`.`id` = `post-thread-user`.`post-user-id` @@ -2767,9 +2772,9 @@ CREATE VIEW `post-user-view` AS SELECT `thr-parent-item-uri`.`uri` AS `thr-parent`, `post-user`.`thr-parent-id` AS `thr-parent-id`, `conversation-item-uri`.`uri` AS `conversation`, - `post-thread-user`.`conversation-id` AS `conversation-id`, + `post-thread`.`conversation-id` AS `conversation-id`, `context-item-uri`.`uri` AS `context`, - `post-thread-user`.`context-id` AS `context-id`, + `post-thread`.`context-id` AS `context-id`, `quote-item-uri`.`uri` AS `quote-uri`, `post-content`.`quote-uri-id` AS `quote-uri-id`, `item-uri`.`guid` AS `guid`, @@ -2781,9 +2786,9 @@ CREATE VIEW `post-user-view` AS SELECT `post-user`.`replies-id` AS `replies-id`, `post-user`.`created` AS `created`, `post-user`.`edited` AS `edited`, - `post-thread-user`.`commented` AS `commented`, + `post-thread`.`commented` AS `commented`, `post-user`.`received` AS `received`, - `post-thread-user`.`changed` AS `changed`, + `post-thread`.`changed` AS `changed`, `post-user`.`post-type` AS `post-type`, `post-user`.`post-reason` AS `post-reason`, `post-user`.`private` AS `private`, @@ -2915,15 +2920,16 @@ CREATE VIEW `post-user-view` AS SELECT EXISTS(SELECT `id` FROM `post-media` WHERE `post-media`.`uri-id` = `post-user`.`uri-id`) AS `has-media`, `diaspora-interaction`.`interaction` AS `signed_text`, `parent-item-uri`.`guid` AS `parent-guid`, - `post-thread-user`.`network` AS `parent-network`, - `post-thread-user`.`owner-id` AS `parent-owner-id`, - `post-thread-user`.`author-id` AS `parent-author-id`, + `post-thread`.`network` AS `parent-network`, + `post-thread`.`owner-id` AS `parent-owner-id`, + `post-thread`.`author-id` AS `parent-author-id`, `parent-post-author`.`url` AS `parent-author-link`, `parent-post-author`.`name` AS `parent-author-name`, `parent-post-author`.`nick` AS `parent-author-nick`, `parent-post-author`.`network` AS `parent-author-network` FROM `post-user` - INNER JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid` + LEFT JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid` + INNER JOIN `post-thread` ON `post-thread`.`uri-id` = `post-user`.`parent-uri-id` STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-user`.`contact-id` STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `post-user`.`author-id` STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = `post-user`.`owner-id` @@ -2931,8 +2937,8 @@ CREATE VIEW `post-user-view` AS SELECT LEFT JOIN `item-uri` ON `item-uri`.`id` = `post-user`.`uri-id` LEFT JOIN `item-uri` AS `thr-parent-item-uri` ON `thr-parent-item-uri`.`id` = `post-user`.`thr-parent-id` LEFT JOIN `item-uri` AS `parent-item-uri` ON `parent-item-uri`.`id` = `post-user`.`parent-uri-id` - LEFT JOIN `item-uri` AS `conversation-item-uri` ON `conversation-item-uri`.`id` = `post-thread-user`.`conversation-id` - LEFT JOIN `item-uri` AS `context-item-uri` ON `context-item-uri`.`id` = `post-thread-user`.`context-id` + LEFT JOIN `item-uri` AS `conversation-item-uri` ON `conversation-item-uri`.`id` = `post-thread`.`conversation-id` + LEFT JOIN `item-uri` AS `context-item-uri` ON `context-item-uri`.`id` = `post-thread`.`context-id` LEFT JOIN `item-uri` AS `external-item-uri` ON `external-item-uri`.`id` = `post-user`.`external-id` LEFT JOIN `item-uri` AS `replies-item-uri` ON `replies-item-uri`.`id` = `post-user`.`replies-id` LEFT JOIN `verb` ON `verb`.`id` = `post-user`.`vid` @@ -2943,7 +2949,7 @@ CREATE VIEW `post-user-view` AS SELECT LEFT JOIN `post-delivery-data` ON `post-delivery-data`.`uri-id` = `post-user`.`uri-id` AND `post-user`.`origin` LEFT JOIN `post-question` ON `post-question`.`uri-id` = `post-user`.`uri-id` LEFT JOIN `permissionset` ON `permissionset`.`id` = `post-user`.`psid` - LEFT JOIN `contact` AS `parent-post-author` ON `parent-post-author`.`id` = `post-thread-user`.`author-id`; + LEFT JOIN `contact` AS `parent-post-author` ON `parent-post-author`.`id` = `post-thread`.`author-id`; -- -- VIEW post-thread-user-view diff --git a/doc/en/spec/database/db-post-engagement.md b/doc/en/spec/database/db-post-engagement.md index e42381ac70..be5d031520 100644 --- a/doc/en/spec/database/db-post-engagement.md +++ b/doc/en/spec/database/db-post-engagement.md @@ -18,6 +18,7 @@ Engagement data per post | restricted | If true, this post is either unlisted or not from a federated network | boolean | NO | | 0 | | | comments | Number of comments | mediumint unsigned | YES | | NULL | | | activities | Number of activities (like, dislike, ...) | mediumint unsigned | YES | | NULL | | +| views | Number of views | mediumint unsigned | YES | | NULL | | ## Indexes diff --git a/src/Content/Conversation/Factory/ChannelPost.php b/src/Content/Conversation/Factory/ChannelPost.php index 7cb08c3ab1..e52a474ac5 100644 --- a/src/Content/Conversation/Factory/ChannelPost.php +++ b/src/Content/Conversation/Factory/ChannelPost.php @@ -18,6 +18,7 @@ use Friendica\Model\Contact; use Friendica\Model\Item; use Friendica\Model\Post; use Friendica\Model\Tag; +use Friendica\Protocol\Activity; use Psr\Log\LoggerInterface; /** @@ -92,7 +93,7 @@ final class ChannelPost } foreach ($channels as $channel) { - $in_timeline = Post::exists(['parent-uri-id' => $engagement['uri-id'], 'uid' => $channel->uid]); + $in_timeline = Post::exists(["`parent-uri-id` = ? AND `uid` = ? AND NOT `verb` IN (?, ?, ?)", $engagement['uri-id'], $channel->uid, Activity::FOLLOW, Activity::VIEW, Activity::READ]); if ($engagement['restricted'] && !$in_timeline) { continue; diff --git a/src/Content/Conversation/Factory/SystemChannelPost.php b/src/Content/Conversation/Factory/SystemChannelPost.php index 1042344114..a9e7d98f65 100644 --- a/src/Content/Conversation/Factory/SystemChannelPost.php +++ b/src/Content/Conversation/Factory/SystemChannelPost.php @@ -17,6 +17,7 @@ use Friendica\Model\Contact; use Friendica\Model\Item; use Friendica\Model\Post; use Friendica\Model\User; +use Friendica\Protocol\Activity; use Friendica\Util\DateTimeFormat; use Psr\Log\LoggerInterface; @@ -108,7 +109,7 @@ final class SystemChannelPost $store = false; switch ($channel) { case Channel::WHATSHOT: - $store = ($engagement['comments'] > $this->channelRepository->getMedianComments($uid, 4, $network) || $engagement['activities'] > $this->channelRepository->getMedianActivities($uid, 4, $network)) && $engagement['contact-type'] != Contact::TYPE_COMMUNITY; + $store = ($engagement['comments'] > $this->channelRepository->getMedianComments($uid, 4, $network) || $engagement['activities'] > $this->channelRepository->getMedianActivities($uid, 4, $network) || $engagement['views'] > $this->channelRepository->getMedianViews($uid, 4, $network)) && $engagement['contact-type'] != Contact::TYPE_COMMUNITY; break; case Channel::FORYOU: @@ -117,7 +118,7 @@ final class SystemChannelPost if ($relation = $this->dba->selectFirst('contact-relation', ['relation-thread-score', 'follows'], ['relation-cid' => $cid, 'cid' => $owner])) { $store = $relation['relation-thread-score'] > $this->channelRepository->getMedianRelationThreadScore($cid, 4); if (!$store && $relation['follows']) { - $store = ($engagement['comments'] >= $this->channelRepository->getMedianComments($uid, 4, $network) || $engagement['activities'] >= $this->channelRepository->getMedianActivities($uid, 4, $network)); + $store = ($engagement['comments'] >= $this->channelRepository->getMedianComments($uid, 4, $network) || $engagement['activities'] >= $this->channelRepository->getMedianActivities($uid, 4, $network) || $engagement['views'] >= $this->channelRepository->getMedianViews($uid, 4, $network)); } } @@ -139,7 +140,7 @@ final class SystemChannelPost $store = $this->dba->exists('contact-relation', ["`relation-cid` = ? AND `cid` = ? AND `follows` AND `relation-thread-score` > ?", $owner, $cid, 0]); } - if (!$store && ($engagement['comments'] >= $this->channelRepository->getMedianComments($uid, 4, $network) || $engagement['activities'] >= $this->channelRepository->getMedianActivities($uid, 4, $network))) { + if (!$store && ($engagement['comments'] >= $this->channelRepository->getMedianComments($uid, 4, $network) || $engagement['activities'] >= $this->channelRepository->getMedianActivities($uid, 4, $network)) || $engagement['views'] >= $this->channelRepository->getMedianViews($uid, 4, $network)) { $store = $this->dba->exists('contact-relation', ["`relation-cid` = ? AND `cid` = ? AND `relation-thread-score` > ?", $owner, $cid, 0]); if (!$store) { $store = $this->dba->exists('contact-relation', ["`cid` = ? AND `relation-cid` = ? AND `relation-thread-score` > ?", $owner, $cid, 0]); @@ -208,7 +209,7 @@ final class SystemChannelPost 'channel' => $channel, 'uid' => $uid, 'uri-id' => $engagement['uri-id'], - 'in-timeline' => Post::exists(['parent-uri-id' => $engagement['uri-id'], 'uid' => $uid]), + 'in-timeline' => Post::exists(["`parent-uri-id` = ? AND `uid` = ? AND NOT `verb` IN (?, ?, ?)", $engagement['uri-id'], $uid, Activity::FOLLOW, Activity::VIEW, Activity::READ]), 'created' => $post['created'], 'received' => $post['received'], 'commented' => $post['commented'], diff --git a/src/Content/Conversation/Repository/UserDefinedChannel.php b/src/Content/Conversation/Repository/UserDefinedChannel.php index 4e5b380c57..8562904775 100644 --- a/src/Content/Conversation/Repository/UserDefinedChannel.php +++ b/src/Content/Conversation/Repository/UserDefinedChannel.php @@ -749,6 +749,42 @@ class UserDefinedChannel extends BaseRepository return $activities; } + /** + * Compute median views for a user's wanted languages. + * + * @param int $uid User id. + * @param int $divider Divider used to determine median index. + * @param string $network Optional network filter. + * @return int Median views value. + */ + public function getMedianViews(int $uid, int $divider, string $network = ''): int + { + $languages = User::getWantedLanguages($uid); + $cache_key = 'Channel:getMedianViews:' . $divider . ':' . implode(':', $languages) . $network; + $views = $this->cache->get($cache_key); + if (!empty($views)) { + return $views; + } + + $condition = ["`contact-type` != ? AND `views` > ? AND NOT `restricted`", Contact::TYPE_COMMUNITY, 0]; + $condition = $this->addLanguageCondition($uid, $condition); + + if ($network) { + $condition = DBA::mergeConditions($condition, ["`network` = ?", $network]); + } + + $limit = $this->db->count('post-engagement', $condition) / $divider; + $post = $this->db->selectToArray('post-engagement', ['views'], $condition, ['order' => ['views' => true], 'limit' => [$limit, 1]]); + $views = $post[0]['views'] ?? 0; + if (empty($views)) { + return 0; + } + + $this->cache->set($cache_key, $views, Duration::HALF_HOUR); + $this->logger->debug('Calculated median views', ['divider' => $divider, 'languages' => $languages, 'network' => $network, 'median' => $views]); + return $views; + } + /** * Compute median relation thread score for a contact id. * diff --git a/src/Content/Item.php b/src/Content/Item.php index 826146f68d..afbc0e7124 100644 --- a/src/Content/Item.php +++ b/src/Content/Item.php @@ -1363,4 +1363,24 @@ class Item $used_languages = $this->l10n->t("Detected languages in this post:\n%s", $used_languages); return $used_languages; } + + public function setViewed(int $uri_id, int $uid) + { + if (Post::exists(['thr-parent-id' => $uri_id, 'verb' => Activity::VIEW, 'uid' => $uid])) { + return; + } + + $item = Post::selectFirst(['id'], ['uri-id' => $uri_id, 'gravity' => ItemModel::GRAVITY_PARENT, 'uid' => [0, $uid]], ['order' => ['uid' => true]]); + if (!DBA::isResult($item)) { + return; + } + + $self = DBA::selectFirst('contact', ['id'], ['uid' => $uid, 'self' => true]); + if (!DBA::isResult($self)) { + return; + } + + $this->logger->debug('Marking item as viewed.', ['uri-id' => $uri_id, 'uid' => $uid]); + ItemModel::performActivity($item['id'], 'view', $uid, '<' . $self['id'] . '>', '', '', ''); + } } diff --git a/src/Model/Contact/Relation.php b/src/Model/Contact/Relation.php index 89a1104f8a..397c25720c 100644 --- a/src/Model/Contact/Relation.php +++ b/src/Model/Contact/Relation.php @@ -829,27 +829,23 @@ class Relation DI::logger()->debug('Calculation - start', ['uid' => $uid, 'cid' => $contact_id, 'days' => $days]); $follow = Verb::getID(Activity::FOLLOW); - $view = Verb::getID(Activity::VIEW); - $read = Verb::getID(Activity::READ); DBA::update('contact-relation', ['score' => 0, 'relation-score' => 0, 'thread-score' => 0, 'relation-thread-score' => 0], ['relation-cid' => $contact_id]); $total = DBA::fetchFirst( - "SELECT count(*) AS `activity` FROM `post-user` INNER JOIN `post` ON `post`.`uri-id` = `post-user`.`thr-parent-id` WHERE `post-user`.`author-id` = ? AND `post-user`.`received` >= ? AND `post-user`.`uid` = ? AND `post`.`author-id` != ? AND NOT `post`.`vid` IN (?, ?, ?)", + "SELECT count(*) AS `activity` FROM `post-user` INNER JOIN `post` ON `post`.`uri-id` = `post-user`.`thr-parent-id` WHERE `post-user`.`author-id` = ? AND `post-user`.`received` >= ? AND `post-user`.`uid` = ? AND `post`.`author-id` != ? AND `post`.`vid` != ?", $contact_id, DateTimeFormat::utc('now - ' . $days . ' day'), $uid, $contact_id, - $follow, - $view, - $read + $follow ); DI::logger()->debug('Calculate relation-score', ['uid' => $uid, 'total' => $total['activity']]); $interactions = DBA::p( "SELECT `post`.`author-id`, count(*) AS `activity`, EXISTS(SELECT `pid` FROM `account-user-view` WHERE `pid` = `post`.`author-id` AND `uid` = ? AND `rel` IN (?, ?)) AS `follows` - FROM `post-user` INNER JOIN `post` ON `post`.`uri-id` = `post-user`.`thr-parent-id` WHERE `post-user`.`author-id` = ? AND `post-user`.`received` >= ? AND `post-user`.`uid` = ? AND `post`.`author-id` != ? AND NOT `post`.`vid` IN (?, ?, ?) GROUP BY `post`.`author-id`", + FROM `post-user` INNER JOIN `post` ON `post`.`uri-id` = `post-user`.`thr-parent-id` WHERE `post-user`.`author-id` = ? AND `post-user`.`received` >= ? AND `post-user`.`uid` = ? AND `post`.`author-id` != ? AND `post`.`vid` != ? GROUP BY `post`.`author-id`", $uid, Contact::SHARING, Contact::FRIEND, @@ -857,9 +853,7 @@ class Relation DateTimeFormat::utc('now - ' . $days . ' day'), $uid, $contact_id, - $follow, - $view, - $read + $follow ); while ($interaction = DBA::fetch($interactions)) { $score = min((int)(($interaction['activity'] / $total['activity']) * 65535), 65535); @@ -868,21 +862,19 @@ class Relation DBA::close($interactions); $total = DBA::fetchFirst( - "SELECT count(*) AS `activity` FROM `post-user` INNER JOIN `post` ON `post`.`uri-id` = `post-user`.`parent-uri-id` WHERE `post-user`.`author-id` = ? AND `post-user`.`received` >= ? AND `post-user`.`uid` = ? AND `post`.`author-id` != ? AND NOT `post`.`vid` IN (?, ?, ?)", + "SELECT count(*) AS `activity` FROM `post-user` INNER JOIN `post` ON `post`.`uri-id` = `post-user`.`parent-uri-id` WHERE `post-user`.`author-id` = ? AND `post-user`.`received` >= ? AND `post-user`.`uid` = ? AND `post`.`author-id` != ? AND `post`.`vid` != ?", $contact_id, DateTimeFormat::utc('now - ' . $days . ' day'), $uid, $contact_id, - $follow, - $view, - $read + $follow ); DI::logger()->debug('Calculate relation-thread-score', ['uid' => $uid, 'total' => $total['activity']]); $interactions = DBA::p( "SELECT `post`.`author-id`, count(*) AS `activity`, EXISTS(SELECT `pid` FROM `account-user-view` WHERE `pid` = `post`.`author-id` AND `uid` = ? AND `rel` IN (?, ?)) AS `follows` - FROM `post-user` INNER JOIN `post` ON `post`.`uri-id` = `post-user`.`parent-uri-id` WHERE `post-user`.`author-id` = ? AND `post-user`.`received` >= ? AND `post-user`.`uid` = ? AND `post`.`author-id` != ? AND NOT `post`.`vid` IN (?, ?, ?) GROUP BY `post`.`author-id`", + FROM `post-user` INNER JOIN `post` ON `post`.`uri-id` = `post-user`.`parent-uri-id` WHERE `post-user`.`author-id` = ? AND `post-user`.`received` >= ? AND `post-user`.`uid` = ? AND `post`.`author-id` != ? AND `post`.`vid` != ? GROUP BY `post`.`author-id`", $uid, Contact::SHARING, Contact::FRIEND, @@ -890,9 +882,7 @@ class Relation DateTimeFormat::utc('now - ' . $days . ' day'), $uid, $contact_id, - $follow, - $view, - $read + $follow ); while ($interaction = DBA::fetch($interactions)) { $score = min((int)(($interaction['activity'] / $total['activity']) * 65535), 65535); @@ -901,27 +891,23 @@ class Relation DBA::close($interactions); $total = DBA::fetchFirst( - "SELECT count(*) AS `activity` FROM `post-user` INNER JOIN `post` ON `post-user`.`uri-id` = `post`.`thr-parent-id` WHERE `post-user`.`author-id` = ? AND `post-user`.`received` >= ? AND `post-user`.`uid` = ? AND `post`.`author-id` != ? AND NOT `post`.`vid` IN (?, ?, ?)", + "SELECT count(*) AS `activity` FROM `post-user` INNER JOIN `post` ON `post-user`.`uri-id` = `post`.`thr-parent-id` WHERE `post-user`.`author-id` = ? AND `post-user`.`received` >= ? AND `post-user`.`uid` = ? AND `post`.`author-id` != ? AND `post`.`vid` != ?", $contact_id, DateTimeFormat::utc('now - ' . $days . ' day'), $uid, $contact_id, - $follow, - $view, - $read + $follow ); DI::logger()->debug('Calculate score', ['uid' => $uid, 'total' => $total['activity']]); $interactions = DBA::p( - "SELECT `post`.`author-id`, count(*) AS `activity` FROM `post-user` INNER JOIN `post` ON `post-user`.`uri-id` = `post`.`thr-parent-id` WHERE `post-user`.`author-id` = ? AND `post-user`.`received` >= ? AND `post-user`.`uid` = ? AND `post`.`author-id` != ? AND NOT `post`.`vid` IN (?, ?, ?) GROUP BY `post`.`author-id`", + "SELECT `post`.`author-id`, count(*) AS `activity` FROM `post-user` INNER JOIN `post` ON `post-user`.`uri-id` = `post`.`thr-parent-id` WHERE `post-user`.`author-id` = ? AND `post-user`.`received` >= ? AND `post-user`.`uid` = ? AND `post`.`author-id` != ? AND `post`.`vid` != ? GROUP BY `post`.`author-id`", $contact_id, DateTimeFormat::utc('now - ' . $days . ' day'), $uid, $contact_id, - $follow, - $view, - $read + $follow ); while ($interaction = DBA::fetch($interactions)) { $score = min((int)(($interaction['activity'] / $total['activity']) * 65535), 65535); @@ -930,27 +916,23 @@ class Relation DBA::close($interactions); $total = DBA::fetchFirst( - "SELECT count(*) AS `activity` FROM `post-user` INNER JOIN `post` ON `post-user`.`uri-id` = `post`.`parent-uri-id` WHERE `post-user`.`author-id` = ? AND `post-user`.`received` >= ? AND `post-user`.`uid` = ? AND `post`.`author-id` != ? AND NOT `post`.`vid` IN (?, ?, ?)", + "SELECT count(*) AS `activity` FROM `post-user` INNER JOIN `post` ON `post-user`.`uri-id` = `post`.`parent-uri-id` WHERE `post-user`.`author-id` = ? AND `post-user`.`received` >= ? AND `post-user`.`uid` = ? AND `post`.`author-id` != ? AND `post`.`vid` != ?", $contact_id, DateTimeFormat::utc('now - ' . $days . ' day'), $uid, $contact_id, - $follow, - $view, - $read + $follow ); DI::logger()->debug('Calculate thread-score', ['uid' => $uid, 'total' => $total['activity']]); $interactions = DBA::p( - "SELECT `post`.`author-id`, count(*) AS `activity` FROM `post-user` INNER JOIN `post` ON `post-user`.`uri-id` = `post`.`parent-uri-id` WHERE `post-user`.`author-id` = ? AND `post-user`.`received` >= ? AND `post-user`.`uid` = ? AND `post`.`author-id` != ? AND NOT `post`.`vid` IN (?, ?, ?) GROUP BY `post`.`author-id`", + "SELECT `post`.`author-id`, count(*) AS `activity` FROM `post-user` INNER JOIN `post` ON `post-user`.`uri-id` = `post`.`parent-uri-id` WHERE `post-user`.`author-id` = ? AND `post-user`.`received` >= ? AND `post-user`.`uid` = ? AND `post`.`author-id` != ? AND `post`.`vid` != ? GROUP BY `post`.`author-id`", $contact_id, DateTimeFormat::utc('now - ' . $days . ' day'), $uid, $contact_id, - $follow, - $view, - $read + $follow ); while ($interaction = DBA::fetch($interactions)) { $score = min((int)(($interaction['activity'] / $total['activity']) * 65535), 65535); diff --git a/src/Model/Item.php b/src/Model/Item.php index 9facded0fc..ba54a3e599 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -1162,6 +1162,9 @@ class Item self::reshareChannelPost($engagement_uri_id); } + if ($posted_item['origin'] && in_array($posted_item['verb'], [Activity::LIKE, Activity::DISLIKE, Activity::ATTEND, Activity::ATTENDNO, Activity::ATTENDMAYBE, Activity::ANNOUNCE, Activity::POST])) { + DI::contentItem()->setViewed($posted_item['thr-parent-id'], $posted_item['uid']); + } } if ($posted_item['uid'] !== 0 && ($posted_item['origin'] || !in_array($posted_item['network'], Protocol::FEDERATED))) { @@ -2572,7 +2575,7 @@ class Item return false; } - if (!Post::exists(['uri-id' => $item['parent-uri-id'], 'uid' => $uid])) { + if (!in_array($verb, ['view', 'unview']) && !Post::exists(['uri-id' => $item['parent-uri-id'], 'uid' => $uid])) { $stored = self::storeForUserByUriId($item['parent-uri-id'], $uid, ['post-reason' => Item::PR_ACTIVITY]); if (($item['parent-uri-id'] == $item['uri-id']) && !empty($stored)) { $item = Post::selectFirst(self::ITEM_FIELDLIST, ['id' => $stored]); @@ -2627,6 +2630,10 @@ class Item case 'unannounce': $activity = Activity::ANNOUNCE; break; + case 'view': + case 'unview': + $activity = Activity::VIEW; + break; default: DI::logger()->warning('unknown verb', ['verb' => $verb, 'item' => $item_id]); return false; diff --git a/src/Model/ItemHelper.php b/src/Model/ItemHelper.php index 4b348e4964..1476343f80 100644 --- a/src/Model/ItemHelper.php +++ b/src/Model/ItemHelper.php @@ -266,7 +266,10 @@ final class ItemHelper 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', 'wall', 'private', 'origin', 'author-id' ]; - $condition = ['uri-id' => [$item['thr-parent-id'], $item['parent-uri-id']], 'uid' => $item['uid']]; + + $uids = $item['verb'] === Activity::VIEW ? [0, $item['uid']] : $item['uid']; + + $condition = ['uri-id' => [$item['thr-parent-id'], $item['parent-uri-id']], 'uid' => $uids]; $params = ['order' => ['id' => false]]; $parent = Post::selectFirst($fields, $condition, $params); diff --git a/src/Model/Post/Engagement.php b/src/Model/Post/Engagement.php index e9c9e58cb1..e9e75acf69 100644 --- a/src/Model/Post/Engagement.php +++ b/src/Model/Post/Engagement.php @@ -108,11 +108,12 @@ class Engagement 'network' => $parent['network'], 'restricted' => !in_array($item['network'], Protocol::FEDERATED) || ($parent['private'] != Item::PUBLIC), 'comments' => DBA::count('post', ['parent-uri-id' => $item['parent-uri-id'], 'gravity' => Item::GRAVITY_COMMENT]), + 'views' => DBA::count('post', ['parent-uri-id' => $item['parent-uri-id'], 'gravity' => Item::GRAVITY_ACTIVITY, 'vid' => [Verb::getID(Activity::VIEW), Verb::getID(Activity::READ)]]), 'activities' => DBA::count('post', [ "`parent-uri-id` = ? AND `gravity` = ? AND NOT `vid` IN (?, ?, ?)", $item['parent-uri-id'], Item::GRAVITY_ACTIVITY, Verb::getID(Activity::FOLLOW), Verb::getID(Activity::VIEW), Verb::getID(Activity::READ) - ]) + ]), ]; if (!$store && ($engagement['comments'] == 0) && ($engagement['activities'] == 0)) { DI::logger()->debug('No media, follower, subscribed tags, comments or activities. Engagement not stored', ['fields' => $engagement]); diff --git a/src/Module/Api/Mastodon/Statuses.php b/src/Module/Api/Mastodon/Statuses.php index 6236e8eec3..2727951f02 100644 --- a/src/Module/Api/Mastodon/Statuses.php +++ b/src/Module/Api/Mastodon/Statuses.php @@ -394,6 +394,7 @@ class Statuses extends BaseApi if (Post::exists(['uri-id' => $this->parameters['id'], 'uid' => $uid, 'unseen' => true])) { Post::update(['unseen' => false], ['uri-id' => $this->parameters['id'], 'uid' => $uid, 'unseen' => true]); } + $this->item->setViewed($this->parameters['id'], $uid); } $this->jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, false)); diff --git a/src/Module/Conversation/Timeline.php b/src/Module/Conversation/Timeline.php index bbf700ce1d..42936ff1da 100644 --- a/src/Module/Conversation/Timeline.php +++ b/src/Module/Conversation/Timeline.php @@ -320,9 +320,9 @@ class Timeline extends BaseModule if ($this->selectedTab == ChannelEntity::WHATSHOT) { if (!$cache) { if (!is_null($this->accountType)) { - $condition = ["(`comments` > ? OR `activities` > ?) AND `contact-type` = ?", $this->channelRepository->getMedianComments($uid, 4), $this->channelRepository->getMedianActivities($uid, 4), $this->accountType]; + $condition = ["(`comments` > ? OR `activities` > ? OR `views` > ?) AND `contact-type` = ?", $this->channelRepository->getMedianComments($uid, 4), $this->channelRepository->getMedianActivities($uid, 4), $this->channelRepository->getMedianViews($uid, 4), $this->accountType]; } else { - $condition = ["(`comments` > ? OR `activities` > ?) AND `contact-type` != ?", $this->channelRepository->getMedianComments($uid, 4), $this->channelRepository->getMedianActivities($uid, 4), Contact::TYPE_COMMUNITY]; + $condition = ["(`comments` > ? OR `activities` > ? OR `views` > ?) AND `contact-type` != ?", $this->channelRepository->getMedianComments($uid, 4), $this->channelRepository->getMedianActivities($uid, 4), $this->channelRepository->getMedianViews($uid, 4), Contact::TYPE_COMMUNITY]; } } } elseif ($this->selectedTab == ChannelEntity::FORYOU) { @@ -331,9 +331,9 @@ class Timeline extends BaseModule $condition = [ "(`owner-id` IN (SELECT `cid` FROM `contact-relation` WHERE `relation-cid` = ? AND `relation-thread-score` > ?) OR - ((`comments` >= ? OR `activities` >= ?) AND `owner-id` IN (SELECT `cid` FROM `contact-relation` WHERE `follows` AND `relation-cid` = ?)) OR + ((`comments` >= ? OR `activities` >= ? OR `views` >= ?) AND `owner-id` IN (SELECT `cid` FROM `contact-relation` WHERE `follows` AND `relation-cid` = ?)) OR (`owner-id` IN (SELECT `cid` FROM `user-contact` WHERE `uid` = ? AND (`notify_new_posts` OR `channel-frequency` = ?))))", - $cid, $this->channelRepository->getMedianRelationThreadScore($cid, 4), $this->channelRepository->getMedianComments($uid, 4), $this->channelRepository->getMedianActivities($uid, 4), $cid, + $cid, $this->channelRepository->getMedianRelationThreadScore($cid, 4), $this->channelRepository->getMedianComments($uid, 4), $this->channelRepository->getMedianActivities($uid, 4), $this->channelRepository->getMedianViews($uid, 4), $cid, $uid, Contact\User::FREQUENCY_ALWAYS ]; } @@ -345,11 +345,11 @@ class Timeline extends BaseModule "`owner-id` IN (SELECT `cid` FROM `contact-relation` WHERE `relation-cid` = ? AND NOT `follows`) AND (`owner-id` IN (SELECT `cid` FROM `contact-relation` WHERE `relation-cid` = ? AND NOT `follows` AND `relation-thread-score` > ?) OR `owner-id` IN (SELECT `cid` FROM `contact-relation` WHERE `cid` = ? AND `relation-thread-score` > ?) OR - ((`comments` >= ? OR `activities` >= ?) AND + ((`comments` >= ? OR `activities` >= ? OR `views` >= ?) AND (`owner-id` IN (SELECT `cid` FROM `contact-relation` WHERE `cid` = ? AND `relation-thread-score` > ?)) OR (`owner-id` IN (SELECT `cid` FROM `contact-relation` WHERE `relation-cid` = ? AND `relation-thread-score` > ?))))", $cid, $cid, $this->channelRepository->getMedianRelationThreadScore($cid, 4), $cid, $this->channelRepository->getMedianRelationThreadScore($cid, 4), - $this->channelRepository->getMedianComments($uid, 4), $this->channelRepository->getMedianActivities($uid, 4), $cid, 0, $cid, 0 + $this->channelRepository->getMedianComments($uid, 4), $this->channelRepository->getMedianActivities($uid, 4), $this->channelRepository->getMedianViews($uid, 4), $cid, 0, $cid, 0 ]; } } elseif ($this->selectedTab == ChannelEntity::FOLLOWERS) { diff --git a/src/Module/Item/Display.php b/src/Module/Item/Display.php index 609cc12f77..ede4bace2a 100644 --- a/src/Module/Item/Display.php +++ b/src/Module/Item/Display.php @@ -89,7 +89,7 @@ class Display extends BaseModule $item = null; $itemUid = $this->session->getLocalUserId(); - $fields = ['uri-id', 'parent-uri-id', 'author-id', 'author-link', 'contact-id', 'contact-contact-type', 'body', 'uid', 'guid', 'gravity', + $fields = ['id', 'uri-id', 'parent-uri-id', 'author-id', 'author-link', 'contact-id', 'contact-contact-type', 'body', 'uid', 'guid', 'gravity', 'plink', 'origin', 'uri', 'post-reason', 'owner-contact-type', 'owner-network', 'owner-id', 'guid', 'author-network', 'author-alias', 'private']; @@ -148,6 +148,10 @@ class Display extends BaseModule $this->notify->setAllSeenForUser($this->session->getLocalUserId(), ['parent-uri-id' => $item['parent-uri-id']]); } + if ($this->session->getLocalUserId() != 0) { + $this->contentItem->setViewed($item['uri-id'], $this->session->getLocalUserId()); + } + $this->displaySidebar($item); $this->displayHead($item['uri-id'], $item['parent-uri-id']); diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index a876046452..9fefca3f53 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -44,7 +44,7 @@ use Friendica\Database\DBA; // This file is required several times during the test in DbaDefinition which justifies this condition if (!defined('DB_UPDATE_VERSION')) { - define('DB_UPDATE_VERSION', 1587); + define('DB_UPDATE_VERSION', 1588); } return [ @@ -1359,6 +1359,7 @@ return [ "restricted" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "If true, this post is either unlisted or not from a federated network"], "comments" => ["type" => "mediumint unsigned", "comment" => "Number of comments"], "activities" => ["type" => "mediumint unsigned", "comment" => "Number of activities (like, dislike, ...)"], + "views" => ["type" => "mediumint unsigned", "comment" => "Number of views"], ], "indexes" => [ "PRIMARY" => ["uri-id"], diff --git a/static/dbview.config.php b/static/dbview.config.php index 0d2615bffa..db8c6a1ec0 100644 --- a/static/dbview.config.php +++ b/static/dbview.config.php @@ -65,8 +65,9 @@ return [ "network" => ["post-engagement", "network"], "contact-type" => ["ownercontact", "contact-type"], "restricted" => ["post-engagement", "restricted"], - "comments" => "0", - "activities" => "0", + "comments" => ["post-engagement", "comments"], + "activities" => ["post-engagement", "activities"], + "views" => ["post-engagement", "views"], ], "query" => "FROM `channel-post` INNER JOIN `post-engagement` ON `post-engagement`.`uri-id` = `channel-post`.`uri-id` @@ -93,8 +94,9 @@ return [ "network" => ["post-engagement", "network"], "contact-type" => ["ownercontact", "contact-type"], "restricted" => ["post-engagement", "restricted"], - "comments" => "0", - "activities" => "0", + "comments" => ["post-engagement", "comments"], + "activities" => ["post-engagement", "activities"], + "views" => ["post-engagement", "views"], ], "query" => "FROM `system-channel-post` INNER JOIN `post-engagement` ON `post-engagement`.`uri-id` = `system-channel-post`.`uri-id` @@ -159,8 +161,9 @@ return [ "network" => ["post-thread-user", "network"], "protocol" => ["post-user", "protocol"], "restricted" => ["post-engagement", "restricted"], - "comments" => "0", - "activities" => "0", + "comments" => ["post-engagement", "comments"], + "activities" => ["post-engagement", "activities"], + "views" => ["post-engagement", "views"], ], "query" => "FROM `post-thread-user` INNER JOIN `post-engagement` ON `post-engagement`.`uri-id` = `post-thread-user`.`uri-id` @@ -182,9 +185,9 @@ return [ "gravity" => ["post-user", "gravity"], "created" => ["post-user", "created"], "edited" => ["post-user", "edited"], - "commented" => ["post-thread-user", "commented"], + "commented" => ["post-thread", "commented"], "received" => ["post-user", "received"], - "changed" => ["post-thread-user", "changed"], + "changed" => ["post-thread", "changed"], "private" => ["post-user", "private"], "visible" => ["post-user", "visible"], "deleted" => ["post-user", "deleted"], @@ -210,12 +213,12 @@ return [ "causer-id" => ["post-user", "causer-id"], "causer-blocked" => ["causer", "blocked"], "causer-gsid" => ["causer", "gsid"], - "parent-network" => ["post-thread-user", "network"], - "parent-owner-id" => ["post-thread-user", "owner-id"], - "parent-author-id" => ["post-thread-user", "author-id"], + "parent-network" => ["post-thread", "network"], + "parent-owner-id" => ["post-thread", "owner-id"], + "parent-author-id" => ["post-thread", "author-id"], ], "query" => "FROM `post-user` - LEFT JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid` + LEFT JOIN `post-thread` ON `post-thread`.`uri-id` = `post-user`.`parent-uri-id` STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-user`.`contact-id` STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `post-user`.`author-id` STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = `post-user`.`owner-id` @@ -228,9 +231,9 @@ return [ "gravity" => ["post-origin", "gravity"], "created" => ["post-origin", "created"], "edited" => ["post-user", "edited"], - "commented" => ["post-thread-user", "commented"], + "commented" => ["post-thread", "commented"], "received" => ["post-origin", "received"], - "changed" => ["post-thread-user", "changed"], + "changed" => ["post-thread", "changed"], "private" => ["post-origin", "private"], "visible" => ["post-user", "visible"], "deleted" => ["post-user", "deleted"], @@ -259,7 +262,7 @@ return [ ], "query" => "FROM `post-origin` INNER JOIN `post-user` ON `post-user`.`id` = `post-origin`.`id` - LEFT JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-origin`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-origin`.`uid` + LEFT JOIN `post-thread` ON `post-thread`.`uri-id` = `post-origin`.`parent-uri-id` STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-user`.`contact-id` STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `post-user`.`author-id` STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = `post-user`.`owner-id` @@ -282,6 +285,7 @@ return [ "restricted" => ["post-searchindex", "restricted"], "comments" => "0", "activities" => "0", + "views" => "0", ], "query" => "FROM `post-thread-user` INNER JOIN `post-searchindex` ON `post-searchindex`.`uri-id` = `post-thread-user`.`uri-id` @@ -694,9 +698,9 @@ return [ "thr-parent" => ["thr-parent-item-uri", "uri"], "thr-parent-id" => ["post-user", "thr-parent-id"], "conversation" => ["conversation-item-uri", "uri"], - "conversation-id" => ["post-thread-user", "conversation-id"], + "conversation-id" => ["post-thread", "conversation-id"], "context" => ["context-item-uri", "uri"], - "context-id" => ["post-thread-user", "context-id"], + "context-id" => ["post-thread", "context-id"], "quote-uri" => ["quote-item-uri", "uri"], "quote-uri-id" => ["post-content", "quote-uri-id"], "guid" => ["item-uri", "guid"], @@ -708,9 +712,9 @@ return [ "replies-id" => ["post-user", "replies-id"], "created" => ["post-user", "created"], "edited" => ["post-user", "edited"], - "commented" => ["post-thread-user", "commented"], + "commented" => ["post-thread", "commented"], "received" => ["post-user", "received"], - "changed" => ["post-thread-user", "changed"], + "changed" => ["post-thread", "changed"], "post-type" => ["post-user", "post-type"], "post-reason" => ["post-user", "post-reason"], "private" => ["post-user", "private"], @@ -842,16 +846,17 @@ return [ "has-media" => "EXISTS(SELECT `id` FROM `post-media` WHERE `post-media`.`uri-id` = `post-user`.`uri-id`)", "signed_text" => ["diaspora-interaction", "interaction"], "parent-guid" => ["parent-item-uri", "guid"], - "parent-network" => ["post-thread-user", "network"], - "parent-owner-id" => ["post-thread-user", "owner-id"], - "parent-author-id" => ["post-thread-user", "author-id"], + "parent-network" => ["post-thread", "network"], + "parent-owner-id" => ["post-thread", "owner-id"], + "parent-author-id" => ["post-thread", "author-id"], "parent-author-link" => ["parent-post-author", "url"], "parent-author-name" => ["parent-post-author", "name"], "parent-author-nick" => ["parent-post-author", "nick"], "parent-author-network" => ["parent-post-author", "network"], ], "query" => "FROM `post-user` - INNER JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid` + LEFT JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid` + INNER JOIN `post-thread` ON `post-thread`.`uri-id` = `post-user`.`parent-uri-id` STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-user`.`contact-id` STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `post-user`.`author-id` STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = `post-user`.`owner-id` @@ -859,8 +864,8 @@ return [ LEFT JOIN `item-uri` ON `item-uri`.`id` = `post-user`.`uri-id` LEFT JOIN `item-uri` AS `thr-parent-item-uri` ON `thr-parent-item-uri`.`id` = `post-user`.`thr-parent-id` LEFT JOIN `item-uri` AS `parent-item-uri` ON `parent-item-uri`.`id` = `post-user`.`parent-uri-id` - LEFT JOIN `item-uri` AS `conversation-item-uri` ON `conversation-item-uri`.`id` = `post-thread-user`.`conversation-id` - LEFT JOIN `item-uri` AS `context-item-uri` ON `context-item-uri`.`id` = `post-thread-user`.`context-id` + LEFT JOIN `item-uri` AS `conversation-item-uri` ON `conversation-item-uri`.`id` = `post-thread`.`conversation-id` + LEFT JOIN `item-uri` AS `context-item-uri` ON `context-item-uri`.`id` = `post-thread`.`context-id` LEFT JOIN `item-uri` AS `external-item-uri` ON `external-item-uri`.`id` = `post-user`.`external-id` LEFT JOIN `item-uri` AS `replies-item-uri` ON `replies-item-uri`.`id` = `post-user`.`replies-id` LEFT JOIN `verb` ON `verb`.`id` = `post-user`.`vid` @@ -871,7 +876,7 @@ return [ LEFT JOIN `post-delivery-data` ON `post-delivery-data`.`uri-id` = `post-user`.`uri-id` AND `post-user`.`origin` LEFT JOIN `post-question` ON `post-question`.`uri-id` = `post-user`.`uri-id` LEFT JOIN `permissionset` ON `permissionset`.`id` = `post-user`.`psid` - LEFT JOIN `contact` AS `parent-post-author` ON `parent-post-author`.`id` = `post-thread-user`.`author-id`" + LEFT JOIN `contact` AS `parent-post-author` ON `parent-post-author`.`id` = `post-thread`.`author-id`" ], "post-thread-user-view" => [ "fields" => [ From e647dcf54ee590e66e1d9fcdc6b537955916cd64 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 8 Feb 2026 11:54:51 +0000 Subject: [PATCH 043/197] Issue 15456: Fix login to Bridgy Fed --- database.sql | 4 ++-- doc/en/spec/database/db-application.md | 2 +- static/dbstructure.config.php | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/database.sql b/database.sql index 8062072567..2fd7625bee 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2026.04-dev (Blutwurz) --- DB_UPDATE_VERSION 1588 +-- DB_UPDATE_VERSION 1589 -- ------------------------------------------ @@ -414,7 +414,7 @@ CREATE TABLE IF NOT EXISTS `application` ( `name` varchar(255) NOT NULL COMMENT '', `redirect_uri` varbinary(383) NOT NULL COMMENT '', `website` varbinary(383) COMMENT '', - `scopes` varchar(255) COMMENT '', + `scopes` varchar(511) COMMENT '', `read` boolean COMMENT 'Read scope', `write` boolean COMMENT 'Write scope', `follow` boolean COMMENT 'Follow scope', diff --git a/doc/en/spec/database/db-application.md b/doc/en/spec/database/db-application.md index 2b13367e38..4457c519c4 100644 --- a/doc/en/spec/database/db-application.md +++ b/doc/en/spec/database/db-application.md @@ -12,7 +12,7 @@ OAuth application | name | | varchar(255) | NO | | NULL | | | redirect_uri | | varbinary(383) | NO | | NULL | | | website | | varbinary(383) | YES | | NULL | | -| scopes | | varchar(255) | YES | | NULL | | +| scopes | | varchar(511) | YES | | NULL | | | read | Read scope | boolean | YES | | NULL | | | write | Write scope | boolean | YES | | NULL | | | follow | Follow scope | boolean | YES | | NULL | | diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index 9fefca3f53..7a4aad4acd 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -44,7 +44,7 @@ use Friendica\Database\DBA; // This file is required several times during the test in DbaDefinition which justifies this condition if (!defined('DB_UPDATE_VERSION')) { - define('DB_UPDATE_VERSION', 1588); + define('DB_UPDATE_VERSION', 1589); } return [ @@ -459,7 +459,7 @@ return [ "name" => ["type" => "varchar(255)", "not null" => "1", "comment" => ""], "redirect_uri" => ["type" => "varbinary(383)", "not null" => "1", "comment" => ""], "website" => ["type" => "varbinary(383)", "comment" => ""], - "scopes" => ["type" => "varchar(255)", "comment" => ""], + "scopes" => ["type" => "varchar(511)", "comment" => ""], "read" => ["type" => "boolean", "comment" => "Read scope"], "write" => ["type" => "boolean", "comment" => "Write scope"], "follow" => ["type" => "boolean", "comment" => "Follow scope"], From 05da451545b528c0fbe068889e44cffb37599611 Mon Sep 17 00:00:00 2001 From: Marcus Funch Date: Sun, 5 Oct 2025 12:12:02 +0200 Subject: [PATCH 044/197] Update the text on Frio's config page --- view/lang/C/messages.po | 56 +++++++++++++++++------------------ view/theme/frio/config.php | 8 ++--- view/theme/frio/php/Image.php | 2 +- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index 01f7698fd2..643e538da4 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 2026.04-dev\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-02-06 11:45+0100\n" +"POT-Creation-Date: 2026-02-08 14:11+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -1848,7 +1848,7 @@ msgstr "" msgid "Find groups to join" msgstr "" -#: src/Content/Item.php:336 src/Model/Item.php:2834 +#: src/Content/Item.php:336 src/Model/Item.php:2841 msgid "event" msgstr "" @@ -1856,7 +1856,7 @@ msgstr "" msgid "status" msgstr "" -#: src/Content/Item.php:345 src/Model/Item.php:2836 +#: src/Content/Item.php:345 src/Model/Item.php:2843 #: src/Module/Post/Tag/Add.php:112 msgid "photo" msgstr "" @@ -2275,8 +2275,8 @@ msgstr "" msgid "%2$s %3$s" msgstr "" -#: src/Content/Text/BBCode.php:945 src/Model/Item.php:3724 -#: src/Model/Item.php:3730 src/Model/Item.php:3731 +#: src/Content/Text/BBCode.php:945 src/Model/Item.php:3731 +#: src/Model/Item.php:3737 src/Model/Item.php:3738 msgid "Link to source" msgstr "" @@ -3421,84 +3421,84 @@ msgstr "" msgid "Happy Birthday %s" msgstr "" -#: src/Model/Item.php:2838 +#: src/Model/Item.php:2845 msgid "activity" msgstr "" -#: src/Model/Item.php:2840 +#: src/Model/Item.php:2847 msgid "comment" msgstr "" -#: src/Model/Item.php:2843 src/Module/Post/Tag/Add.php:112 +#: src/Model/Item.php:2850 src/Module/Post/Tag/Add.php:112 msgid "post" msgstr "" -#: src/Model/Item.php:3032 +#: src/Model/Item.php:3039 #, php-format msgid "%s is blocked" msgstr "" -#: src/Model/Item.php:3034 +#: src/Model/Item.php:3041 #, php-format msgid "%s is ignored" msgstr "" -#: src/Model/Item.php:3036 +#: src/Model/Item.php:3043 #, php-format msgid "Content from %s is collapsed" msgstr "" -#: src/Model/Item.php:3040 +#: src/Model/Item.php:3047 msgid "Sensitive content" msgstr "" -#: src/Model/Item.php:3594 +#: src/Model/Item.php:3601 msgid "bytes" msgstr "" -#: src/Model/Item.php:3628 +#: src/Model/Item.php:3635 #, php-format msgid "The media in this post is not displayed to visitors. To view it, please go to the original post." msgstr "" -#: src/Model/Item.php:3630 +#: src/Model/Item.php:3637 msgid "The media in this post is not displayed to visitors. To view it, please log in." msgstr "" -#: src/Model/Item.php:3655 +#: src/Model/Item.php:3662 #, php-format msgid "%2$s (%3$d%%, %1$d vote)" msgid_plural "%2$s (%3$d%%, %1$d votes)" msgstr[0] "" msgstr[1] "" -#: src/Model/Item.php:3657 +#: src/Model/Item.php:3664 #, php-format msgid "%2$s (%1$d vote)" msgid_plural "%2$s (%1$d votes)" msgstr[0] "" msgstr[1] "" -#: src/Model/Item.php:3662 +#: src/Model/Item.php:3669 #, php-format msgid "%d voter. Poll end: %s" msgid_plural "%d voters. Poll end: %s" msgstr[0] "" msgstr[1] "" -#: src/Model/Item.php:3664 +#: src/Model/Item.php:3671 #, php-format msgid "%d voter." msgid_plural "%d voters." msgstr[0] "" msgstr[1] "" -#: src/Model/Item.php:3666 +#: src/Model/Item.php:3673 #, php-format msgid "Poll end: %s" msgstr "" -#: src/Model/Item.php:3707 src/Model/Item.php:3708 +#: src/Model/Item.php:3714 src/Model/Item.php:3715 msgid "View on separate page" msgstr "" @@ -7282,7 +7282,7 @@ msgstr "" msgid "You can make this page always open when you use the New Post button in the Theme Customization settings." msgstr "" -#: src/Module/Item/Display.php:164 +#: src/Module/Item/Display.php:168 #, php-format msgid "Post by %s" msgstr "" @@ -11991,7 +11991,7 @@ msgid "Note" msgstr "" #: view/theme/frio/config.php:153 -msgid "Check image permissions if all users are allowed to see the image" +msgid "Ensure that the image has the correct permissions, allowing all users to view it." msgstr "" #: view/theme/frio/config.php:158 @@ -12007,11 +12007,11 @@ msgid "Accent color" msgstr "" #: view/theme/frio/config.php:162 -msgid "Copy or paste schemestring" +msgid "Copy or paste theme settings" msgstr "" #: view/theme/frio/config.php:162 -msgid "You can copy this string to share your theme with others. Pasting here applies the schemestring" +msgid "You can copy this text to share your theme settings with others. Pasting here updates the theme settings below. Afterwards, if you want, click the save button below to use the new settings." msgstr "" #: view/theme/frio/config.php:163 @@ -12047,7 +12047,7 @@ msgid "Always open Compose page" msgstr "" #: view/theme/frio/config.php:172 -msgid "The New Post button always open the Compose page instead of the modal form. When this is disabled, the Compose page can be accessed with a middle click on the link or from the modal." +msgid "If enabled, the button to make a new post always opens a dedicated page (the Compose page) instead of a small window on top of the current page. When disabled, the \"Compose page\" can be accessed with a middle click on the button to make a new post, or via a button in the small window." msgstr "" #: view/theme/frio/config.php:176 @@ -12059,7 +12059,7 @@ msgid "Login page background color" msgstr "" #: view/theme/frio/config.php:180 -msgid "Leave background image and color empty for theme defaults" +msgid "Leave background image and color empty to use theme defaults." msgstr "" #: view/theme/frio/php/Image.php:27 @@ -12083,7 +12083,7 @@ msgid "Single row mosaic" msgstr "" #: view/theme/frio/php/Image.php:29 -msgid "Resize image to repeat it on a single row, either vertical or horizontal." +msgid "Resize image to repeat it in a single direction, either vertical or horizontal." msgstr "" #: view/theme/frio/php/Image.php:30 diff --git a/view/theme/frio/config.php b/view/theme/frio/config.php index 6d36fa443f..c0798b19ca 100644 --- a/view/theme/frio/config.php +++ b/view/theme/frio/config.php @@ -150,7 +150,7 @@ function frio_form($arr) $scheme_info = get_scheme_info($arr['scheme']); $disable = $scheme_info['overwrites']; - $background_image_help = '' . DI::l10n()->t('Note') . ': ' . DI::l10n()->t('Check image permissions if all users are allowed to see the image'); + $background_image_help = '' . DI::l10n()->t('Note') . ': ' . DI::l10n()->t('Ensure that the image has the correct permissions, allowing all users to view it.'); $t = Renderer::getMarkupTemplate('theme_settings.tpl'); $ctx = [ @@ -159,7 +159,7 @@ function frio_form($arr) '$title' => DI::l10n()->t('Theme settings'), '$scheme' => ['frio_scheme', DI::l10n()->t('Appearance'), $arr['scheme'], frio_scheme_get_list()], '$scheme_accent' => !$scheme_info['accented'] ? '' : ['frio_scheme_accent', DI::l10n()->t('Accent color'), $arr['scheme_accent']], - '$share_string' => $arr['scheme'] != FRIO_CUSTOM_SCHEME ? '' : ['frio_share_string', DI::l10n()->t('Copy or paste schemestring'), $arr['share_string'], DI::l10n()->t('You can copy this string to share your theme with others. Pasting here applies the schemestring'), false, false], + '$share_string' => $arr['scheme'] != FRIO_CUSTOM_SCHEME ? '' : ['frio_share_string', DI::l10n()->t('Copy or paste theme settings'), $arr['share_string'], DI::l10n()->t('You can copy this text to share your theme settings with others. Pasting here updates the theme settings below. Afterwards, if you want, click the save button below to use the new settings.'), false, false], '$nav_bg' => array_key_exists('nav_bg', $disable) ? '' : ['frio_nav_bg', DI::l10n()->t('Navigation bar background color'), $arr['nav_bg'], '', false], '$nav_icon_color' => array_key_exists('nav_icon_color', $disable) ? '' : ['frio_nav_icon_color', DI::l10n()->t('Navigation bar icon color '), $arr['nav_icon_color'], '', false], '$link_color' => array_key_exists('link_color', $disable) ? '' : ['frio_link_color', DI::l10n()->t('Link color'), $arr['link_color'], '', false], @@ -169,7 +169,7 @@ function frio_form($arr) '$bg_image_options_title' => DI::l10n()->t('Background image style'), '$bg_image_options' => Image::get_options($arr), - '$always_open_compose' => ['frio_always_open_compose', DI::l10n()->t('Always open Compose page'), $arr['always_open_compose'], DI::l10n()->t('The New Post button always open the Compose page instead of the modal form. When this is disabled, the Compose page can be accessed with a middle click on the link or from the modal.')], + '$always_open_compose' => ['frio_always_open_compose', DI::l10n()->t('Always open Compose page'), $arr['always_open_compose'], DI::l10n()->t('If enabled, the button to make a new post always opens a dedicated page (the Compose page) instead of a small window on top of the current page. When disabled, the "Compose page" can be accessed with a middle click on the button to make a new post, or via a button in the small window.')], ]; if (array_key_exists('login_bg_image', $arr) && !array_key_exists('login_bg_image', $disable)) { @@ -177,7 +177,7 @@ function frio_form($arr) } if (array_key_exists('login_bg_color', $arr) && !array_key_exists('login_bg_color', $disable)) { - $ctx['$login_bg_color'] = ['frio_login_bg_color', DI::l10n()->t('Login page background color'), $arr['login_bg_color'], DI::l10n()->t('Leave background image and color empty for theme defaults'), false]; + $ctx['$login_bg_color'] = ['frio_login_bg_color', DI::l10n()->t('Login page background color'), $arr['login_bg_color'], DI::l10n()->t('Leave background image and color empty to use theme defaults.'), false]; } return Renderer::replaceMacros($t, $ctx); diff --git a/view/theme/frio/php/Image.php b/view/theme/frio/php/Image.php index 6e8fa5028f..dbfc13ac47 100644 --- a/view/theme/frio/php/Image.php +++ b/view/theme/frio/php/Image.php @@ -26,7 +26,7 @@ class Image $bg_image_options = [ 'stretch' => ['frio_bg_image_option', DI::l10n()->t('Top Banner'), 'stretch', DI::l10n()->t('Resize image to the width of the screen and show background color below on long pages.'), ($arr['bg_image_option'] == 'stretch')], 'cover' => ['frio_bg_image_option', DI::l10n()->t('Full screen'), 'cover', DI::l10n()->t('Resize image to fill entire screen, clipping either the right or the bottom.'), ($arr['bg_image_option'] == 'cover')], - 'contain' => ['frio_bg_image_option', DI::l10n()->t('Single row mosaic'), 'contain', DI::l10n()->t('Resize image to repeat it on a single row, either vertical or horizontal.'), ($arr['bg_image_option'] == 'contain')], + 'contain' => ['frio_bg_image_option', DI::l10n()->t('Single row mosaic'), 'contain', DI::l10n()->t('Resize image to repeat it in a single direction, either vertical or horizontal.'), ($arr['bg_image_option'] == 'contain')], 'repeat' => ['frio_bg_image_option', DI::l10n()->t('Mosaic'), 'repeat', DI::l10n()->t('Repeat image to fill the screen.'), ($arr['bg_image_option'] == 'repeat')], ]; From dddca40d75678f299bc72c9cf8115d3a092fc2b7 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 8 Feb 2026 11:33:12 +0000 Subject: [PATCH 045/197] Issue 14583: Avoid empty entries in list of trending links --- src/Module/Api/Mastodon/Trends/Links.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Module/Api/Mastodon/Trends/Links.php b/src/Module/Api/Mastodon/Trends/Links.php index bd288bda69..5f736c6578 100644 --- a/src/Module/Api/Mastodon/Trends/Links.php +++ b/src/Module/Api/Mastodon/Trends/Links.php @@ -8,7 +8,6 @@ namespace Friendica\Module\Api\Mastodon\Trends; use Friendica\Core\Protocol; -use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Post; @@ -26,7 +25,7 @@ class Links extends BaseApi protected function rawContent(array $request = []) { $request = $this->getRequest([ - 'limit' => 10, // Maximum number of results to return. Defaults to 10. + 'limit' => 10, // Maximum number of results to return. Defaults to 10. 'offset' => 0, // Offset in set, Defaults to 0. ], $request); @@ -37,8 +36,11 @@ class Links extends BaseApi $trending = []; $statuses = Post::selectPostThread(['uri-id', 'total-comments', 'total-actors'], $condition, ['limit' => [$request['offset'], $request['limit']], 'offset' => $request['offset'], 'order' => ['total-actors' => true]]); while ($status = Post::fetch($statuses)) { - $history = [['day' => (string)time(), 'uses' => (string)$status['total-comments'], 'accounts' => (string)$status['total-actors']]]; - $trending[] = DI::mstdnCard()->createFromUriId($status['uri-id'], $history)->toArray(); + $history = [['day' => (string)time(), 'uses' => (string)$status['total-comments'], 'accounts' => (string)$status['total-actors']]]; + $link = DI::mstdnCard()->createFromUriId($status['uri-id'], $history)->toArray(); + if ($link) { + $trending[] = $link; + } } DBA::close($statuses); From a40e2f3beef39044a881c1f3000de5e516b28de7 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 8 Feb 2026 16:39:37 +0000 Subject: [PATCH 046/197] Issue 15478: Prevent comments when blocked or is blocked --- src/Model/ItemHelper.php | 12 +++++++++++- src/Object/Post.php | 4 ++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Model/ItemHelper.php b/src/Model/ItemHelper.php index 1476343f80..0a56eb23a2 100644 --- a/src/Model/ItemHelper.php +++ b/src/Model/ItemHelper.php @@ -368,7 +368,7 @@ final class ItemHelper return $item; } - private function hasRestrictions(array $item, int $author_id, int $restrictions = null): bool + private function hasRestrictions(array $item, int $author_id, ?int $restrictions = null): bool { if (empty($restrictions) || ($author_id == $item['author-id'])) { return false; @@ -396,6 +396,16 @@ final class ItemHelper return true; } + if ($item['uid'] != 0 && Contact\User::isBlocked($item['author-id'], $item['uid'])) { + $this->logger->debug('Author is blocked by the user, post is ignored.', ['author' => $item['author-id'], 'uid' => $item['uid']]); + return true; + } + + if ($item['uid'] != 0 && Contact\User::isIsBlocked($author_id, $item['uid'])) { + $this->logger->debug('User is blocked by the author, post is ignored.', ['author' => $author_id, 'uid' => $item['uid']]); + return true; + } + return false; } diff --git a/src/Object/Post.php b/src/Object/Post.php index 1a4e1f57de..45fbb9f0aa 100644 --- a/src/Object/Post.php +++ b/src/Object/Post.php @@ -223,6 +223,10 @@ class Post $edpost = false; if (DI::userSession()->getLocalUserId()) { + if ($commentable && Contact\User::isIsBlocked($item['author-id'], DI::userSession()->getLocalUserId())) { + $commentable = false; + } + if (Strings::compareLink(DI::session()->get('my_url'), $item['author-link'])) { if ($item['event-id'] != 0) { $edpost = ['calendar/event/edit/' . $item['event-id'], DI::l10n()->t('Edit')]; From bf3e2c306ff443ef6a60be078db57820d8c37e0b Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 8 Feb 2026 16:48:10 +0000 Subject: [PATCH 047/197] Add quoted post as attachment when it couldn't be fetched --- src/Protocol/ActivityPub/Processor.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 57849e9cde..33b014e6ee 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -984,7 +984,8 @@ class Processor $item['quote-uri-id'] = ItemURI::getIdByURI($activity['quote-url']); DI::logger()->info('Quote is queued but not processed yet', ['uri' => $item['uri'], 'uri-id' => $item['uri-id'], 'quote' => $activity['quote-url'], 'quote-uri-id' => $item['quote-uri-id']]); } else { - DI::logger()->notice('Quote was not fetched', ['uri' => $item['uri'], 'uri-id' => $item['uri-id'], 'quote' => $activity['quote-url']]); + DI::logger()->notice('Quote was not fetched, link will be added instead as attachment.', ['uri' => $item['uri'], 'uri-id' => $item['uri-id'], 'quote' => $activity['quote-url']]); + self::storeAttachmentAsMedia($item['uri-id'], ['url' => $activity['quote-url']]); } } From 60823c07fe0673ce36de0acb148564ecd440730b Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 9 Feb 2026 21:02:35 +0000 Subject: [PATCH 048/197] Two slow database queries fixed --- database.sql | 1 + doc/en/spec/database/db-contact.md | 1 + src/Model/Item.php | 2 +- src/Module/Api/Mastodon/Directory.php | 6 ++++-- static/dbstructure.config.php | 1 + 5 files changed, 8 insertions(+), 3 deletions(-) diff --git a/database.sql b/database.sql index 2fd7625bee..e15d19ca7d 100644 --- a/database.sql +++ b/database.sql @@ -236,6 +236,7 @@ CREATE TABLE IF NOT EXISTS `contact` ( INDEX `next-update` (`next-update`), INDEX `local-data-next-update` (`local-data`,`next-update`), INDEX `uid_lastitem` (`uid`,`last-item`), + INDEX `uid_created` (`uid`,`created`), INDEX `baseurl` (`baseurl`(64)), INDEX `uid_contact-type` (`uid`,`contact-type`), INDEX `uid_self_contact-type` (`uid`,`self`,`contact-type`), diff --git a/doc/en/spec/database/db-contact.md b/doc/en/spec/database/db-contact.md index c89eb41e41..de19114e7b 100644 --- a/doc/en/spec/database/db-contact.md +++ b/doc/en/spec/database/db-contact.md @@ -114,6 +114,7 @@ contact table | next-update | next-update | | local-data-next-update | local-data, next-update | | uid_lastitem | uid, last-item | +| uid_created | uid, created | | baseurl | baseurl(64) | | uid_contact-type | uid, contact-type | | uid_self_contact-type | uid, self, contact-type | diff --git a/src/Model/Item.php b/src/Model/Item.php index ba54a3e599..7cf86db706 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -403,7 +403,7 @@ class Item Post\DeliveryData::delete($item['uri-id']); // If it's the parent of a comment thread, kill all the kids - if ($item['gravity'] == self::GRAVITY_PARENT) { + if ($item['gravity'] == self::GRAVITY_PARENT && !is_null($item['parent'])) { self::markForDeletion(['parent' => $item['parent'], 'deleted' => false], $priority); } diff --git a/src/Module/Api/Mastodon/Directory.php b/src/Module/Api/Mastodon/Directory.php index b83341d00b..990da59bb0 100644 --- a/src/Module/Api/Mastodon/Directory.php +++ b/src/Module/Api/Mastodon/Directory.php @@ -42,8 +42,10 @@ class Directory extends BaseApi $condition = ['uid' => 0, 'hidden' => false, 'network' => Protocol::FEDERATED]; } - $params = ['limit' => [$request['offset'], $request['limit']], - 'order' => [($request['order'] == 'active') ? 'last-item' : 'created' => true]]; + $params = [ + 'limit' => [$request['offset'], $request['limit']], + 'order' => [($request['order'] == 'active') ? 'last-item' : 'created' => true] + ]; $accounts = []; $contacts = DBA::select($table, ['id', 'uid'], $condition, $params); diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index 7a4aad4acd..f71c1d870b 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -285,6 +285,7 @@ return [ "next-update" => ["next-update"], "local-data-next-update" => ["local-data", "next-update"], "uid_lastitem" => ["uid", "last-item"], + "uid_created" => ["uid", "created"], "baseurl" => ["baseurl(64)"], "uid_contact-type" => ["uid", "contact-type"], "uid_self_contact-type" => ["uid", "self", "contact-type"], From 04572cd25bf12ab873bc56e2cbd8c3ec460f9694 Mon Sep 17 00:00:00 2001 From: Marcus Funch Date: Fri, 2 Jan 2026 20:10:02 +0100 Subject: [PATCH 049/197] User menu cleanup --- src/Content/Nav.php | 2 +- view/theme/frio/templates/nav.tpl | 27 +++++---------------------- 2 files changed, 6 insertions(+), 23 deletions(-) diff --git a/src/Content/Nav.php b/src/Content/Nav.php index 51d75a7d21..08f6690061 100644 --- a/src/Content/Nav.php +++ b/src/Content/Nav.php @@ -224,8 +224,8 @@ class Nav if ($this->session->isAuthenticated()) { // user menu - $nav['usermenu'][] = ['profile/' . $this->session->getLocalUserNickname(), $this->l10n->t('Conversations'), '', $this->l10n->t('Conversations you started'), 'fa-commenting']; $nav['usermenu'][] = ['profile/' . $this->session->getLocalUserNickname() . '/profile', $this->l10n->t('Profile'), '', $this->l10n->t('Your profile page'), 'fa-user']; + $nav['usermenu'][] = ['profile/' . $this->session->getLocalUserNickname(), $this->l10n->t('Conversations'), '', $this->l10n->t('Conversations you started'), 'fa-commenting']; $nav['usermenu'][] = ['profile/' . $this->session->getLocalUserNickname() . '/photos', $this->l10n->t('Photos'), '', $this->l10n->t('Your photos'), 'fa-picture-o']; $nav['usermenu'][] = ['profile/' . $this->session->getLocalUserNickname() . '/media', $this->l10n->t('Media'), '', $this->l10n->t('Your postings with media'), 'fa-edit']; $nav['usermenu'][] = ['calendar/', $this->l10n->t('Calendar'), '', $this->l10n->t('Your calendar'), 'fa-calendar']; diff --git a/view/theme/frio/templates/nav.tpl b/view/theme/frio/templates/nav.tpl index 5f36caf4d1..2149953f06 100644 --- a/view/theme/frio/templates/nav.tpl +++ b/view/theme/frio/templates/nav.tpl @@ -197,24 +197,16 @@ {{/if}} {{foreach $nav.usermenu as $usermenu}}
  • - {{$usermenu.1}}
  • {{/foreach}} -

  • - {{if $nav.notifications}} -
  • - - - {{$nav.notifications.1}} - -
  • - {{/if}} +

  • {{if $nav.messages}} -
  • +
  • @@ -224,9 +216,8 @@
  • {{/if}} -

  • {{if $nav.contacts}} -
  • +
  • @@ -362,17 +353,9 @@
  • {{/foreach}} - {{if $nav.notifications || $nav.contacts || $nav.messages || $nav.delegation}} + {{if $nav.contacts || $nav.messages || $nav.delegation}}

  • {{/if}} - {{if $nav.notifications}} -
  • - {{$nav.notifications.1}} - -
  • - {{/if}} {{if $nav.contacts}}
  • Date: Fri, 6 Feb 2026 15:22:24 +0100 Subject: [PATCH 050/197] Remove media/media posts from the user menu to simplify it --- src/Content/Nav.php | 1 - view/lang/C/messages.po | 145 ++++++++++++++++++++-------------------- 2 files changed, 72 insertions(+), 74 deletions(-) diff --git a/src/Content/Nav.php b/src/Content/Nav.php index 08f6690061..9001b2c63d 100644 --- a/src/Content/Nav.php +++ b/src/Content/Nav.php @@ -227,7 +227,6 @@ class Nav $nav['usermenu'][] = ['profile/' . $this->session->getLocalUserNickname() . '/profile', $this->l10n->t('Profile'), '', $this->l10n->t('Your profile page'), 'fa-user']; $nav['usermenu'][] = ['profile/' . $this->session->getLocalUserNickname(), $this->l10n->t('Conversations'), '', $this->l10n->t('Conversations you started'), 'fa-commenting']; $nav['usermenu'][] = ['profile/' . $this->session->getLocalUserNickname() . '/photos', $this->l10n->t('Photos'), '', $this->l10n->t('Your photos'), 'fa-picture-o']; - $nav['usermenu'][] = ['profile/' . $this->session->getLocalUserNickname() . '/media', $this->l10n->t('Media'), '', $this->l10n->t('Your postings with media'), 'fa-edit']; $nav['usermenu'][] = ['calendar/', $this->l10n->t('Calendar'), '', $this->l10n->t('Your calendar'), 'fa-calendar']; $nav['usermenu'][] = ['notes/', $this->l10n->t('Personal notes'), '', $this->l10n->t('Your personal notes'), 'fa-book']; diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index 643e538da4..e458db0a7f 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 2026.04-dev\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-02-08 14:11+0100\n" +"POT-Creation-Date: 2026-02-09 20:34+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -210,12 +210,12 @@ msgstr "" msgid "Your password has been changed at %s" msgstr "" -#: mod/message.php:28 mod/message.php:124 src/Content/Nav.php:316 +#: mod/message.php:28 mod/message.php:124 src/Content/Nav.php:315 #: view/theme/frio/theme.php:229 msgid "Messages" msgstr "" -#: mod/message.php:35 mod/message.php:117 src/Content/Nav.php:319 +#: mod/message.php:35 mod/message.php:117 src/Content/Nav.php:318 msgid "New Message" msgstr "" @@ -537,7 +537,7 @@ msgstr "" msgid "View Full Size" msgstr "" -#: mod/photos.php:1024 src/Content/Nav.php:271 src/Content/Text/HTML.php:872 +#: mod/photos.php:1024 src/Content/Nav.php:270 src/Content/Text/HTML.php:872 #: src/Content/Widget/TagCloud.php:54 msgid "Tags" msgstr "" @@ -1719,7 +1719,7 @@ msgid "Display posts that have been created by accounts of the selected circle." msgstr "" #: src/Content/Feature.php:128 src/Content/GroupManager.php:131 -#: src/Content/Nav.php:276 src/Content/Text/HTML.php:877 +#: src/Content/Nav.php:275 src/Content/Text/HTML.php:877 #: src/Content/Widget.php:558 src/Model/User.php:1400 msgid "Groups" msgstr "" @@ -1966,7 +1966,7 @@ msgstr "" msgid "Nothing new here" msgstr "" -#: src/Content/Nav.php:118 src/Content/Nav.php:249 src/Content/Nav.php:306 +#: src/Content/Nav.php:118 src/Content/Nav.php:248 src/Content/Nav.php:305 #: src/Module/Help.php:68 msgid "Home" msgstr "" @@ -1997,26 +1997,26 @@ msgstr "" msgid "Sign in" msgstr "" -#: src/Content/Nav.php:227 src/Module/BaseProfile.php:42 -#: src/Module/Contact.php:497 -msgid "Conversations" -msgstr "" - -#: src/Content/Nav.php:227 -msgid "Conversations you started" -msgstr "" - -#: src/Content/Nav.php:228 src/Module/BaseProfile.php:34 +#: src/Content/Nav.php:227 src/Module/BaseProfile.php:34 #: src/Module/BaseSettings.php:86 src/Module/Contact.php:489 #: src/Module/Contact/Profile.php:471 src/Module/Profile/Profile.php:282 #: src/Module/Welcome.php:44 view/theme/frio/theme.php:218 msgid "Profile" msgstr "" -#: src/Content/Nav.php:228 view/theme/frio/theme.php:218 +#: src/Content/Nav.php:227 view/theme/frio/theme.php:218 msgid "Your profile page" msgstr "" +#: src/Content/Nav.php:228 src/Module/BaseProfile.php:42 +#: src/Module/Contact.php:497 +msgid "Conversations" +msgstr "" + +#: src/Content/Nav.php:228 +msgid "Conversations you started" +msgstr "" + #: src/Content/Nav.php:229 src/Module/BaseProfile.php:50 #: src/Module/Media/Photo/Browser.php:62 view/theme/frio/theme.php:222 msgid "Photos" @@ -2026,17 +2026,7 @@ msgstr "" msgid "Your photos" msgstr "" -#: src/Content/Nav.php:230 src/Module/BaseProfile.php:58 -#: src/Module/BaseProfile.php:61 src/Module/Contact.php:513 -#: view/theme/frio/theme.php:223 -msgid "Media" -msgstr "" - -#: src/Content/Nav.php:230 view/theme/frio/theme.php:223 -msgid "Your postings with media" -msgstr "" - -#: src/Content/Nav.php:231 src/Content/Nav.php:291 +#: src/Content/Nav.php:230 src/Content/Nav.php:290 #: src/Module/BaseProfile.php:70 src/Module/BaseProfile.php:73 #: src/Module/BaseProfile.php:81 src/Module/BaseProfile.php:84 #: src/Module/Calendar/Show.php:113 src/Module/Settings/Display.php:435 @@ -2044,33 +2034,33 @@ msgstr "" msgid "Calendar" msgstr "" -#: src/Content/Nav.php:231 view/theme/frio/theme.php:224 +#: src/Content/Nav.php:230 view/theme/frio/theme.php:224 msgid "Your calendar" msgstr "" -#: src/Content/Nav.php:232 +#: src/Content/Nav.php:231 msgid "Personal notes" msgstr "" -#: src/Content/Nav.php:232 +#: src/Content/Nav.php:231 msgid "Your personal notes" msgstr "" -#: src/Content/Nav.php:249 src/Module/Settings/OAuth.php:59 +#: src/Content/Nav.php:248 src/Module/Settings/OAuth.php:59 msgid "Home Page" msgstr "" -#: src/Content/Nav.php:253 src/Module/Register.php:173 +#: src/Content/Nav.php:252 src/Module/Register.php:173 #: src/Module/Security/Login.php:128 msgid "Register" msgstr "" -#: src/Content/Nav.php:253 src/Module/Register.php:157 +#: src/Content/Nav.php:252 src/Module/Register.php:157 #: src/Module/Security/Login.php:127 msgid "Create an account" msgstr "" -#: src/Content/Nav.php:259 src/Module/Help.php:54 +#: src/Content/Nav.php:258 src/Module/Help.php:54 #: src/Module/Settings/TwoFactor/AppSpecific.php:118 #: src/Module/Settings/TwoFactor/Index.php:125 #: src/Module/Settings/TwoFactor/Recovery.php:96 @@ -2078,32 +2068,32 @@ msgstr "" msgid "Help" msgstr "" -#: src/Content/Nav.php:259 +#: src/Content/Nav.php:258 msgid "Help and documentation" msgstr "" -#: src/Content/Nav.php:263 +#: src/Content/Nav.php:262 msgid "Apps" msgstr "" -#: src/Content/Nav.php:263 +#: src/Content/Nav.php:262 msgid "Addon applications, utilities, games" msgstr "" -#: src/Content/Nav.php:267 src/Content/Text/HTML.php:862 +#: src/Content/Nav.php:266 src/Content/Text/HTML.php:862 #: src/Module/Admin/Logs/View.php:74 src/Module/Search/Index.php:99 msgid "Search" msgstr "" -#: src/Content/Nav.php:267 +#: src/Content/Nav.php:266 msgid "Search site content" msgstr "" -#: src/Content/Nav.php:270 src/Content/Text/HTML.php:871 +#: src/Content/Nav.php:269 src/Content/Text/HTML.php:871 msgid "Full Text" msgstr "" -#: src/Content/Nav.php:272 src/Content/Nav.php:327 +#: src/Content/Nav.php:271 src/Content/Nav.php:326 #: src/Content/Text/HTML.php:873 src/Module/BaseProfile.php:112 #: src/Module/BaseProfile.php:115 src/Module/Contact.php:181 #: src/Module/Contact.php:411 src/Module/Contact.php:521 @@ -2111,121 +2101,121 @@ msgstr "" msgid "Contacts" msgstr "" -#: src/Content/Nav.php:287 +#: src/Content/Nav.php:286 msgid "Community" msgstr "" -#: src/Content/Nav.php:287 +#: src/Content/Nav.php:286 msgid "Conversations on this and other servers" msgstr "" -#: src/Content/Nav.php:294 +#: src/Content/Nav.php:293 msgid "Directory" msgstr "" -#: src/Content/Nav.php:294 +#: src/Content/Nav.php:293 msgid "People directory" msgstr "" -#: src/Content/Nav.php:296 src/Module/BaseAdmin.php:70 +#: src/Content/Nav.php:295 src/Module/BaseAdmin.php:70 #: src/Module/BaseModeration.php:97 msgid "Information" msgstr "" -#: src/Content/Nav.php:296 +#: src/Content/Nav.php:295 msgid "Information about this friendica instance" msgstr "" -#: src/Content/Nav.php:299 src/Module/Admin/Tos.php:64 +#: src/Content/Nav.php:298 src/Module/Admin/Tos.php:64 #: src/Module/BaseAdmin.php:80 src/Module/Register.php:181 #: src/Module/Tos.php:87 msgid "Terms of Service" msgstr "" -#: src/Content/Nav.php:299 +#: src/Content/Nav.php:298 msgid "Terms of Service of this Friendica instance" msgstr "" -#: src/Content/Nav.php:304 view/theme/frio/theme.php:227 +#: src/Content/Nav.php:303 view/theme/frio/theme.php:227 msgid "Network" msgstr "" -#: src/Content/Nav.php:304 view/theme/frio/theme.php:227 +#: src/Content/Nav.php:303 view/theme/frio/theme.php:227 msgid "Conversations from your friends" msgstr "" -#: src/Content/Nav.php:306 view/theme/frio/theme.php:217 +#: src/Content/Nav.php:305 view/theme/frio/theme.php:217 msgid "Your posts and conversations" msgstr "" -#: src/Content/Nav.php:310 +#: src/Content/Nav.php:309 msgid "Introductions" msgstr "" -#: src/Content/Nav.php:310 +#: src/Content/Nav.php:309 msgid "Friend Requests" msgstr "" -#: src/Content/Nav.php:311 src/Module/BaseNotifications.php:134 +#: src/Content/Nav.php:310 src/Module/BaseNotifications.php:134 #: src/Module/Notifications/Introductions.php:63 msgid "Notifications" msgstr "" -#: src/Content/Nav.php:312 +#: src/Content/Nav.php:311 msgid "View all" msgstr "" -#: src/Content/Nav.php:313 src/Module/Settings/Connectors.php:226 +#: src/Content/Nav.php:312 src/Module/Settings/Connectors.php:226 msgid "Mark as read" msgstr "" -#: src/Content/Nav.php:313 +#: src/Content/Nav.php:312 msgid "Mark all system notifications as seen" msgstr "" -#: src/Content/Nav.php:316 view/theme/frio/theme.php:229 +#: src/Content/Nav.php:315 view/theme/frio/theme.php:229 msgid "Private mail" msgstr "" -#: src/Content/Nav.php:317 +#: src/Content/Nav.php:316 msgid "Inbox" msgstr "" -#: src/Content/Nav.php:318 +#: src/Content/Nav.php:317 msgid "Outbox" msgstr "" -#: src/Content/Nav.php:322 +#: src/Content/Nav.php:321 msgid "Accounts" msgstr "" -#: src/Content/Nav.php:322 +#: src/Content/Nav.php:321 msgid "Manage other accounts, including groups and pages" msgstr "" -#: src/Content/Nav.php:325 src/Module/Admin/Addons/Details.php:140 +#: src/Content/Nav.php:324 src/Module/Admin/Addons/Details.php:140 #: src/Module/Admin/Themes/Details.php:85 src/Module/BaseSettings.php:177 #: src/Module/Welcome.php:39 view/theme/frio/theme.php:230 msgid "Settings" msgstr "" -#: src/Content/Nav.php:325 view/theme/frio/theme.php:230 +#: src/Content/Nav.php:324 view/theme/frio/theme.php:230 msgid "Account settings" msgstr "" -#: src/Content/Nav.php:327 view/theme/frio/theme.php:231 +#: src/Content/Nav.php:326 view/theme/frio/theme.php:231 msgid "Manage/edit friends and contacts" msgstr "" -#: src/Content/Nav.php:332 src/Module/BaseAdmin.php:114 +#: src/Content/Nav.php:331 src/Module/BaseAdmin.php:114 msgid "Admin" msgstr "" -#: src/Content/Nav.php:332 +#: src/Content/Nav.php:331 msgid "Site setup and configuration" msgstr "" -#: src/Content/Nav.php:333 src/Module/BaseModeration.php:117 +#: src/Content/Nav.php:332 src/Module/BaseModeration.php:117 #: src/Module/Moderation/Blocklist/Contact.php:98 #: src/Module/Moderation/Blocklist/Contact/Import.php:101 #: src/Module/Moderation/Blocklist/Server/Add.php:110 @@ -2242,15 +2232,15 @@ msgstr "" msgid "Moderation" msgstr "" -#: src/Content/Nav.php:333 +#: src/Content/Nav.php:332 msgid "Content and user moderation" msgstr "" -#: src/Content/Nav.php:336 +#: src/Content/Nav.php:335 msgid "Navigation" msgstr "" -#: src/Content/Nav.php:336 +#: src/Content/Nav.php:335 msgid "Site map" msgstr "" @@ -5784,6 +5774,11 @@ msgstr "" msgid "Conversations started" msgstr "" +#: src/Module/BaseProfile.php:58 src/Module/BaseProfile.php:61 +#: src/Module/Contact.php:513 view/theme/frio/theme.php:223 +msgid "Media" +msgstr "" + #: src/Module/BaseProfile.php:96 msgid "Only You Can See This" msgstr "" @@ -12118,6 +12113,10 @@ msgstr "" msgid "Visitor" msgstr "" +#: view/theme/frio/theme.php:223 +msgid "Your postings with media" +msgstr "" + #: view/theme/quattro/config.php:77 msgid "Alignment" msgstr "" From f3caad0b1464752db5839c380226d81bad6f65a2 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 10 Feb 2026 04:40:42 +0000 Subject: [PATCH 051/197] Respect robots.txt when fetching server data --- src/DI.php | 5 + src/Database/Definition/DbaDefinition.php | 2 +- src/Model/GServer.php | 178 ++++++++++++++++---- src/Network/RobotsTxt.php | 193 ++++++++++++++++++++++ 4 files changed, 342 insertions(+), 36 deletions(-) create mode 100644 src/Network/RobotsTxt.php diff --git a/src/DI.php b/src/DI.php index 4f825e18fb..7112e727b1 100644 --- a/src/DI.php +++ b/src/DI.php @@ -413,6 +413,11 @@ abstract class DI return self::$dice->create(Network\HTTPClient\Capability\ICanSendHttpRequests::class); } + public static function robotsTxt(): Network\RobotsTxt + { + return self::$dice->create(Network\RobotsTxt::class); + } + // // "Repository" namespace // diff --git a/src/Database/Definition/DbaDefinition.php b/src/Database/Definition/DbaDefinition.php index c5d77d3a46..4632882aa9 100644 --- a/src/Database/Definition/DbaDefinition.php +++ b/src/Database/Definition/DbaDefinition.php @@ -70,7 +70,7 @@ class DbaDefinition // Assign all field that are present in the table foreach ($fieldNames as $field) { - if (isset($data[$field])) { + if (array_key_exists($field, $data)) { // Limit the length of varchar, varbinary, char and binary fields if (is_string($data[$field]) && preg_match("/char\((\d*)\)/", $definition[$table]['fields'][$field]['type'], $result)) { if ($charset == 'latin1') { diff --git a/src/Model/GServer.php b/src/Model/GServer.php index 8ead599408..c74b0e86ba 100644 --- a/src/Model/GServer.php +++ b/src/Model/GServer.php @@ -29,6 +29,7 @@ use Friendica\Util\Network; use Friendica\Util\Strings; use Friendica\Util\XML; use Friendica\Network\HTTPException; +use Friendica\Network\RobotsTxt; use Friendica\Worker\UpdateGServer; use GuzzleHttp\Psr7\Uri; use Psr\Http\Message\UriInterface; @@ -78,6 +79,8 @@ class GServer const DETECT_NODEINFO_21 = 104; // Nodeinfo Version 2.1 const DETECT_NODEINFO_22 = 105; // Nodeinfo Version 2.2 + private static RobotsTxt $robotsTxt; + /** * Check for the existence of a server and adds it in the background if not existant * @@ -630,6 +633,9 @@ class GServer $in_webroot = empty(parse_url($url, PHP_URL_PATH)); + self::$robotsTxt = DI::robotsTxt(); + self::$robotsTxt->load($url); + // When a nodeinfo is present, we don't need to dig further $curlResult = DI::httpClient()->get($url . '/.well-known/nodeinfo', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); if ($curlResult->isTimeout()) { @@ -642,6 +648,10 @@ class GServer } else { $serverdata = self::parseNodeinfo($url, $curlResult); + if (!empty($serverdata)) { + $serverdata = self::clearStatisticalData($serverdata); + } + if (empty($serverdata) || !in_array($serverdata['detection-method'], [self::DETECT_NODEINFO_20, self::DETECT_NODEINFO_21, self::DETECT_NODEINFO_22])) { $curlResult = DI::httpClient()->get($url . '/.well-known/x-nodeinfo2', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); $serverdata = self::parseNodeinfo2($curlResult) ?: $serverdata; @@ -658,7 +668,7 @@ class GServer // When there is no Nodeinfo, then use some protocol specific endpoints if ($serverdata['network'] == Protocol::PHANTOM) { - if ($in_webroot) { + if ($in_webroot && self::$robotsTxt->isAllowed('/')) { // Fetch the landing page, possibly it reveals some data $accept = 'application/activity+json,application/ld+json,application/json,*/*;q=0.9'; $curlResult = DI::httpClient()->get($url, $accept, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); @@ -814,11 +824,6 @@ class GServer $serverdata['registered-users'] = $serverdata['registered-users'] ?? 0; - // Numbers above a reasonable value (10 millions) are ignored - if ($serverdata['registered-users'] > 10000000) { - $serverdata['registered-users'] = 0; - } - // On an active server there has to be at least a single user if (!in_array($serverdata['network'], [Protocol::PHANTOM, Protocol::FEED]) && ($serverdata['registered-users'] <= 0)) { $serverdata['registered-users'] = 1; @@ -862,6 +867,53 @@ class GServer return $ret; } + /** + * Clear statistical data from nodeinfo when we are not allowed to access it or when the data seems to be faked. + * + * GotoSocial is known for having an option to provide fake statistical data, so we apply some checks for this platform in particular. + * + * @param array $serverdata + * @return array + */ + private static function clearStatisticalData(array $serverdata): array + { + // We don't clear the data when we are allowed to access the nodeinfo + $clear = !self::$robotsTxt->isAllowed('/.well-known/nodeinfo'); + + // Numbers above a reasonable value (10 millions) are a sign for faked data, so we clear the data in this case as well. + if (($serverdata['registered-users'] ?? 0) > 10000000) { + $clear = true; + } + + // All the following checks are only applied for GoToSocial, so we can skip them for other platforms. + if (!$clear && $serverdata['platform'] !== 'gotosocial') { + return $serverdata; + } + + // When the robots.txt couldn't be loaded, we clear the data as well. + if (!self::$robotsTxt->isLoaded()) { + $clear = true; + } + + // We clear the data when there are more than 10.000 registered users, since this is an indicator for faked data. + if (($serverdata['registered-users'] ?? 0) > 10000) { + $clear = true; + } + + if (!$clear) { + return $serverdata; + } + + $serverdata['registered-users'] = null; + $serverdata['active-week-users'] = null; + $serverdata['active-month-users'] = null; + $serverdata['active-halfyear-users'] = null; + $serverdata['local-posts'] = null; + $serverdata['local-comments'] = null; + + return $serverdata; + } + /** * Count the number of known contacts from this server */ @@ -905,6 +957,10 @@ class GServer */ private static function discoverRelay(string $server_url) { + if (!self::$robotsTxt->isAllowed('/.well-known/x-social-relay')) { + return; + } + DI::logger()->info('Discover relay data', ['server' => $server_url]); $curlResult = DI::httpClient()->get($server_url . '/.well-known/x-social-relay', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); @@ -1002,6 +1058,10 @@ class GServer */ private static function fetchStatistics(string $url, array $serverdata): array { + if (!self::$robotsTxt->isAllowed('/statistics.json')) { + return $serverdata; + } + $curlResult = DI::httpClient()->get($url . '/statistics.json', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); if (!$curlResult->isSuccess()) { return $serverdata; @@ -1504,6 +1564,10 @@ class GServer */ private static function fetchSiteinfo(string $url, array $serverdata): array { + if (!self::$robotsTxt->isAllowed('/siteinfo.json')) { + return $serverdata; + } + $curlResult = DI::httpClient()->get($url . '/siteinfo.json', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); if (!$curlResult->isSuccess()) { return $serverdata; @@ -1684,6 +1748,10 @@ class GServer */ private static function getNomadVersion(string $url): string { + if (!self::$robotsTxt->isAllowed('/api/z/1.0/version')) { + return ''; + } + $curlResult = DI::httpClient()->get($url . '/api/z/1.0/version', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); if (!$curlResult->isSuccess() || ($curlResult->getBodyString() == '')) { return ''; @@ -1777,6 +1845,10 @@ class GServer */ private static function validHostMeta(string $url): bool { + if (!self::$robotsTxt->isAllowed(Probe::HOST_META)) { + return false; + } + $xrd_timeout = DI::config()->get('system', 'xrd_timeout'); $curlResult = DI::httpClient()->get($url . Probe::HOST_META, HttpClientAccept::XRD_XML, [HttpClientOptions::TIMEOUT => $xrd_timeout, HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); if (!$curlResult->isSuccess()) { @@ -1866,6 +1938,10 @@ class GServer { $serverdata['poco'] = ''; + if (!self::$robotsTxt->isAllowed('/poco')) { + return $serverdata; + } + $curlResult = DI::httpClient()->get($url . '/poco', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); if (!$curlResult->isSuccess()) { return $serverdata; @@ -1895,6 +1971,10 @@ class GServer */ public static function checkMastodonDirectory(string $url, array $serverdata): array { + if (!self::$robotsTxt->isAllowed('/api/v1/directory')) { + return $serverdata; + } + $curlResult = DI::httpClient()->get($url . '/api/v1/directory?limit=1', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); if (!$curlResult->isSuccess()) { return $serverdata; @@ -1927,6 +2007,10 @@ class GServer */ private static function detectPeertube(string $url, array $serverdata): array { + if (!self::$robotsTxt->isAllowed('/api/v1/config')) { + return $serverdata; + } + $curlResult = DI::httpClient()->get($url . '/api/v1/config', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); if (!$curlResult->isSuccess() || ($curlResult->getBodyString() == '')) { return $serverdata; @@ -1975,6 +2059,10 @@ class GServer */ private static function detectNextcloud(string $url, array $serverdata, bool $validHostMeta): array { + if (!self::$robotsTxt->isAllowed('/status.php')) { + return $serverdata; + } + $curlResult = DI::httpClient()->get($url . '/status.php', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); if (!$curlResult->isSuccess() || ($curlResult->getBodyString() == '')) { return $serverdata; @@ -2011,6 +2099,10 @@ class GServer */ private static function fetchWeeklyUsage(string $url, array $serverdata): array { + if (!self::$robotsTxt->isAllowed('/api/v1/instance/activity')) { + return $serverdata; + } + $curlResult = DI::httpClient()->get($url . '/api/v1/instance/activity', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); if (!$curlResult->isSuccess() || ($curlResult->getBodyString() == '')) { return $serverdata; @@ -2051,6 +2143,10 @@ class GServer */ private static function detectMastodonAlikes(string $url, array $serverdata): array { + if (!self::$robotsTxt->isAllowed('/api/v1/instance')) { + return $serverdata; + } + $curlResult = DI::httpClient()->get($url . '/api/v1/instance', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); if (!$curlResult->isSuccess() || ($curlResult->getBodyString() == '')) { return $serverdata; @@ -2128,6 +2224,10 @@ class GServer */ private static function detectHubzilla(string $url, array $serverdata): array { + if (!self::$robotsTxt->isAllowed('/api/statusnet/config.json')) { + return $serverdata; + } + $curlResult = DI::httpClient()->get($url . '/api/statusnet/config.json', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); if (!$curlResult->isSuccess() || ($curlResult->getBodyString() == '')) { return $serverdata; @@ -2223,44 +2323,48 @@ class GServer private static function detectGNUSocial(string $url, array $serverdata): array { // Test for GNU Social - $curlResult = DI::httpClient()->get($url . '/api/gnusocial/version.json', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); - if ($curlResult->isSuccess() && ($curlResult->getBodyString() != '{"error":"not implemented"}') && + if (self::$robotsTxt->isAllowed('/api/gnusocial/version.json')) { + $curlResult = DI::httpClient()->get($url . '/api/gnusocial/version.json', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); + if ($curlResult->isSuccess() && ($curlResult->getBodyString() != '{"error":"not implemented"}') && ($curlResult->getBodyString() != '') && (strlen($curlResult->getBodyString()) < 30)) { - $serverdata['platform'] = 'gnusocial'; - // Remove junk that some GNU Social servers return - $serverdata['version'] = str_replace(chr(239) . chr(187) . chr(191), '', $curlResult->getBodyString()); - $serverdata['version'] = str_replace(["\r", "\n", "\t"], '', $serverdata['version']); - $serverdata['version'] = trim($serverdata['version'], '"'); - $serverdata['network'] = Protocol::OSTATUS; + $serverdata['platform'] = 'gnusocial'; + // Remove junk that some GNU Social servers return + $serverdata['version'] = str_replace(chr(239) . chr(187) . chr(191), '', $curlResult->getBodyString()); + $serverdata['version'] = str_replace(["\r", "\n", "\t"], '', $serverdata['version']); + $serverdata['version'] = trim($serverdata['version'], '"'); + $serverdata['network'] = Protocol::OSTATUS; - if (in_array($serverdata['detection-method'], self::DETECT_UNSPECIFIC)) { - $serverdata['detection-method'] = self::DETECT_GNUSOCIAL; + if (in_array($serverdata['detection-method'], self::DETECT_UNSPECIFIC)) { + $serverdata['detection-method'] = self::DETECT_GNUSOCIAL; + } + + return $serverdata; } - - return $serverdata; } // Test for Statusnet - $curlResult = DI::httpClient()->get($url . '/api/statusnet/version.json', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); - if ($curlResult->isSuccess() && ($curlResult->getBodyString() != '{"error":"not implemented"}') && - ($curlResult->getBodyString() != '') && (strlen($curlResult->getBodyString()) < 30)) { + if (self::$robotsTxt->isAllowed('/api/statusnet/version.json')) { + $curlResult = DI::httpClient()->get($url . '/api/statusnet/version.json', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); + if ($curlResult->isSuccess() && ($curlResult->getBodyString() != '{"error":"not implemented"}') && + ($curlResult->getBodyString() != '') && (strlen($curlResult->getBodyString()) < 30)) { - // Remove junk that some GNU Social servers return - $serverdata['version'] = str_replace(chr(239) . chr(187) . chr(191), '', $curlResult->getBodyString()); - $serverdata['version'] = str_replace(["\r", "\n", "\t"], '', $serverdata['version']); - $serverdata['version'] = trim($serverdata['version'], '"'); + // Remove junk that some GNU Social servers return + $serverdata['version'] = str_replace(chr(239) . chr(187) . chr(191), '', $curlResult->getBodyString()); + $serverdata['version'] = str_replace(["\r", "\n", "\t"], '', $serverdata['version']); + $serverdata['version'] = trim($serverdata['version'], '"'); - if (!empty($serverdata['version']) && strtolower(substr($serverdata['version'], 0, 7)) == 'pleroma') { - $serverdata['platform'] = 'pleroma'; - $serverdata['version'] = trim(str_ireplace('pleroma', '', $serverdata['version'])); - $serverdata['network'] = Protocol::ACTIVITYPUB; - } else { - $serverdata['platform'] = 'statusnet'; - $serverdata['network'] = Protocol::OSTATUS; - } + if (!empty($serverdata['version']) && strtolower(substr($serverdata['version'], 0, 7)) == 'pleroma') { + $serverdata['platform'] = 'pleroma'; + $serverdata['version'] = trim(str_ireplace('pleroma', '', $serverdata['version'])); + $serverdata['network'] = Protocol::ACTIVITYPUB; + } else { + $serverdata['platform'] = 'statusnet'; + $serverdata['network'] = Protocol::OSTATUS; + } - if (in_array($serverdata['detection-method'], self::DETECT_UNSPECIFIC)) { - $serverdata['detection-method'] = self::DETECT_STATUSNET; + if (in_array($serverdata['detection-method'], self::DETECT_UNSPECIFIC)) { + $serverdata['detection-method'] = self::DETECT_STATUSNET; + } } } @@ -2277,6 +2381,10 @@ class GServer */ private static function detectFriendica(string $url, array $serverdata): array { + if (!self::$robotsTxt->isAllowed('/friendica/json')) { + return $serverdata; + } + // There is a bug in some versions of Friendica that will return an ActivityStream actor when the content type "application/json" is requested. // Because of this me must not use ACCEPT_JSON here. $curlResult = DI::httpClient()->get($url . '/friendica/json', HttpClientAccept::DEFAULT, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); diff --git a/src/Network/RobotsTxt.php b/src/Network/RobotsTxt.php new file mode 100644 index 0000000000..1a1704f616 --- /dev/null +++ b/src/Network/RobotsTxt.php @@ -0,0 +1,193 @@ +httpClient = $httpClient; + } + + /** + * Loads the RobotsTxt parser with a server URL + * + * @param string $url The base URL of the server + * @return bool True if robots.txt was successfully loaded, false otherwise + */ + public function load(string $url): bool + { + $this->url = rtrim($url, '/'); + $this->disallowRules = []; + $this->allowRules = []; + $this->isLoaded = false; + + $robotsUrl = $this->url . '/robots.txt'; + + try { + $curlResult = $this->httpClient->get( + $robotsUrl, + HttpClientAccept::TEXT, + [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO] + ); + + if (!$curlResult->isSuccess()) { + return false; + } + + if (empty($curlResult->getBodyString())) { + return false; + } + + $this->isLoaded = $this->parseRobotsTxt($curlResult->getBodyString()); + return $this->isLoaded; + } catch (\Exception $e) { + return false; + } + } + + /** + * Check if the robots.txt has been loaded successfully + * + * @return bool True if loaded, false otherwise + */ + public function isLoaded(): bool + { + return $this->isLoaded; + } + + /** + * Parse the robots.txt content and extract rules for user-agent * + * + * @param string $content The content of robots.txt + * @return bool True if parsing was successful + */ + private function parseRobotsTxt(string $content): bool + { + $lines = explode("\n", $content); + + $isRelevantSection = false; + + foreach ($lines as $line) { + $line = preg_replace('~\s*#.*$~', '', $line); + $line = trim($line); + + if (empty($line)) { + continue; + } + + if (stripos($line, 'User-Agent:') === 0) { + $agent = trim(substr($line, strlen('User-Agent:'))); + + $isRelevantSection = ($agent === '*'); + continue; + } + + if (!$isRelevantSection) { + continue; + } + + if (stripos($line, 'Disallow:') === 0) { + $path = trim(substr($line, strlen('Disallow:'))); + if (!empty($path)) { + $this->disallowRules[] = $path; + } + continue; + } + + if (stripos($line, 'Allow:') === 0) { + $path = trim(substr($line, strlen('Allow:'))); + if (!empty($path)) { + $this->allowRules[] = $path; + } + continue; + } + + if (stripos($line, 'User-Agent:') === 0 && !$isRelevantSection) { + break; + } + } + + return sizeof($this->disallowRules) > 0 || sizeof($this->allowRules) > 0; + } + + /** + * Check if a given path is allowed according to robots.txt rules + * + * @param string $path The path to check (e.g., "/api/v1/accounts") + * @return bool True if the path is allowed, false otherwise + */ + public function isAllowed(string $path): bool + { + $path = '/' . ltrim(parse_url($path, PHP_URL_PATH), '/'); + $allowed = true; + $length = 0; + + foreach ($this->allowRules as $rule) { + if (strlen($rule) > $length && $this->pathMatches($path, $rule)) { + $length = strlen($rule); + } + } + + foreach ($this->disallowRules as $rule) { + if (strlen($rule) > $length && $this->pathMatches($path, $rule)) { + $allowed = false; + } + } + + return $allowed; + } + + /** + * Check if a path matches a robots.txt rule + * Rules use prefix matching: /admin will block /admin, /admin/, /admin/page, etc. + * + * @param string $path The path to check + * @param string $rule The robots.txt rule + * @return bool True if the path matches the rule + */ + private function pathMatches(string $path, string $rule): bool + { + if (str_ends_with($rule, '*')) { + $rule = substr($rule, 0, -1); + return str_starts_with($path, $rule); + } + + return str_starts_with($path, $rule); + } +} From 545a58df58caff2401efbbb947ce8edd481754c1 Mon Sep 17 00:00:00 2001 From: "Marcus F." Date: Fri, 6 Feb 2026 20:54:09 +0100 Subject: [PATCH 052/197] Photos - File browser: Larger buttons to switch file types, add text --- src/Module/Media/Attachment/Browser.php | 21 +- src/Module/Media/Photo/Browser.php | 24 ++- view/lang/C/messages.po | 222 +++++++++++--------- view/theme/frio/css/style.css | 3 + view/theme/frio/templates/media/browser.tpl | 14 +- 5 files changed, 164 insertions(+), 120 deletions(-) diff --git a/src/Module/Media/Attachment/Browser.php b/src/Module/Media/Attachment/Browser.php index 45162ed794..6a9c63df88 100644 --- a/src/Module/Media/Attachment/Browser.php +++ b/src/Module/Media/Attachment/Browser.php @@ -57,13 +57,20 @@ class Browser extends BaseModule $tpl = Renderer::getMarkupTemplate('media/browser.tpl'); $output = Renderer::replaceMacros($tpl, [ - '$type' => 'attachment', - '$path' => ['' => $this->t('Files')], - '$folders' => false, - '$files' => $fileArray, - '$cancel' => $this->t('Cancel'), - '$nickname' => $this->session->getLocalUserNickname(), - '$upload' => $this->t('Upload'), + '$type' => 'attachment', + '$path' => ['' => $this->t('Files')], + '$folders' => false, + '$files' => $fileArray, + '$cancel' => $this->t('Cancel'), + '$nickname' => $this->session->getLocalUserNickname(), + '$upload' => $this->t('Upload'), + '$photos_text' => $this->t('Photos'), + '$files_text' => $this->t('Files'), + '$aria_close' => $this->t('Close'), + '$aria_breadcrumb' => $this->t('Breadcrumb'), + '$aria_mode_switch' => $this->t('Switch between photo and attachment mode'), + '$aria_album_nav' => $this->t('Album navigation'), + '$aria_browser_content' => $this->t('Browser content'), ]); if (empty($request['mode'])) { diff --git a/src/Module/Media/Photo/Browser.php b/src/Module/Media/Photo/Browser.php index 408ba575d1..1322a4515d 100644 --- a/src/Module/Media/Photo/Browser.php +++ b/src/Module/Media/Photo/Browser.php @@ -69,13 +69,20 @@ class Browser extends BaseModule $tpl = Renderer::getMarkupTemplate('media/browser.tpl'); $output = Renderer::replaceMacros($tpl, [ - '$type' => 'photo', - '$path' => $path, - '$folders' => $albums, - '$files' => $photosArray, - '$cancel' => $this->t('Cancel'), - '$nickname' => $this->session->getLocalUserNickname(), - '$upload' => $this->t('Upload'), + '$type' => 'photo', + '$path' => $path, + '$folders' => $albums, + '$files' => $photosArray, + '$cancel' => $this->t('Cancel'), + '$nickname' => $this->session->getLocalUserNickname(), + '$upload' => $this->t('Upload'), + '$photos_text' => $this->t('Photos'), + '$files_text' => $this->t('Files'), + '$aria_close' => $this->t('Close'), + '$aria_breadcrumb' => $this->t('Breadcrumb'), + '$aria_mode_switch' => $this->t('Switch between photo and attachment mode'), + '$aria_album_nav' => $this->t('Album navigation'), + '$aria_browser_content' => $this->t('Browser content'), ]); if (empty($request['mode'])) { @@ -99,7 +106,8 @@ class Browser extends BaseModule Proxy::PIXEL_MEDIUM, Proxy::PIXEL_MEDIUM ], - ['order' => ['scale']]); + ['order' => ['scale']] + ); $scale = $photo['scale'] ?? $record['loq']; return [ diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index e458db0a7f..73b0a89175 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 2026.04-dev\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-02-09 20:34+0100\n" +"POT-Creation-Date: 2026-02-11 10:14+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -284,7 +284,7 @@ msgstr "" #: mod/message.php:190 mod/message.php:348 mod/photos.php:1256 #: src/Content/Conversation.php:402 src/Content/Conversation.php:1611 #: src/Module/Item/Compose.php:205 src/Module/Post/Edit.php:143 -#: src/Object/Post.php:617 +#: src/Object/Post.php:621 msgid "Please wait" msgstr "" @@ -576,31 +576,31 @@ msgstr "" #: mod/photos.php:1094 mod/photos.php:1150 mod/photos.php:1230 #: src/Module/Contact.php:609 src/Module/Item/Compose.php:187 -#: src/Object/Post.php:1160 +#: src/Object/Post.php:1164 msgid "This is you" msgstr "" #: mod/photos.php:1096 mod/photos.php:1097 mod/photos.php:1152 #: mod/photos.php:1153 mod/photos.php:1232 mod/photos.php:1233 -#: src/Module/Moderation/Reports.php:110 src/Object/Post.php:611 -#: src/Object/Post.php:1162 +#: src/Module/Moderation/Reports.php:110 src/Object/Post.php:615 +#: src/Object/Post.php:1166 msgid "Comment" msgstr "" #: mod/photos.php:1098 mod/photos.php:1154 mod/photos.php:1234 #: src/Content/Conversation.php:416 src/Module/Calendar/Event/Form.php:234 #: src/Module/Item/Compose.php:200 src/Module/Post/Edit.php:163 -#: src/Object/Post.php:1176 +#: src/Object/Post.php:1180 msgid "Preview" msgstr "" #: mod/photos.php:1099 src/Content/Conversation.php:370 src/Content/Nav.php:113 -#: src/Module/Post/Edit.php:128 src/Object/Post.php:1164 +#: src/Module/Post/Edit.php:128 src/Object/Post.php:1168 msgid "Loading..." msgstr "" #: mod/photos.php:1191 src/Content/Conversation.php:1533 -#: src/Object/Post.php:263 +#: src/Object/Post.php:267 msgid "Select" msgstr "" @@ -613,23 +613,23 @@ msgstr "" msgid "Delete" msgstr "" -#: mod/photos.php:1253 src/Object/Post.php:435 +#: mod/photos.php:1253 src/Object/Post.php:439 msgid "Like" msgstr "" -#: mod/photos.php:1254 src/Object/Post.php:435 +#: mod/photos.php:1254 src/Object/Post.php:439 msgid "I like this (toggle)" msgstr "" -#: mod/photos.php:1255 src/Object/Post.php:436 +#: mod/photos.php:1255 src/Object/Post.php:440 msgid "Dislike" msgstr "" -#: mod/photos.php:1257 src/Object/Post.php:436 +#: mod/photos.php:1257 src/Object/Post.php:440 msgid "I don't like this (toggle)" msgstr "" -#: mod/photos.php:1278 src/Object/Post.php:228 src/Object/Post.php:230 +#: mod/photos.php:1278 src/Object/Post.php:232 src/Object/Post.php:234 msgid "Edit" msgstr "" @@ -743,7 +743,9 @@ msgid "toggle mobile" msgstr "" #: src/App/Page.php:356 src/Module/Admin/Logs/View.php:92 -#: view/theme/frio/php/minimal.php:39 view/theme/frio/php/standard.php:138 +#: src/Module/Media/Attachment/Browser.php:69 +#: src/Module/Media/Photo/Browser.php:81 view/theme/frio/php/minimal.php:39 +#: view/theme/frio/php/standard.php:138 msgid "Close" msgstr "" @@ -1224,7 +1226,7 @@ msgid "Visible to everybody" msgstr "" #: src/Content/Conversation.php:337 src/Module/Item/Compose.php:199 -#: src/Object/Post.php:1175 +#: src/Object/Post.php:1179 msgid "Please enter a image/video/audio/webpage URL:" msgstr "" @@ -1277,52 +1279,52 @@ msgid "attach file" msgstr "" #: src/Content/Conversation.php:375 src/Module/Item/Compose.php:189 -#: src/Module/Post/Edit.php:169 src/Object/Post.php:1165 +#: src/Module/Post/Edit.php:169 src/Object/Post.php:1169 msgid "Bold" msgstr "" #: src/Content/Conversation.php:376 src/Module/Item/Compose.php:190 -#: src/Module/Post/Edit.php:170 src/Object/Post.php:1166 +#: src/Module/Post/Edit.php:170 src/Object/Post.php:1170 msgid "Italic" msgstr "" #: src/Content/Conversation.php:377 src/Module/Item/Compose.php:191 -#: src/Module/Post/Edit.php:171 src/Object/Post.php:1167 +#: src/Module/Post/Edit.php:171 src/Object/Post.php:1171 msgid "Underline" msgstr "" #: src/Content/Conversation.php:378 src/Module/Item/Compose.php:192 -#: src/Module/Post/Edit.php:172 src/Object/Post.php:1169 +#: src/Module/Post/Edit.php:172 src/Object/Post.php:1173 msgid "Quote" msgstr "" #: src/Content/Conversation.php:379 src/Module/Item/Compose.php:193 -#: src/Module/Post/Edit.php:173 src/Object/Post.php:1170 +#: src/Module/Post/Edit.php:173 src/Object/Post.php:1174 msgid "Add emojis" msgstr "" #: src/Content/Conversation.php:380 src/Module/Item/Compose.php:194 -#: src/Object/Post.php:1168 +#: src/Object/Post.php:1172 msgid "Content Warning" msgstr "" #: src/Content/Conversation.php:381 src/Module/Item/Compose.php:195 -#: src/Module/Post/Edit.php:174 src/Object/Post.php:1171 +#: src/Module/Post/Edit.php:174 src/Object/Post.php:1175 msgid "Code" msgstr "" #: src/Content/Conversation.php:382 src/Module/Item/Compose.php:196 -#: src/Object/Post.php:1172 +#: src/Object/Post.php:1176 msgid "Image" msgstr "" #: src/Content/Conversation.php:383 src/Module/Item/Compose.php:197 -#: src/Module/Post/Edit.php:175 src/Object/Post.php:1173 +#: src/Module/Post/Edit.php:175 src/Object/Post.php:1177 msgid "Link" msgstr "" #: src/Content/Conversation.php:384 src/Module/Item/Compose.php:198 -#: src/Module/Post/Edit.php:176 src/Object/Post.php:1174 +#: src/Module/Post/Edit.php:176 src/Object/Post.php:1178 msgid "Link or Media" msgstr "" @@ -1488,25 +1490,25 @@ msgstr "" msgid "Channel \"%s\"" msgstr "" -#: src/Content/Conversation.php:1553 src/Object/Post.php:250 +#: src/Content/Conversation.php:1553 src/Object/Post.php:254 msgid "Pinned item" msgstr "" -#: src/Content/Conversation.php:1570 src/Object/Post.php:552 -#: src/Object/Post.php:553 +#: src/Content/Conversation.php:1570 src/Object/Post.php:556 +#: src/Object/Post.php:557 #, php-format msgid "View %s's profile @ %s" msgstr "" -#: src/Content/Conversation.php:1584 src/Object/Post.php:540 +#: src/Content/Conversation.php:1584 src/Object/Post.php:544 msgid "Categories:" msgstr "" -#: src/Content/Conversation.php:1585 src/Object/Post.php:541 +#: src/Content/Conversation.php:1585 src/Object/Post.php:545 msgid "Filed under:" msgstr "" -#: src/Content/Conversation.php:1593 src/Object/Post.php:568 +#: src/Content/Conversation.php:1593 src/Object/Post.php:572 #, php-format msgid "%s from %s" msgstr "" @@ -1644,7 +1646,7 @@ msgstr "" msgid "Posts that mention or involve you" msgstr "" -#: src/Content/Conversation/Factory/Network.php:28 src/Object/Post.php:406 +#: src/Content/Conversation/Factory/Network.php:28 src/Object/Post.php:410 msgid "Starred" msgstr "" @@ -1918,16 +1920,16 @@ msgstr "" msgid "Collapse" msgstr "" -#: src/Content/Item.php:446 src/Object/Post.php:291 +#: src/Content/Item.php:446 src/Object/Post.php:295 #, php-format msgid "Ignore %s server" msgstr "" -#: src/Content/Item.php:450 src/Object/Post.php:512 +#: src/Content/Item.php:450 src/Object/Post.php:516 msgid "Detected languages" msgstr "" -#: src/Content/Item.php:453 src/Object/Post.php:595 +#: src/Content/Item.php:453 src/Object/Post.php:599 msgid "Raw content" msgstr "" @@ -2018,7 +2020,9 @@ msgid "Conversations you started" msgstr "" #: src/Content/Nav.php:229 src/Module/BaseProfile.php:50 -#: src/Module/Media/Photo/Browser.php:62 view/theme/frio/theme.php:222 +#: src/Module/Media/Attachment/Browser.php:67 +#: src/Module/Media/Photo/Browser.php:62 src/Module/Media/Photo/Browser.php:79 +#: view/theme/frio/theme.php:222 msgid "Photos" msgstr "" @@ -5799,7 +5803,7 @@ msgstr "" #: src/Module/Contact.php:542 src/Module/Conversation/Channel.php:98 #: src/Module/Conversation/Community.php:91 #: src/Module/Conversation/Network.php:384 -#: src/Module/Moderation/BaseUsers.php:130 src/Object/Post.php:615 +#: src/Module/Moderation/BaseUsers.php:130 src/Object/Post.php:619 msgid "More" msgstr "" @@ -5973,7 +5977,7 @@ msgstr "" #: src/Module/Moderation/Report/Create.php:200 #: src/Module/Moderation/Report/Create.php:260 #: src/Module/Settings/Server/Action.php:65 src/Module/User/Delegation.php:181 -#: src/Object/Post.php:1163 view/theme/duepuntozero/config.php:73 +#: src/Object/Post.php:1167 view/theme/duepuntozero/config.php:73 #: view/theme/quattro/config.php:75 view/theme/vier/config.php:123 msgid "Submit" msgstr "" @@ -6138,7 +6142,7 @@ msgid "Only show blocked contacts" msgstr "" #: src/Module/Contact.php:353 src/Module/Contact.php:425 -#: src/Module/Settings/Server/Index.php:94 src/Object/Post.php:394 +#: src/Module/Settings/Server/Index.php:94 src/Object/Post.php:398 msgid "Ignored" msgstr "" @@ -7308,6 +7312,8 @@ msgid "You need to be logged in to access this page." msgstr "" #: src/Module/Media/Attachment/Browser.php:61 +#: src/Module/Media/Attachment/Browser.php:68 +#: src/Module/Media/Photo/Browser.php:80 msgid "Files" msgstr "" @@ -7317,6 +7323,26 @@ msgstr "" msgid "Upload" msgstr "" +#: src/Module/Media/Attachment/Browser.php:70 +#: src/Module/Media/Photo/Browser.php:82 +msgid "Breadcrumb" +msgstr "" + +#: src/Module/Media/Attachment/Browser.php:71 +#: src/Module/Media/Photo/Browser.php:83 +msgid "Switch between photo and attachment mode" +msgstr "" + +#: src/Module/Media/Attachment/Browser.php:72 +#: src/Module/Media/Photo/Browser.php:84 +msgid "Album navigation" +msgstr "" + +#: src/Module/Media/Attachment/Browser.php:73 +#: src/Module/Media/Photo/Browser.php:85 +msgid "Browser content" +msgstr "" + #: src/Module/Media/Attachment/Upload.php:83 msgid "Sorry, maybe your upload is bigger than the PHP configuration allows" msgstr "" @@ -8735,7 +8761,7 @@ msgstr "" msgid "Private Message" msgstr "" -#: src/Module/Profile/Schedule.php:101 src/Object/Post.php:555 +#: src/Module/Profile/Schedule.php:101 src/Object/Post.php:559 msgid "via" msgstr "" @@ -11584,254 +11610,254 @@ msgstr "" msgid "Connector Message" msgstr "" -#: src/Object/Post.php:264 +#: src/Object/Post.php:268 msgid "Delete globally" msgstr "" -#: src/Object/Post.php:264 +#: src/Object/Post.php:268 msgid "Remove locally" msgstr "" -#: src/Object/Post.php:271 +#: src/Object/Post.php:275 #, php-format msgid "Block %s" msgstr "" -#: src/Object/Post.php:276 +#: src/Object/Post.php:280 #, php-format msgid "Ignore %s" msgstr "" -#: src/Object/Post.php:281 +#: src/Object/Post.php:285 #, php-format msgid "Collapse %s" msgstr "" -#: src/Object/Post.php:285 +#: src/Object/Post.php:289 msgid "Report post" msgstr "" -#: src/Object/Post.php:296 +#: src/Object/Post.php:300 msgid "Save to folder" msgstr "" -#: src/Object/Post.php:342 +#: src/Object/Post.php:346 msgid "I will attend" msgstr "" -#: src/Object/Post.php:342 +#: src/Object/Post.php:346 msgid "I will not attend" msgstr "" -#: src/Object/Post.php:342 +#: src/Object/Post.php:346 msgid "I might attend" msgstr "" -#: src/Object/Post.php:389 +#: src/Object/Post.php:393 msgid "Ignore thread" msgstr "" -#: src/Object/Post.php:390 +#: src/Object/Post.php:394 msgid "Unignore thread" msgstr "" -#: src/Object/Post.php:391 +#: src/Object/Post.php:395 msgid "Toggle ignore status" msgstr "" -#: src/Object/Post.php:401 +#: src/Object/Post.php:405 msgid "Add star" msgstr "" -#: src/Object/Post.php:402 +#: src/Object/Post.php:406 msgid "Remove star" msgstr "" -#: src/Object/Post.php:403 +#: src/Object/Post.php:407 msgid "Toggle star status" msgstr "" -#: src/Object/Post.php:414 +#: src/Object/Post.php:418 msgid "Pin" msgstr "" -#: src/Object/Post.php:415 +#: src/Object/Post.php:419 msgid "Unpin" msgstr "" -#: src/Object/Post.php:416 +#: src/Object/Post.php:420 msgid "Toggle pin status" msgstr "" -#: src/Object/Post.php:419 +#: src/Object/Post.php:423 msgid "Pinned" msgstr "" -#: src/Object/Post.php:424 +#: src/Object/Post.php:428 msgid "Add tag" msgstr "" -#: src/Object/Post.php:439 +#: src/Object/Post.php:443 msgid "Quote share this" msgstr "" -#: src/Object/Post.php:439 +#: src/Object/Post.php:443 msgid "Quote Share" msgstr "" -#: src/Object/Post.php:442 +#: src/Object/Post.php:446 msgid "Reshare this" msgstr "" -#: src/Object/Post.php:442 +#: src/Object/Post.php:446 msgid "Reshare" msgstr "" -#: src/Object/Post.php:443 +#: src/Object/Post.php:447 msgid "Cancel your Reshare" msgstr "" -#: src/Object/Post.php:443 +#: src/Object/Post.php:447 msgid "Unshare" msgstr "" -#: src/Object/Post.php:487 +#: src/Object/Post.php:491 #, php-format msgid "%s (Received %s)" msgstr "" -#: src/Object/Post.php:493 +#: src/Object/Post.php:497 msgid "Comment this item on your system" msgstr "" -#: src/Object/Post.php:493 +#: src/Object/Post.php:497 msgid "Remote comment" msgstr "" -#: src/Object/Post.php:517 +#: src/Object/Post.php:521 msgid "Share via ..." msgstr "" -#: src/Object/Post.php:517 +#: src/Object/Post.php:521 msgid "Share via external services" msgstr "" -#: src/Object/Post.php:524 +#: src/Object/Post.php:528 msgid "Unknown parent" msgstr "" -#: src/Object/Post.php:528 +#: src/Object/Post.php:532 #, php-format msgid "in reply to %s" msgstr "" -#: src/Object/Post.php:530 +#: src/Object/Post.php:534 msgid "Parent is probably private or not federated." msgstr "" -#: src/Object/Post.php:554 +#: src/Object/Post.php:558 msgid "to" msgstr "" -#: src/Object/Post.php:556 +#: src/Object/Post.php:560 msgid "Wall-to-Wall" msgstr "" -#: src/Object/Post.php:557 +#: src/Object/Post.php:561 msgid "via Wall-To-Wall:" msgstr "" -#: src/Object/Post.php:612 +#: src/Object/Post.php:616 #, php-format msgid "Reply to %s" msgstr "" -#: src/Object/Post.php:634 +#: src/Object/Post.php:638 msgid "Notifier task is pending" msgstr "" -#: src/Object/Post.php:635 +#: src/Object/Post.php:639 msgid "Delivery to remote servers is pending" msgstr "" -#: src/Object/Post.php:636 +#: src/Object/Post.php:640 msgid "Delivery to remote servers is underway" msgstr "" -#: src/Object/Post.php:637 +#: src/Object/Post.php:641 msgid "Delivery to remote servers is mostly done" msgstr "" -#: src/Object/Post.php:638 +#: src/Object/Post.php:642 msgid "Delivery to remote servers is done" msgstr "" -#: src/Object/Post.php:663 +#: src/Object/Post.php:667 #, php-format msgid "%d comment" msgid_plural "%d comments" msgstr[0] "" msgstr[1] "" -#: src/Object/Post.php:664 +#: src/Object/Post.php:668 msgid "Show more" msgstr "" -#: src/Object/Post.php:665 +#: src/Object/Post.php:669 msgid "Show fewer" msgstr "" -#: src/Object/Post.php:702 +#: src/Object/Post.php:706 #, php-format msgid "Reshared by: %s" msgstr "" -#: src/Object/Post.php:707 +#: src/Object/Post.php:711 #, php-format msgid "Viewed by: %s" msgstr "" -#: src/Object/Post.php:712 +#: src/Object/Post.php:716 #, php-format msgid "Read by: %s" msgstr "" -#: src/Object/Post.php:717 +#: src/Object/Post.php:721 #, php-format msgid "Liked by: %s" msgstr "" -#: src/Object/Post.php:722 +#: src/Object/Post.php:726 #, php-format msgid "Disliked by: %s" msgstr "" -#: src/Object/Post.php:727 +#: src/Object/Post.php:731 #, php-format msgid "Attended by: %s" msgstr "" -#: src/Object/Post.php:732 +#: src/Object/Post.php:736 #, php-format msgid "Maybe attended by: %s" msgstr "" -#: src/Object/Post.php:737 +#: src/Object/Post.php:741 #, php-format msgid "Not attended by: %s" msgstr "" -#: src/Object/Post.php:742 +#: src/Object/Post.php:746 #, php-format msgid "Commented by: %s" msgstr "" -#: src/Object/Post.php:747 +#: src/Object/Post.php:751 #, php-format msgid "Reacted with %s by: %s" msgstr "" -#: src/Object/Post.php:770 +#: src/Object/Post.php:774 #, php-format msgid "Quote shared by: %s" msgstr "" diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index 5165bc075b..1a4025b1dc 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -1697,6 +1697,9 @@ textarea.comment-edit-text:focus + .comment-edit-form .preview { .fbrowser.photo .photo-album-image-wrapper .jg-caption { pointer-events: none; } +.fbswitcher { + margin-top: -3px; +} /* Photo album hover effect using jg-caption */ .photo-top-image-wrapper { diff --git a/view/theme/frio/templates/media/browser.tpl b/view/theme/frio/templates/media/browser.tpl index 366bbc8944..c13730386c 100644 --- a/view/theme/frio/templates/media/browser.tpl +++ b/view/theme/frio/templates/media/browser.tpl @@ -10,11 +10,11 @@
    {{* The breadcrumb navigation *}} -
    diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index 1a4025b1dc..6e9a3ed354 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -1532,7 +1532,7 @@ section #jotOpen { } #jot-title-wrap, #jot-category-wrap { - margin-bottom: 5px; + margin-bottom: 10px; } #jot-text-wrap { margin-top: 20px; @@ -1561,6 +1561,14 @@ textarea.comment-edit-text:focus + .comment-edit-form .preview { border: 2px solid #6fdbe8; border-top: none; } +#compose-additional-settings-location { + align-items: center; + display: flex; + flex-grow: 1; + gap: 5px; + padding-bottom: 15px; +} + .preview hr.previewseparator { margin-top: 0px; border-color: #d2d2d2; @@ -2317,7 +2325,9 @@ wall-item-comment-wrapper.well hr { } .comment-edit-submit-wrapper { - text-align: right; + display: flex; + flex-wrap: wrap; + justify-content: flex-end; margin-bottom: 0; } From 44be322a977237618a1e8f3529474ea4778b472f Mon Sep 17 00:00:00 2001 From: philipp Date: Thu, 12 Feb 2026 19:33:45 +0100 Subject: [PATCH 058/197] [CI] add all-in-one package for Release --- .woodpecker/.releaser-allinone.yml | 96 ++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 .woodpecker/.releaser-allinone.yml diff --git a/.woodpecker/.releaser-allinone.yml b/.woodpecker/.releaser-allinone.yml new file mode 100644 index 0000000000..d23def1bd5 --- /dev/null +++ b/.woodpecker/.releaser-allinone.yml @@ -0,0 +1,96 @@ +# SPDX-FileCopyrightText: 2010 - 2024 the Friendica project +# +# SPDX-License-Identifier: CC0-1.0 + +# This prevents executing this pipeline at other servers than ci.friendi.ca +labels: + location: friendica + type: releaser + +skip_clone: true + +when: + repo: friendica/friendica + branch: stable + event: tag + +steps: + clone_friendica_base: + image: alpine/git + commands: + - git config --global user.email "no-reply@friendi.ca" + - git config --global user.name "Friendica" + - git config --global --add safe.directory $CI_WORKSPACE + - git clone $CI_REPO_CLONE_URL . + - git checkout $CI_COMMIT_BRANCH + - git fetch origin $CI_COMMIT_REF + - git merge $CI_COMMIT_SHA + clone_friendica_addon: + image: alpine/git + commands: + - git config --global user.email "no-reply@friendi.ca" + - git config --global user.name "Friendica" + - git clone https://github.com/friendica/friendica-addons.git addon + - cd addon/ + - git checkout $CI_COMMIT_BRANCH + restore_cache: + image: meltwater/drone-cache:dev + settings: + backend: "filesystem" + restore: true + cache_key: "{{ .Repo.Name }}_php7.4_{{ arch }}_{{ os }}" + archive_format: "gzip" + mount: + - '.composer' + volumes: + - /tmp/drone-cache:/tmp/cache + composer_install: + image: friendicaci/php8.2:php8.2.28 + commands: + - export COMPOSER_HOME=.composer + - composer validate + - composer install --no-dev --optimize-autoloader + volumes: + - /etc/hosts:/etc/hosts + create_artifacts: + image: debian + commands: + - apt-get update + - apt-get install bzip2 + - mkdir ./build + - export VERSION="$(cat VERSION)" + - export RELEASE="friendica-all-in-one-$VERSION" + - export ARTIFACT="$RELEASE.tar.gz" + - tar + --transform "s,^,$RELEASE/,S" + -X mods/release-list-exclude.txt + -T mods/release-list-include.txt + -cvzf ./build/$ARTIFACT + - cd ./build + - sha256sum "$ARTIFACT" > "$ARTIFACT.sum256" + - chmod 664 ./* + - ls -lh + - cat "$ARTIFACT.sum256" + - sha256sum "$ARTIFACT" + sign_artifacts: + image: plugins/gpgsign + settings: + key: + from_secret: gpg_key + passphrase: + from_secret: gpg_password + files: + - build/* + exclude: + - build/*.sum256 + detach_sign: true + when: + repo: friendica/friendica + branch: stable + event: tag + publish_artifacts: + image: alpine + commands: + - cp -fr build/* /tmp/friendica_files/ + volumes: + - files:/tmp/friendica_files From 65bb4b2751196ed50f1b86da0594de37cf442735 Mon Sep 17 00:00:00 2001 From: "Marcus F." Date: Wed, 11 Feb 2026 23:01:37 +0100 Subject: [PATCH 059/197] Frio: Make login form background color respect dark theme --- view/theme/frio/css/style.css | 2 +- view/theme/frio/scheme/light.css | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 view/theme/frio/scheme/light.css diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index 5165bc075b..b01becfee5 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -4093,7 +4093,7 @@ div.login-form, .login-content-wrapper, .mod-home.is-not-singleuser .login-form, .mod-login #content .login-form { - background-color: #fff; + background-color: $background_color; padding: 1.5em; position: relative; } diff --git a/view/theme/frio/scheme/light.css b/view/theme/frio/scheme/light.css new file mode 100644 index 0000000000..126c5a4281 --- /dev/null +++ b/view/theme/frio/scheme/light.css @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: 2010-2024 the Friendica project + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +/* + Licence : AGPL + Created on : 12.02.2026 + Author : Marcus Funch +*/ + +.mod-home.is-not-singleuser .login-form { + background: #fcfcfc; +} From fa6d82363ad6baf8591914e6adbb195898e02d35 Mon Sep 17 00:00:00 2001 From: "Marcus F." Date: Thu, 12 Feb 2026 23:07:05 +0100 Subject: [PATCH 060/197] Fix bug in #15486 - photo/file browser --- view/theme/frio/templates/media/browser.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view/theme/frio/templates/media/browser.tpl b/view/theme/frio/templates/media/browser.tpl index c13730386c..0ee2e9f686 100644 --- a/view/theme/frio/templates/media/browser.tpl +++ b/view/theme/frio/templates/media/browser.tpl @@ -48,7 +48,7 @@ {{/if}} {{* The main content (images or files) *}} -
    +
    {{foreach $files as $f}}
    From 27e256c7e3513b28eb78cbbf0e67b9aef7088fd3 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 12 Feb 2026 21:23:33 +0000 Subject: [PATCH 061/197] Don't transmit "View" activities via Diaspora --- src/Worker/Notifier.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Worker/Notifier.php b/src/Worker/Notifier.php index 4c329def2b..e7ff0f3352 100644 --- a/src/Worker/Notifier.php +++ b/src/Worker/Notifier.php @@ -332,6 +332,11 @@ class Notifier $ap_contacts = $apdelivery['contacts']; $delivery_queue_count += $apdelivery['count']; + if ($target_item['verb'] === Activity::VIEW) { + DI::logger()->info('Not delivering view activities', ['guid' => $target_item['guid'], 'uri-id' => $target_item['uri-id']]); + return; + } + if (!$only_ap_delivery) { if (empty($delivery_contacts_stmt)) { $condition = ['id' => $recipients, 'self' => false, 'uid' => [0, $uid], @@ -384,7 +389,7 @@ class Notifier $delivery_queue_count += self::delivery($cmd, $post_uriid, $sender_uid, $target_item, $parent, $thr_parent, $owner, $batch_delivery, false, $contacts, $ap_contacts, $conversants); } - if (!empty($target_item)) { + if ($target_item) { DI::logger()->info('Calling hooks for ' . $cmd . ' ' . $target_id); Hook::fork($appHelper->getQueueValue('priority'), 'notifier_normal', $target_item); From c310fec8308e69914fb6788beba41efe27019528 Mon Sep 17 00:00:00 2001 From: "Marcus F." Date: Thu, 29 Jan 2026 19:08:52 +0100 Subject: [PATCH 062/197] Adjustments to some strings around photos and events --- mod/notes.php | 2 +- mod/photos.php | 8 +-- src/Module/BaseProfile.php | 2 +- src/Module/Calendar/Event/Form.php | 8 +-- src/Module/Profile/Photos.php | 4 +- src/Module/Settings/Account.php | 12 ++--- src/Module/Settings/Display.php | 4 +- src/Module/Settings/Profile/Index.php | 4 +- view/lang/C/messages.po | 72 +++++++++++++-------------- 9 files changed, 56 insertions(+), 60 deletions(-) diff --git a/mod/notes.php b/mod/notes.php index 478e4c4aca..aa647520f4 100644 --- a/mod/notes.php +++ b/mod/notes.php @@ -38,7 +38,7 @@ function notes_content(bool $update = false) $o = BaseProfile::getTabsHTML('notes', true, DI::userSession()->getLocalUserNickname(), false); if (!$update) { - $o .= '

    ' . DI::l10n()->t('Personal Notes') . '

    '; + $o .= '

    ' . DI::l10n()->t('Personal notes') . '

    '; $x = [ 'lockstate' => 'lock', diff --git a/mod/photos.php b/mod/photos.php index 5d295a2ca9..271be56b07 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -88,7 +88,7 @@ function photos_init() '$title' => DI::l10n()->t('Photo Albums'), '$recent' => DI::l10n()->t('Recent Photos'), '$albums' => $ret['albums'], - '$upload' => [DI::l10n()->t('Upload Photos'), 'photos/' . $owner['nickname'] . '/upload'], + '$upload' => [DI::l10n()->t('Upload photo'), 'photos/' . $owner['nickname'] . '/upload'], '$can_post' => $can_post ]); } @@ -656,7 +656,7 @@ function photos_content() $default_upload_box = Renderer::replaceMacros(Renderer::getMarkupTemplate('photos_default_uploader_box.tpl'), []); $default_upload_submit = Renderer::replaceMacros(Renderer::getMarkupTemplate('photos_default_uploader_submit.tpl'), [ - '$submit' => DI::l10n()->t('Upload selected picture'), + '$submit' => DI::l10n()->t('Upload selected photo'), ]); // Get the relevant size limits for uploads. Abbreviated var names: MaxImageSize -> mis; upload_max_filesize -> umf @@ -679,7 +679,7 @@ function photos_content() $aclselect_e = ($visitor ? '' : ACL::getFullSelectorHTML(DI::page(), DI::userSession()->getLocalUserId())); $o .= Renderer::replaceMacros($tpl, [ - '$pagename' => DI::l10n()->t('Upload Photos'), + '$pagename' => DI::l10n()->t('Upload photo'), '$sessid' => session_id(), '$usage' => $usage_message, '$nickname' => $user['nickname'], @@ -823,7 +823,7 @@ function photos_content() '$photos' => $photos, '$album' => $album, '$can_post' => $can_post, - '$upload' => [DI::l10n()->t('Upload Photos'), 'photos/' . $user['nickname'] . '/upload/' . bin2hex($album)], + '$upload' => [DI::l10n()->t('Upload photo'), 'photos/' . $user['nickname'] . '/upload/' . bin2hex($album)], '$order' => $order, '$edit' => $edit, '$drop' => $drop, diff --git a/src/Module/BaseProfile.php b/src/Module/BaseProfile.php index ce5d276861..4259bf04a3 100644 --- a/src/Module/BaseProfile.php +++ b/src/Module/BaseProfile.php @@ -90,7 +90,7 @@ class BaseProfile extends BaseModule if ($is_owner) { $tabs[] = [ - 'label' => DI::l10n()->t('Personal Notes'), + 'label' => DI::l10n()->t('Personal notes'), 'url' => DI::baseUrl() . '/notes', 'sel' => $current == 'notes' ? 'active' : '', 'title' => DI::l10n()->t('Only You Can See This'), diff --git a/src/Module/Calendar/Event/Form.php b/src/Module/Calendar/Event/Form.php index 51f6c83bc9..bcd0cd5c2f 100644 --- a/src/Module/Calendar/Event/Form.php +++ b/src/Module/Calendar/Event/Form.php @@ -206,14 +206,14 @@ class Form extends BaseModule true ), - '$n_text' => $this->t('Finish date/time is not known or not relevant'), + '$n_text' => $this->t('End date/time is unknown or irrelevant'), '$n_checked' => $n_checked, - '$f_text' => $this->t('Event Finishes:'), + '$f_text' => $this->t('Event ends:'), '$f_dsel' => Temporal::getDateTimeField( new \DateTime(), \DateTime::createFromFormat('Y', intval($fyear) + 5), \DateTime::createFromFormat('Y-m-d H:i', "$fyear-$fmonth-$fday $fhour:$fminute"), - $this->t('Event Finishes:'), + $this->t('Event ends:'), 'finish_text', true, true, @@ -230,7 +230,7 @@ class Form extends BaseModule '$sh_text' => $this->t('Share this event'), '$share' => ['share', $this->t('Share this event'), $share_checked, '', $share_disabled], '$sh_checked' => $share_checked, - '$nofinish' => ['nofinish', $this->t('Finish date/time is not known or not relevant'), $n_checked], + '$nofinish' => ['nofinish', $this->t('End date/time is unknown or irrelevant'), $n_checked], '$preview' => $this->t('Preview'), '$acl' => $acl, '$submit' => $this->t('Submit'), diff --git a/src/Module/Profile/Photos.php b/src/Module/Profile/Photos.php index 63320fb05c..313b10caa7 100644 --- a/src/Module/Profile/Photos.php +++ b/src/Module/Profile/Photos.php @@ -439,10 +439,10 @@ class Photos extends \Friendica\Module\BaseProfile $o .= Renderer::replaceMacros($tpl, [ '$title' => $this->t('Recent Photos'), '$can_post' => $is_owner, - '$upload' => [$this->t('Upload Photos'), 'photos/' . $this->owner['nickname'] . '/upload'], + '$upload' => [$this->t('Upload photo'), 'photos/' . $this->owner['nickname'] . '/upload'], '$photos' => $photos, '$paginate' => $pager->renderFull($total), - 'upload_text' => $this->t('Upload Photos'), + 'upload_text' => $this->t('Upload photo'), ]); return $o; diff --git a/src/Module/Settings/Account.php b/src/Module/Settings/Account.php index b65ac03101..67f0788df4 100644 --- a/src/Module/Settings/Account.php +++ b/src/Module/Settings/Account.php @@ -504,7 +504,7 @@ class Account extends BaseSettings '$ptitle' => DI::l10n()->t('Account Settings'), '$desc' => DI::l10n()->t("Your Identity Address is '%s' or '%s'.", $nickname . '@' . DI::baseUrl()->getHost() . DI::baseUrl()->getPath(), DI::baseUrl() . '/profile/' . $nickname), - '$submit' => DI::l10n()->t('Save Settings'), + '$submit' => DI::l10n()->t('Save settings'), '$uid' => DI::userSession()->getLocalUserId(), '$form_security_token' => self::getFormSecurityToken('settings'), '$open' => $this->parameters['open'] ?? 'password', @@ -543,7 +543,7 @@ class Account extends BaseSettings '$aclselect' => ACL::getFullSelectorHTML(DI::page(), $this->session->getLocalUserId()), '$expire' => [ - 'label' => DI::l10n()->t('Expiration settings'), + 'label' => DI::l10n()->t('Post expiration'), 'days' => ['expire', DI::l10n()->t("Automatically expire posts after this many days:"), $expire, DI::l10n()->t('If empty, posts will not expire. Expired posts will be deleted')], 'items' => ['expire_items', DI::l10n()->t('Expire posts'), $expire_items, DI::l10n()->t('When activated, posts and comments will be expired.')], 'notes' => ['expire_notes', DI::l10n()->t('Expire personal notes'), $expire_notes, DI::l10n()->t('When activated, the personal notes on your profile page will be expired.')], @@ -551,17 +551,17 @@ class Account extends BaseSettings 'network_only' => ['expire_network_only', DI::l10n()->t('Only expire posts by others'), $expire_network_only, DI::l10n()->t('When activated, your own posts never expire. Then the settings above are only valid for posts you received.')], ], - '$h_not' => DI::l10n()->t('Notification Settings'), - '$lbl_not' => DI::l10n()->t('Send a notification email when:'), + '$h_not' => DI::l10n()->t('Notifications'), + '$lbl_not' => DI::l10n()->t('Send an email when:'), '$notify1' => ['notify1', DI::l10n()->t('You receive an introduction'), ($notify & Notification\Type::INTRO), Notification\Type::INTRO, ''], '$notify2' => ['notify2', DI::l10n()->t('Your introductions are confirmed'), ($notify & Notification\Type::CONFIRM), Notification\Type::CONFIRM, ''], - '$notify3' => ['notify3', DI::l10n()->t('Someone writes on your profile wall'), ($notify & Notification\Type::WALL), Notification\Type::WALL, ''], + '$notify3' => ['notify3', DI::l10n()->t('Someone writes on your wall'), ($notify & Notification\Type::WALL), Notification\Type::WALL, ''], '$notify4' => ['notify4', DI::l10n()->t('Someone writes a followup comment'), ($notify & Notification\Type::COMMENT), Notification\Type::COMMENT, ''], '$notify5' => ['notify5', DI::l10n()->t('You receive a private message'), ($notify & Notification\Type::MAIL), Notification\Type::MAIL, ''], '$notify6' => ['notify6', DI::l10n()->t('You receive a friend suggestion'), ($notify & Notification\Type::SUGGEST), Notification\Type::SUGGEST, ''], '$notify7' => ['notify7', DI::l10n()->t('You are tagged in a post'), ($notify & Notification\Type::TAG_SELF), Notification\Type::TAG_SELF, ''], - '$lbl_notify' => DI::l10n()->t('Create a desktop notification when:'), + '$lbl_notify' => DI::l10n()->t('Notify when:'), '$notify_tagged' => ['notify_tagged', DI::l10n()->t('Someone tagged you'), is_null($notify_type) || $notify_type & UserNotification::TYPE_EXPLICIT_TAGGED, ''], '$notify_direct_comment' => ['notify_direct_comment', DI::l10n()->t('Someone directly commented on your post'), is_null($notify_type) || $notify_type & (UserNotification::TYPE_IMPLICIT_TAGGED + UserNotification::TYPE_DIRECT_COMMENT + UserNotification::TYPE_DIRECT_THREAD_COMMENT), ''], '$notify_like' => ['notify_like', DI::l10n()->t('Someone liked your content'), DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'notify_like'), DI::l10n()->t('Can only be enabled, when the direct comment notification is enabled.')], diff --git a/src/Module/Settings/Display.php b/src/Module/Settings/Display.php index 9f6e757131..04ba259b70 100644 --- a/src/Module/Settings/Display.php +++ b/src/Module/Settings/Display.php @@ -446,14 +446,14 @@ class Display extends BaseSettings '$form_security_token' => self::getFormSecurityToken('settings_display'), '$uid' => $uid, - '$theme' => ['theme', $this->t('Display theme'), $theme_selected, '', $themes, true], + '$theme' => ['theme', $this->t('Theme'), $theme_selected, '', $themes, true], '$mobile_theme' => ['mobile_theme', $this->t('Mobile theme'), $mobile_theme_selected, '', $mobile_themes, false], '$theme_config' => $theme_config, '$itemspage_network' => ['itemspage_network', $this->t('Number of items to display per page:'), $itemspage_network, $this->t('Maximum of 100 items')], '$itemspage_mobile_network' => ['itemspage_mobile_network', $this->t('Number of items to display per page when viewed from mobile device:'), $itemspage_mobile_network, $this->t('Maximum of 100 items')], '$update_content' => ['update_content', $this->t('Regularly update the page content'), $update_content, $this->t('When enabled, new content on network, community and channels are added on top.')], - '$enable_smile' => ['enable_smile', $this->t('Display emoticons'), $enable_smile, $this->t('When enabled, emoticons are replaced with matching symbols.')], + '$enable_smile' => ['enable_smile', $this->t('Display emojis'), $enable_smile, $this->t('When enabled, emoticons are replaced with matching emojis.')], '$infinite_scroll' => ['infinite_scroll', $this->t('Infinite scroll'), $infinite_scroll, $this->t('Automatic fetch new items when reaching the page end.')], '$enable_smart_threading' => ['enable_smart_threading', $this->t('Enable Smart Threading'), $enable_smart_threading, $this->t('Enable the automatic suppression of extraneous thread indentation.')], '$enable_dislike' => ['enable_dislike', $this->t('Display the Dislike feature'), $enable_dislike, $this->t('Display the Dislike button and dislike reactions on posts and comments.')], diff --git a/src/Module/Settings/Profile/Index.php b/src/Module/Settings/Profile/Index.php index 4a2b3420bf..b0420ba88a 100644 --- a/src/Module/Settings/Profile/Index.php +++ b/src/Module/Settings/Profile/Index.php @@ -313,8 +313,8 @@ class Index extends BaseSettings '$xmpp' => ['xmpp', $this->t('XMPP (Jabber) address:'), $owner['xmpp'], $this->t('The XMPP address will be published so that people can follow you there.')], '$matrix' => ['matrix', $this->t('Matrix (Element) address:'), $owner['matrix'], $this->t('The Matrix address will be published so that people can follow you there.')], '$homepage' => ['homepage', $this->t('Homepage URL:'), $owner['homepage'], $homepage_help_text], - '$pub_keywords' => ['pub_keywords', $this->t('Public Keywords:'), $owner['pub_keywords'], $this->t('(Used for suggesting potential friends, can be seen by others)')], - '$prv_keywords' => ['prv_keywords', $this->t('Private Keywords:'), $owner['prv_keywords'], $this->t('(Used for searching profiles, never shown to others)')], + '$pub_keywords' => ['pub_keywords', $this->t('Public Keywords:'), $owner['pub_keywords'], $this->t('Used for suggesting potential friends, can be seen by others.')], + '$prv_keywords' => ['prv_keywords', $this->t('Private Keywords:'), $owner['prv_keywords'], $this->t('Used for searching profiles, never shown to others.')], '$custom_fields' => $custom_fields, ]); diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index 50ec467d7d..2de4e96bfa 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 2026.04-dev\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-02-12 18:06+0100\n" +"POT-Creation-Date: 2026-02-12 23:20+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -272,8 +272,10 @@ msgstr "" msgid "Your message:" msgstr "" -#: mod/message.php:188 mod/message.php:345 src/Content/Conversation.php:371 -#: src/Module/Post/Edit.php:129 +#: mod/message.php:188 mod/message.php:345 mod/photos.php:91 mod/photos.php:682 +#: mod/photos.php:826 src/Content/Conversation.php:371 +#: src/Module/Post/Edit.php:129 src/Module/Profile/Photos.php:442 +#: src/Module/Profile/Photos.php:445 msgid "Upload photo" msgstr "" @@ -342,8 +344,8 @@ msgid_plural "%d messages" msgstr[0] "" msgstr[1] "" -#: mod/notes.php:41 src/Module/BaseProfile.php:93 -msgid "Personal Notes" +#: mod/notes.php:41 src/Content/Nav.php:231 src/Module/BaseProfile.php:93 +msgid "Personal notes" msgstr "" #: mod/notes.php:45 @@ -378,12 +380,6 @@ msgstr "" msgid "Recent Photos" msgstr "" -#: mod/photos.php:91 mod/photos.php:682 mod/photos.php:826 -#: src/Module/Profile/Photos.php:422 src/Module/Profile/Photos.php:442 -#: src/Module/Profile/Photos.php:445 -msgid "Upload Photos" -msgstr "" - #: mod/photos.php:103 src/Module/BaseSettings.php:60 #: src/Module/Profile/Photos.php:403 msgid "everybody" @@ -428,8 +424,8 @@ msgstr "" msgid "No photos selected" msgstr "" -#: mod/photos.php:659 src/Module/Settings/Profile/Index.php:276 -msgid "Upload selected picture" +#: mod/photos.php:659 +msgid "Upload selected photo" msgstr "" #: mod/photos.php:675 @@ -2042,10 +2038,6 @@ msgstr "" msgid "Your calendar" msgstr "" -#: src/Content/Nav.php:231 -msgid "Personal notes" -msgstr "" - #: src/Content/Nav.php:231 msgid "Your personal notes" msgstr "" @@ -2162,6 +2154,7 @@ msgstr "" #: src/Content/Nav.php:310 src/Module/BaseNotifications.php:134 #: src/Module/Notifications/Introductions.php:63 +#: src/Module/Settings/Account.php:554 msgid "Notifications" msgstr "" @@ -3951,8 +3944,7 @@ msgstr "" #: src/Module/Admin/Addons/Index.php:85 src/Module/Admin/Features.php:69 #: src/Module/Admin/Logs/Settings.php:76 src/Module/Admin/Site.php:460 #: src/Module/Admin/Themes/Index.php:105 src/Module/Admin/Tos.php:72 -#: src/Module/Settings/Account.php:507 src/Module/Settings/Addons.php:64 -#: src/Module/Settings/Connectors.php:143 +#: src/Module/Settings/Addons.php:64 src/Module/Settings/Connectors.php:143 #: src/Module/Settings/Connectors.php:228 #: src/Module/Settings/ContactImport.php:111 #: src/Module/Settings/Delegation.php:179 src/Module/Settings/Display.php:427 @@ -5937,12 +5929,12 @@ msgstr "" #: src/Module/Calendar/Event/Form.php:209 #: src/Module/Calendar/Event/Form.php:233 -msgid "Finish date/time is not known or not relevant" +msgid "End date/time is unknown or irrelevant" msgstr "" #: src/Module/Calendar/Event/Form.php:211 #: src/Module/Calendar/Event/Form.php:216 -msgid "Event Finishes:" +msgid "Event ends:" msgstr "" #: src/Module/Calendar/Event/Form.php:223 @@ -8647,6 +8639,10 @@ msgstr "" msgid "View Album" msgstr "" +#: src/Module/Profile/Photos.php:422 +msgid "Upload Photos" +msgstr "" + #: src/Module/Profile/Profile.php:121 src/Module/Profile/Profile.php:156 #: src/Module/Profile/Restricted.php:38 msgid "Profile not found." @@ -9272,6 +9268,10 @@ msgstr "" msgid "Your Identity Address is '%s' or '%s'." msgstr "" +#: src/Module/Settings/Account.php:507 view/theme/frio/config.php:158 +msgid "Save settings" +msgstr "" + #: src/Module/Settings/Account.php:512 msgid "Password Settings" msgstr "" @@ -9401,7 +9401,7 @@ msgid "Default Post Permissions" msgstr "" #: src/Module/Settings/Account.php:546 -msgid "Expiration settings" +msgid "Post expiration" msgstr "" #: src/Module/Settings/Account.php:547 @@ -9444,12 +9444,8 @@ msgstr "" msgid "When activated, your own posts never expire. Then the settings above are only valid for posts you received." msgstr "" -#: src/Module/Settings/Account.php:554 -msgid "Notification Settings" -msgstr "" - #: src/Module/Settings/Account.php:555 -msgid "Send a notification email when:" +msgid "Send an email when:" msgstr "" #: src/Module/Settings/Account.php:556 @@ -9461,7 +9457,7 @@ msgid "Your introductions are confirmed" msgstr "" #: src/Module/Settings/Account.php:558 -msgid "Someone writes on your profile wall" +msgid "Someone writes on your wall" msgstr "" #: src/Module/Settings/Account.php:559 @@ -9481,7 +9477,7 @@ msgid "You are tagged in a post" msgstr "" #: src/Module/Settings/Account.php:564 -msgid "Create a desktop notification when:" +msgid "Notify when:" msgstr "" #: src/Module/Settings/Account.php:565 @@ -10067,7 +10063,7 @@ msgid "Reset order" msgstr "" #: src/Module/Settings/Display.php:449 -msgid "Display theme" +msgid "Theme" msgstr "" #: src/Module/Settings/Display.php:450 @@ -10095,11 +10091,11 @@ msgid "When enabled, new content on network, community and channels are added on msgstr "" #: src/Module/Settings/Display.php:456 -msgid "Display emoticons" +msgid "Display emojis" msgstr "" #: src/Module/Settings/Display.php:456 -msgid "When enabled, emoticons are replaced with matching symbols." +msgid "When enabled, emoticons are replaced with matching emojis." msgstr "" #: src/Module/Settings/Display.php:457 @@ -10324,6 +10320,10 @@ msgstr "" msgid "Upload new picture" msgstr "" +#: src/Module/Settings/Profile/Index.php:276 +msgid "Upload selected picture" +msgstr "" + #: src/Module/Settings/Profile/Index.php:277 msgid "Pick existing picture from photos" msgstr "" @@ -10404,7 +10404,7 @@ msgid "Public Keywords:" msgstr "" #: src/Module/Settings/Profile/Index.php:316 -msgid "(Used for suggesting potential friends, can be seen by others)" +msgid "Used for suggesting potential friends, can be seen by others." msgstr "" #: src/Module/Settings/Profile/Index.php:317 @@ -10412,7 +10412,7 @@ msgid "Private Keywords:" msgstr "" #: src/Module/Settings/Profile/Index.php:317 -msgid "(Used for searching profiles, never shown to others)" +msgid "Used for searching profiles, never shown to others." msgstr "" #: src/Module/Settings/Profile/Photo/Crop.php:90 @@ -12015,10 +12015,6 @@ msgstr "" msgid "Ensure that the image has the correct permissions, allowing all users to view it." msgstr "" -#: view/theme/frio/config.php:158 -msgid "Save settings" -msgstr "" - #: view/theme/frio/config.php:160 msgid "Appearance" msgstr "" From 265614db2d813e3611dcbb2212b9adf4b96e841e Mon Sep 17 00:00:00 2001 From: "Marcus F." Date: Wed, 11 Feb 2026 21:16:14 +0100 Subject: [PATCH 063/197] Fix CS --- mod/notes.php | 27 ++++++++++++++++++--------- src/Module/BaseProfile.php | 2 +- src/Module/Calendar/Event/Form.php | 6 ++++-- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/mod/notes.php b/mod/notes.php index aa647520f4..0aeffbca21 100644 --- a/mod/notes.php +++ b/mod/notes.php @@ -1,4 +1,5 @@ 'lock', - 'acl' => \Friendica\Core\ACL::getSelfOnlyHTML(DI::userSession()->getLocalUserId(), DI::l10n()->t('Personal notes are visible only by yourself.')), - 'button' => DI::l10n()->t('Save'), - 'acl_data' => '', + 'acl' => \Friendica\Core\ACL::getSelfOnlyHTML(DI::userSession()->getLocalUserId(), DI::l10n()->t('Personal notes are visible only by yourself.')), + 'button' => DI::l10n()->t('Save'), + 'acl_data' => '', ]; $o .= DI::conversation()->statusEditor($x, $contactId); } $condition = ['uid' => DI::userSession()->getLocalUserId(), 'post-type' => Item::PT_PERSONAL_NOTE, 'gravity' => Item::GRAVITY_PARENT, - 'contact-id'=> $contactId]; + 'contact-id' => $contactId]; if (DI::mode()->isMobile()) { - $itemsPerPage = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'itemspage_mobile_network', - DI::config()->get('system', 'itemspage_network_mobile')); + $itemsPerPage = DI::pConfig()->get( + DI::userSession()->getLocalUserId(), + 'system', + 'itemspage_mobile_network', + DI::config()->get('system', 'itemspage_network_mobile') + ); } else { - $itemsPerPage = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'itemspage_network', - DI::config()->get('system', 'itemspage_network')); + $itemsPerPage = DI::pConfig()->get( + DI::userSession()->getLocalUserId(), + 'system', + 'itemspage_network', + DI::config()->get('system', 'itemspage_network') + ); } $pager = new Pager(DI::l10n(), DI::args()->getQueryString(), $itemsPerPage); $params = ['order' => ['created' => true], - 'limit' => [$pager->getStart(), $pager->getItemsPerPage()]]; + 'limit' => [$pager->getStart(), $pager->getItemsPerPage()]]; $r = Post::selectThreadForUser(DI::userSession()->getLocalUserId(), ['uri-id'], $condition, $params); $count = 0; diff --git a/src/Module/BaseProfile.php b/src/Module/BaseProfile.php index 4259bf04a3..740cf592da 100644 --- a/src/Module/BaseProfile.php +++ b/src/Module/BaseProfile.php @@ -76,7 +76,7 @@ class BaseProfile extends BaseModule ]; } else { $owner = User::getByNickname($nickname, ['uid']); - if(DI::userSession()->isAuthenticated() || $owner && Feature::isEnabled($owner['uid'], Feature::PUBLIC_CALENDAR)) { + if (DI::userSession()->isAuthenticated() || $owner && Feature::isEnabled($owner['uid'], Feature::PUBLIC_CALENDAR)) { $tabs[] = [ 'label' => DI::l10n()->t('Calendar'), 'url' => DI::baseUrl() . '/calendar/show/' . $nickname, diff --git a/src/Module/Calendar/Event/Form.php b/src/Module/Calendar/Event/Form.php index bcd0cd5c2f..d525fac7f0 100644 --- a/src/Module/Calendar/Event/Form.php +++ b/src/Module/Calendar/Event/Form.php @@ -108,8 +108,10 @@ class Form extends BaseModule $share_disabled = ''; if (empty($orig_event)) { - $orig_event = User::getById($this->session->getLocalUserId(), - ['allow_cid', 'allow_gid', 'deny_cid', 'deny_gid']); + $orig_event = User::getById( + $this->session->getLocalUserId(), + ['allow_cid', 'allow_gid', 'deny_cid', 'deny_gid'] + ); } elseif ($orig_event['allow_cid'] !== '<' . $this->session->getLocalUserId() . '>' || $orig_event['allow_gid'] || $orig_event['deny_cid'] From 003a54a429d3eaed3a7ba40b555712ee4c14d175 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 13 Feb 2026 04:40:20 +0000 Subject: [PATCH 064/197] Don't process "View" --- src/Worker/Notifier.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Worker/Notifier.php b/src/Worker/Notifier.php index e7ff0f3352..372af7ac90 100644 --- a/src/Worker/Notifier.php +++ b/src/Worker/Notifier.php @@ -690,6 +690,12 @@ class Notifier return ['count' => 0, 'contacts' => []]; } + // "View" is not delivered + if ($target_item['verb'] === Activity::VIEW) { + DI::logger()->info('Not delivering view activities', ['guid' => $target_item['guid'], 'uri-id' => $target_item['uri-id']]); + return ['count' => 0, 'contacts' => []]; + } + $inboxes = []; $relay_inboxes = []; From da9e6998851781141d2105900dbd8086613c106f Mon Sep 17 00:00:00 2001 From: Marcus Funch Date: Sun, 11 Jan 2026 18:21:19 +0100 Subject: [PATCH 065/197] Admin logs rename settings page, minor ui adjustments --- src/Module/Admin/Logs/Settings.php | 22 ++--- src/Module/Admin/Logs/View.php | 10 +-- src/Module/BaseAdmin.php | 4 +- view/lang/C/messages.po | 81 ++++++++++--------- view/templates/admin/logs/settings.tpl | 10 +-- view/templates/admin/logs/view.tpl | 2 +- view/theme/frio/css/style.css | 10 ++- view/theme/frio/templates/admin/logs/view.tpl | 14 ++-- 8 files changed, 84 insertions(+), 69 deletions(-) diff --git a/src/Module/Admin/Logs/Settings.php b/src/Module/Admin/Logs/Settings.php index a0dd009899..be0f8f01ae 100644 --- a/src/Module/Admin/Logs/Settings.php +++ b/src/Module/Admin/Logs/Settings.php @@ -71,20 +71,20 @@ class Settings extends BaseAdmin $t = Renderer::getMarkupTemplate('admin/logs/settings.tpl'); return Renderer::replaceMacros($t, [ - '$title' => DI::l10n()->t('Administration'), - '$page' => DI::l10n()->t('Logs'), - '$submit' => DI::l10n()->t('Save Settings'), - '$clear' => DI::l10n()->t('Clear'), + '$title' => DI::l10n()->t('Administration'), + '$page' => DI::l10n()->t('Log settings'), + '$submit' => DI::l10n()->t('Save Settings'), + '$clear' => DI::l10n()->t('Clear'), '$logname' => DI::config()->get('system', 'logfile'), // see /help/smarty3-templates#1_1 on any Friendica node - '$debugging' => ['debugging', DI::l10n()->t('Enable Debugging'), DI::config()->get('system', 'debugging'), !DI::config()->isWritable('system', 'debugging') ? DI::l10n()->t('Read-only because it is set by an environment variable') : '', !DI::config()->isWritable('system', 'debugging') ? 'disabled' : ''], - '$logfile' => ['logfile', DI::l10n()->t('Log file'), DI::config()->get('system', 'logfile'), DI::l10n()->t('Must be writable by web server. Relative to your Friendica top-level directory.') . (!DI::config()->isWritable('system', 'logfile') ? '
    ' . DI::l10n()->t('Read-only because it is set by an environment variable') : ''), '', !DI::config()->isWritable('system', 'logfile') ? 'disabled' : ''], - '$loglevel' => ['loglevel', DI::l10n()->t("Log level"), DI::config()->get('system', 'loglevel'), !DI::config()->isWritable('system', 'loglevel') ? DI::l10n()->t('Read-only because it is set by an environment variable') : '', $log_choices, !DI::config()->isWritable('system', 'loglevel') ? 'disabled' : ''], + '$debugging' => ['debugging', DI::l10n()->t('Enable Debugging'), DI::config()->get('system', 'debugging'), !DI::config()->isWritable('system', 'debugging') ? DI::l10n()->t('Read-only because it is set by an environment variable') : '', !DI::config()->isWritable('system', 'debugging') ? 'disabled' : ''], + '$logfile' => ['logfile', DI::l10n()->t('Log file'), DI::config()->get('system', 'logfile'), DI::l10n()->t('Must be writable by web server. Relative to your Friendica top-level directory.') . (!DI::config()->isWritable('system', 'logfile') ? '
    ' . DI::l10n()->t('Read-only because it is set by an environment variable') : ''), '', !DI::config()->isWritable('system', 'logfile') ? 'disabled' : ''], + '$loglevel' => ['loglevel', DI::l10n()->t("Log level"), DI::config()->get('system', 'loglevel'), !DI::config()->isWritable('system', 'loglevel') ? DI::l10n()->t('Read-only because it is set by an environment variable') : '', $log_choices, !DI::config()->isWritable('system', 'loglevel') ? 'disabled' : ''], '$form_security_token' => self::getFormSecurityToken("admin_logs"), - '$phpheader' => DI::l10n()->t("PHP logging"), - '$phphint' => DI::l10n()->t("To temporarily enable logging of PHP errors and warnings you can prepend the following to the index.php file of your installation. The filename set in the 'error_log' line is relative to the friendica top-level directory and must be writeable by the web server. The option '1' for 'log_errors' and 'display_errors' is to enable these options, set to '0' to disable them."), - '$phplogcode' => "error_reporting(E_ERROR | E_WARNING | E_PARSE);\nini_set('error_log','php.out');\nini_set('log_errors','1');\nini_set('display_errors', '1');", - '$phplogenabled' => $phplogenabled, + '$phpheader' => DI::l10n()->t("PHP logging"), + '$phphint' => DI::l10n()->t("To temporarily enable logging of PHP errors and warnings you can prepend the following to the index.php file of your installation. The filename set in the 'error_log' line is relative to the friendica top-level directory and must be writeable by the web server. The option '1' for 'log_errors' and 'display_errors' is to enable these options, set to '0' to disable them."), + '$phplogcode' => "error_reporting(E_ERROR | E_WARNING | E_PARSE);\nini_set('error_log','php.out');\nini_set('log_errors','1');\nini_set('display_errors', '1');", + '$phplogenabled' => $phplogenabled, ]); } } diff --git a/src/Module/Admin/Logs/View.php b/src/Module/Admin/Logs/View.php index 87c7c9923e..3449957050 100644 --- a/src/Module/Admin/Logs/View.php +++ b/src/Module/Admin/Logs/View.php @@ -45,7 +45,7 @@ class View extends BaseAdmin 'context' => ['', 'index', 'worker', 'daemon'], ]; $filters = [ - 'level' => $_GET['level'] ?? '', + 'level' => $_GET['level'] ?? '', 'context' => $_GET['context'] ?? '', ]; foreach ($filters as $k => $v) { @@ -68,9 +68,9 @@ class View extends BaseAdmin } } return Renderer::replaceMacros($t, [ - '$title' => DI::l10n()->t('Administration'), - '$page' => DI::l10n()->t('View Logs'), - '$l10n' => [ + '$title' => DI::l10n()->t('Administration'), + '$page' => DI::l10n()->t('View Logs'), + '$l10n' => [ 'Search' => DI::l10n()->t('Search'), 'Search_in_logs' => DI::l10n()->t('Search in logs'), 'Show_all' => DI::l10n()->t('Show all'), @@ -96,7 +96,7 @@ class View extends BaseAdmin '$filters' => $filters, '$filtersvalues' => $filters_valid_values, '$error' => $error, - '$logname' => DI::config()->get('system', 'logfile'), + '$logname' => DI::l10n()->t('Current log path: %s', DI::config()->get('system', 'logfile')), ]); } } diff --git a/src/Module/BaseAdmin.php b/src/Module/BaseAdmin.php index ea03efd2a9..9c0c7723ac 100644 --- a/src/Module/BaseAdmin.php +++ b/src/Module/BaseAdmin.php @@ -85,8 +85,8 @@ abstract class BaseAdmin extends BaseModule '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('Settings') , 'logs'], + 'logsview' => ['admin/logs/view' , DI::l10n()->t('View') , 'viewlogs'], ]], 'diagnostics' => [DI::l10n()->t('Diagnostics'), [ 'phpinfo' => ['admin/phpinfo?t=' . self::getFormSecurityToken('phpinfo'), DI::l10n()->t('PHP Info') , 'phpinfo'], diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index 2de4e96bfa..d88432ceac 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 2026.04-dev\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-02-12 23:20+0100\n" +"POT-Creation-Date: 2026-02-13 20:21+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -44,7 +44,7 @@ msgstr "" msgid "Item not found." msgstr "" -#: mod/item.php:463 mod/message.php:56 mod/message.php:102 mod/notes.php:34 +#: mod/item.php:463 mod/message.php:56 mod/message.php:102 mod/notes.php:35 #: mod/photos.php:132 mod/photos.php:624 src/Model/Event.php:511 #: src/Module/Attach.php:40 src/Module/BaseApi.php:90 #: src/Module/BaseNotifications.php:83 src/Module/BaseSettings.php:38 @@ -344,15 +344,15 @@ msgid_plural "%d messages" msgstr[0] "" msgstr[1] "" -#: mod/notes.php:41 src/Content/Nav.php:231 src/Module/BaseProfile.php:93 +#: mod/notes.php:42 src/Content/Nav.php:231 src/Module/BaseProfile.php:93 msgid "Personal notes" msgstr "" -#: mod/notes.php:45 +#: mod/notes.php:46 msgid "Personal notes are visible only by yourself." msgstr "" -#: mod/notes.php:46 src/Module/Admin/Storage.php:128 +#: mod/notes.php:47 src/Module/Admin/Storage.php:128 #: src/Module/Filer/SaveTag.php:60 src/Module/Post/Edit.php:127 #: src/Module/Settings/Channels.php:228 msgid "Save" @@ -446,7 +446,7 @@ msgid "Do not show a status post for this upload" msgstr "" #: mod/photos.php:691 mod/photos.php:1051 src/Content/Conversation.php:404 -#: src/Module/Calendar/Event/Form.php:239 src/Module/Post/Edit.php:181 +#: src/Module/Calendar/Event/Form.php:241 src/Module/Post/Edit.php:181 msgid "Permissions" msgstr "" @@ -584,7 +584,7 @@ msgid "Comment" msgstr "" #: mod/photos.php:1098 mod/photos.php:1154 mod/photos.php:1234 -#: src/Content/Conversation.php:416 src/Module/Calendar/Event/Form.php:234 +#: src/Content/Conversation.php:416 src/Module/Calendar/Event/Form.php:236 #: src/Module/Item/Compose.php:200 src/Module/Post/Edit.php:163 #: src/Object/Post.php:1180 msgid "Preview" @@ -2191,8 +2191,9 @@ msgid "Manage other accounts, including groups and pages" msgstr "" #: src/Content/Nav.php:324 src/Module/Admin/Addons/Details.php:140 -#: src/Module/Admin/Themes/Details.php:85 src/Module/BaseSettings.php:177 -#: src/Module/Welcome.php:39 view/theme/frio/theme.php:230 +#: src/Module/Admin/Themes/Details.php:85 src/Module/BaseAdmin.php:88 +#: src/Module/BaseSettings.php:177 src/Module/Welcome.php:39 +#: view/theme/frio/theme.php:230 msgid "Settings" msgstr "" @@ -4129,9 +4130,8 @@ msgstr "" msgid "PHP log currently disabled." msgstr "" -#: src/Module/Admin/Logs/Settings.php:75 src/Module/BaseAdmin.php:87 -#: src/Module/BaseAdmin.php:88 -msgid "Logs" +#: src/Module/Admin/Logs/Settings.php:75 +msgid "Log settings" msgstr "" #: src/Module/Admin/Logs/Settings.php:77 @@ -4178,7 +4178,7 @@ msgstr "" msgid "Couldn't open %1$s log file.
    Check to see if file %1$s is readable." msgstr "" -#: src/Module/Admin/Logs/View.php:72 src/Module/BaseAdmin.php:89 +#: src/Module/Admin/Logs/View.php:72 msgid "View Logs" msgstr "" @@ -4215,7 +4215,7 @@ msgstr "" msgid "Click to view details" msgstr "" -#: src/Module/Admin/Logs/View.php:84 src/Module/Calendar/Event/Form.php:193 +#: src/Module/Admin/Logs/View.php:84 src/Module/Calendar/Event/Form.php:195 msgid "Event details" msgstr "" @@ -4248,6 +4248,11 @@ msgstr "" msgid "Process ID" msgstr "" +#: src/Module/Admin/Logs/View.php:99 +#, php-format +msgid "Current log path: %s" +msgstr "" + #: src/Module/Admin/Queue.php:36 msgid "Inspect Deferred Worker Queue" msgstr "" @@ -4408,7 +4413,7 @@ msgstr "" msgid "Policies" msgstr "" -#: src/Module/Admin/Site.php:465 src/Module/Calendar/Event/Form.php:238 +#: src/Module/Admin/Site.php:465 src/Module/Calendar/Event/Form.php:240 #: src/Module/Contact.php:532 src/Module/Profile/Profile.php:290 msgid "Advanced" msgstr "" @@ -5667,6 +5672,14 @@ msgstr "" msgid "Inspect worker Queue" msgstr "" +#: src/Module/BaseAdmin.php:87 +msgid "Logs" +msgstr "" + +#: src/Module/BaseAdmin.php:89 src/Module/Calendar/Show.php:114 +msgid "View" +msgstr "" + #: src/Module/BaseAdmin.php:91 src/Module/BaseModeration.php:109 msgid "Diagnostics" msgstr "" @@ -5894,17 +5907,17 @@ msgstr "" msgid "Event title and start time are required." msgstr "" -#: src/Module/Calendar/Event/Form.php:194 +#: src/Module/Calendar/Event/Form.php:196 msgid "Starting date and Title are required." msgstr "" -#: src/Module/Calendar/Event/Form.php:195 -#: src/Module/Calendar/Event/Form.php:200 +#: src/Module/Calendar/Event/Form.php:197 +#: src/Module/Calendar/Event/Form.php:202 msgid "Event Starts:" msgstr "" -#: src/Module/Calendar/Event/Form.php:195 -#: src/Module/Calendar/Event/Form.php:223 src/Module/Debug/Probe.php:45 +#: src/Module/Calendar/Event/Form.php:197 +#: src/Module/Calendar/Event/Form.php:225 src/Module/Debug/Probe.php:45 #: src/Module/Install.php:186 src/Module/Install.php:212 #: src/Module/Install.php:217 src/Module/Install.php:231 #: src/Module/Install.php:240 src/Module/Install.php:245 @@ -5927,35 +5940,35 @@ msgstr "" msgid "Required" msgstr "" -#: src/Module/Calendar/Event/Form.php:209 -#: src/Module/Calendar/Event/Form.php:233 +#: src/Module/Calendar/Event/Form.php:211 +#: src/Module/Calendar/Event/Form.php:235 msgid "End date/time is unknown or irrelevant" msgstr "" -#: src/Module/Calendar/Event/Form.php:211 -#: src/Module/Calendar/Event/Form.php:216 +#: src/Module/Calendar/Event/Form.php:213 +#: src/Module/Calendar/Event/Form.php:218 msgid "Event ends:" msgstr "" -#: src/Module/Calendar/Event/Form.php:223 -#: src/Module/Calendar/Event/Form.php:229 +#: src/Module/Calendar/Event/Form.php:225 +#: src/Module/Calendar/Event/Form.php:231 msgid "Title (BBCode not allowed)" msgstr "" -#: src/Module/Calendar/Event/Form.php:225 +#: src/Module/Calendar/Event/Form.php:227 msgid "Description (BBCode allowed)" msgstr "" -#: src/Module/Calendar/Event/Form.php:227 +#: src/Module/Calendar/Event/Form.php:229 msgid "Location (BBCode not allowed)" msgstr "" -#: src/Module/Calendar/Event/Form.php:230 -#: src/Module/Calendar/Event/Form.php:231 +#: src/Module/Calendar/Event/Form.php:232 +#: src/Module/Calendar/Event/Form.php:233 msgid "Share this event" msgstr "" -#: src/Module/Calendar/Event/Form.php:236 src/Module/Contact/Advanced.php:118 +#: src/Module/Calendar/Event/Form.php:238 src/Module/Contact/Advanced.php:118 #: src/Module/Contact/Profile.php:415 #: src/Module/Debug/ActivityPubConversion.php:128 #: src/Module/Debug/Babel.php:280 src/Module/Debug/Localtime.php:50 @@ -5974,7 +5987,7 @@ msgstr "" msgid "Submit" msgstr "" -#: src/Module/Calendar/Event/Form.php:237 src/Module/Profile/Profile.php:289 +#: src/Module/Calendar/Event/Form.php:239 src/Module/Profile/Profile.php:289 msgid "Basic" msgstr "" @@ -5990,10 +6003,6 @@ msgstr "" msgid "calendar" msgstr "" -#: src/Module/Calendar/Show.php:114 -msgid "View" -msgstr "" - #: src/Module/Calendar/Show.php:115 msgid "New Event" msgstr "" diff --git a/view/templates/admin/logs/settings.tpl b/view/templates/admin/logs/settings.tpl index 4da2c7cd70..85c4bdeef5 100644 --- a/view/templates/admin/logs/settings.tpl +++ b/view/templates/admin/logs/settings.tpl @@ -6,16 +6,16 @@ *}}

    {{$title}} - {{$page}}

    - +
    {{include file="field_checkbox.tpl" field=$debugging}} {{include file="field_input.tpl" field=$logfile}} {{include file="field_select.tpl" field=$loglevel}} - -
    - + +
    +

    {{$phpheader}}

    @@ -24,5 +24,5 @@

    {{$phphint}}

    {{$phplogcode}}
    - +
    diff --git a/view/templates/admin/logs/view.tpl b/view/templates/admin/logs/view.tpl index a94f1284be..65fc11a5ac 100644 --- a/view/templates/admin/logs/view.tpl +++ b/view/templates/admin/logs/view.tpl @@ -7,7 +7,7 @@

    {{$title}} - {{$page}}

    -

    {{$logname}}

    +

    {{$logname}}

    {{if $error }}

    {{$error nofilter}}

    diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index 8b8a3d82ec..8abd5d3d61 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -933,7 +933,7 @@ nav.navbar .nav > li > button:focus { font-size: 1.6em; } -#nav-search-input-field { +#search-box #nav-search-input-field { width: 296px; } @@ -3595,6 +3595,10 @@ li.addon { #adminpage h2 { word-break: break-all; } +#adminpage .form-group-search { + display: flex; + align-items: center; +} #adminpage .table-logs thead tr { display: grid; grid-auto-flow: row; @@ -3613,6 +3617,10 @@ li.addon { #logdetail td.log-message { width: 80%; } +#adminpage #nav-search-input-field { + display: inline; + max-width: 296px; +} @media (min-width: 600px) { #adminpage .table-logs thead tr { grid-auto-flow: column; diff --git a/view/theme/frio/templates/admin/logs/view.tpl b/view/theme/frio/templates/admin/logs/view.tpl index 2ef960d7af..56638cab4c 100644 --- a/view/theme/frio/templates/admin/logs/view.tpl +++ b/view/theme/frio/templates/admin/logs/view.tpl @@ -7,25 +7,23 @@

    {{$title}} - {{$page}}

    -

    {{$logname}}

    +

    {{$logname}}

    {{if $error }}

    {{$error nofilter}}

    {{else}}
    -
    - diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index 8f13cf87c3..0d51beb121 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -2808,6 +2808,11 @@ ul li:hover .contact-wrapper .contact-action-link:hover { padding-top: 10px; } +#num-results { + padding-top: 20px; + margin-bottom: 0; +} + /* circle edit page */ .circle-actions { margin-top: 4px; diff --git a/view/theme/frio/templates/directory_header.tpl b/view/theme/frio/templates/directory_header.tpl index c84c754f4c..71d1ad5552 100644 --- a/view/theme/frio/templates/directory_header.tpl +++ b/view/theme/frio/templates/directory_header.tpl @@ -23,6 +23,7 @@
    From e8c8fa43153c596c15db4169e616718bc074771f Mon Sep 17 00:00:00 2001 From: "Marcus F." Date: Sat, 28 Feb 2026 20:39:17 +0100 Subject: [PATCH 154/197] Update the date format for member since/joined --- src/Core/L10n.php | 12 ++++++++++++ src/Model/Profile.php | 2 +- src/Module/Profile/Profile.php | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Core/L10n.php b/src/Core/L10n.php index 3a05d332de..312ed1d5f7 100644 --- a/src/Core/L10n.php +++ b/src/Core/L10n.php @@ -608,6 +608,18 @@ class L10n return $this->formatDateTime($datestring, IntlDateFormatter::FULL, IntlDateFormatter::NONE); } + /** + * Format a date string (date only) using MEDIUM date format according to current locale. + * + * @param string $datestring Date string + * @return string Formatted date string + * @throws \Exception If the date string cannot be parsed into a DateTime + */ + public function mediumDate(string $datestring): string + { + return $this->formatDateTime($datestring, IntlDateFormatter::MEDIUM, IntlDateFormatter::NONE); + } + /** * Format a date string (date only) using LONG date format according to current locale. * diff --git a/src/Model/Profile.php b/src/Model/Profile.php index ffab10134b..f1071ee4a8 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -447,7 +447,7 @@ class Profile $member_since = null; if (Feature::isEnabled($p['uid'], Feature::MEMBER_SINCE)) { - $member_since = [ DI::l10n()->t('Joined:'), DateTimeFormat::local($p['register_date']) ]; + $member_since = [ DI::l10n()->t('Joined:'), DI::l10n()->mediumDate($p['register_date']) ]; } $tpl = Renderer::getMarkupTemplate('profile/vcard.tpl'); diff --git a/src/Module/Profile/Profile.php b/src/Module/Profile/Profile.php index cb2deaa18a..a8798deeec 100644 --- a/src/Module/Profile/Profile.php +++ b/src/Module/Profile/Profile.php @@ -183,7 +183,7 @@ class Profile extends BaseProfile $basic_fields += self::buildField( 'membersince', $this->t('Joined:'), - $this->l10n->fullDate($profile['register_date']), + $this->l10n->mediumDate($profile['register_date']), ); } From 3a5c3522e2628ef447935d1e4184bf2d9a048f5b Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 10 Mar 2024 18:54:26 +0000 Subject: [PATCH 155/197] The "summary" has now a dedicated field when creating and editing posts --- mod/item.php | 23 ++++++++------ src/Content/Conversation.php | 3 ++ src/Content/Feature.php | 46 ++++++++++++++------------- src/Module/Item/Compose.php | 37 ++++++++++++--------- src/Module/Post/Edit.php | 6 ++-- view/lang/C/messages.po | 26 +++++++++++---- view/templates/item/compose.tpl | 6 ++++ view/templates/jot.tpl | 4 +++ view/theme/frio/css/style.css | 1 + view/theme/frio/templates/jot.tpl | 4 +++ view/theme/quattro/templates/jot.tpl | 4 +++ view/theme/smoothly/style.css | 1 + view/theme/smoothly/templates/jot.tpl | 6 ++++ 13 files changed, 112 insertions(+), 55 deletions(-) diff --git a/mod/item.php b/mod/item.php index 98c9f69372..07179ebc67 100644 --- a/mod/item.php +++ b/mod/item.php @@ -1,4 +1,5 @@ dispatch( - new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL_START, $_REQUEST) + new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL_START, $_REQUEST), )->getArray(); $return_path = $_REQUEST['return'] ?? ''; @@ -101,14 +102,16 @@ function item_edit(int $uid, array $request, bool $preview, string $return_path) $post = item_process($post, $request, $preview, $return_path); $fields = [ - 'title' => $post['title'], - 'body' => $post['body'], - 'attach' => $post['attach'], - 'file' => $post['file'], - 'location' => $post['location'], - 'coord' => $post['coord'], - 'edited' => DateTimeFormat::utcNow(), - 'changed' => DateTimeFormat::utcNow() + 'title' => $post['title'], + 'content-warning' => $post['content-warning'], + 'sensitive' => $post['sensitive'], + 'body' => $post['body'], + 'attach' => $post['attach'], + 'file' => $post['file'], + 'location' => $post['location'], + 'coord' => $post['coord'], + 'edited' => DateTimeFormat::utcNow(), + 'changed' => DateTimeFormat::utcNow(), ]; $fields['body'] = Item::setHashtags($fields['body']); @@ -288,7 +291,7 @@ function item_process(array $post, array $request, bool $preview, string $return ]; $hook_data = $eventDispatcher->dispatch( - new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL, $hook_data) + new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL, $hook_data), )->getArray(); $post = $hook_data['item'] ?? $post; diff --git a/src/Content/Conversation.php b/src/Content/Conversation.php index ef29573c16..a72c572e91 100644 --- a/src/Content/Conversation.php +++ b/src/Content/Conversation.php @@ -389,8 +389,11 @@ class Conversation '$shortnoloc' => $this->l10n->t('clear location'), '$title' => $x['title'] ?? '', '$placeholdertitle' => $this->l10n->t('Set title'), + '$summary' => $x['summary'] ?? '', + '$placeholdersummary' => Feature::isEnabled($this->session->getLocalUserId(), Feature::SUMMARY) ? $this->l10n->t('Set summary, abstract or spoiler text') : '', '$category' => $x['category'] ?? '', '$placeholdercategory' => Feature::isEnabled($this->session->getLocalUserId(), Feature::CATEGORIES) ? $this->l10n->t("Categories \x28comma-separated list\x29") : '', + '$sensitive' => ['sensitive', $this->l10n->t('Sensitive post'), $x['sensitive'] ?? false], '$scheduled_at' => Temporal::getDateTimeField( new \DateTime(), new \DateTime('now + 6 months'), diff --git a/src/Content/Feature.php b/src/Content/Feature.php index 27a39978a7..1e9211b567 100644 --- a/src/Content/Feature.php +++ b/src/Content/Feature.php @@ -12,25 +12,26 @@ use Friendica\Event\ArrayFilterEvent; class Feature { - const ADD_ABSTRACT = 'add_abstract'; - const CATEGORIES = 'categories'; - const COMMUNITY = 'community'; - const EXPLICIT_MENTIONS = 'explicit_mentions'; - const MEMBER_SINCE = 'profile_membersince'; - const PHOTO_LOCATION = 'photo_location'; - const PUBLIC_CALENDAR = 'public_calendar'; - const TAGCLOUD = 'tagadelic'; + public const ADD_ABSTRACT = 'add_abstract'; + public const CATEGORIES = 'categories'; + public const COMMUNITY = 'community'; + public const EXPLICIT_MENTIONS = 'explicit_mentions'; + public const MEMBER_SINCE = 'profile_membersince'; + public const PHOTO_LOCATION = 'photo_location'; + public const PUBLIC_CALENDAR = 'public_calendar'; + public const SUMMARY = 'summary'; + public const TAGCLOUD = 'tagadelic'; // The different widgets: - const ACCOUNTS = 'accounts'; - const ARCHIVE = 'archive'; - const CIRCLES = 'circles'; - const CHANNELS = 'channels'; - const FOLDERS = 'folders'; - const GROUPS = 'forumlist_profile'; - const NETWORKS = 'networks'; - const NOSHARER = 'nosharer'; - const SEARCHES = 'searches'; - const TRENDING_TAGS = 'trending_tags'; + public const ACCOUNTS = 'accounts'; + public const ARCHIVE = 'archive'; + public const CIRCLES = 'circles'; + public const CHANNELS = 'channels'; + public const FOLDERS = 'folders'; + public const GROUPS = 'forumlist_profile'; + public const NETWORKS = 'networks'; + public const NOSHARER = 'nosharer'; + public const SEARCHES = 'searches'; + public const TRENDING_TAGS = 'trending_tags'; /** * check if feature is enabled @@ -56,10 +57,10 @@ class Feature $arr = ['uid' => $uid, 'feature' => $feature, 'enabled' => $enabled]; $arr = $eventDispatcher->dispatch( - new ArrayFilterEvent(ArrayFilterEvent::FEATURE_ENABLED, $arr) + new ArrayFilterEvent(ArrayFilterEvent::FEATURE_ENABLED, $arr), )->getArray(); - return (bool)$arr['enabled']; + return (bool) $arr['enabled']; } /** @@ -119,6 +120,7 @@ class Feature 'tools' => [ $l10n->t('Post/Comment Tools'), [self::CATEGORIES, $l10n->t('Post Categories'), $l10n->t('Add categories to your posts'), false, $config->get('feature_lock', self::CATEGORIES, false)], + [self::SUMMARY, $l10n->t('Summary'), $l10n->t('Add a summary, abstract or spoiler text to your posts'), false, $config->get('feature_lock', self::SUMMARY, false)], ], // Widget visibility on the network stream @@ -147,7 +149,7 @@ class Feature 'advanced_calendar' => [ $l10n->t('Advanced Calendar Settings'), [self::PUBLIC_CALENDAR, $l10n->t('Allow anonymous access to your calendar'), $l10n->t('Allows anonymous visitors to consult your calendar and your public events. Contact birthday events are private to you.'), false, $config->get('feature_lock', self::PUBLIC_CALENDAR, false)], - ] + ], ]; // removed any locked features and remove the entire category if this makes it empty @@ -172,7 +174,7 @@ class Feature } $arr = $eventDispatcher->dispatch( - new ArrayFilterEvent(ArrayFilterEvent::FEATURE_GET, $arr) + new ArrayFilterEvent(ArrayFilterEvent::FEATURE_GET, $arr), )->getArray(); return $arr; diff --git a/src/Module/Item/Compose.php b/src/Module/Item/Compose.php index caf8cd9f74..07c2ce6023 100644 --- a/src/Module/Item/Compose.php +++ b/src/Module/Item/Compose.php @@ -78,7 +78,7 @@ class Compose extends BaseModule protected function post(array $request = []) { - if (!empty($_REQUEST['body'])) { + if (!empty($request['body'])) { $_REQUEST['return'] = 'network'; require_once 'mod/item.php'; item_post(); @@ -131,10 +131,10 @@ class Compose extends BaseModule $type = 'post'; $doesFederate = true; - $contact_allow = $_REQUEST['contact_allow'] ?? ''; - $circle_allow = $_REQUEST['circle_allow'] ?? ''; - $contact_deny = $_REQUEST['contact_deny'] ?? ''; - $circle_deny = $_REQUEST['circle_deny'] ?? ''; + $contact_allow = $request['contact_allow'] ?? ''; + $circle_allow = $request['circle_allow'] ?? ''; + $contact_deny = $request['contact_deny'] ?? ''; + $circle_deny = $request['circle_deny'] ?? ''; if ($contact_allow . $circle_allow @@ -149,11 +149,13 @@ class Compose extends BaseModule break; } - $title = $_REQUEST['title'] ?? ''; - $category = $_REQUEST['category'] ?? ''; - $body = $_REQUEST['body'] ?? ''; - $location = $_REQUEST['location'] ?? $user['default-location']; - $wall = $_REQUEST['wall'] ?? $type == 'post'; + $title = $request['title'] ?? ''; + $summary = $request['summary'] ?? ''; + $sensitive = $request['sensitive'] ?? false; + $category = $request['category'] ?? ''; + $body = $request['body'] ?? ''; + $location = $request['location'] ?? $user['default-location']; + $wall = $request['wall'] ?? $type == 'post'; $jotplugins = $this->eventDispatcher->dispatch( new HtmlFilterEvent(HtmlFilterEvent::JOT_TOOL, ''), @@ -172,7 +174,7 @@ class Compose extends BaseModule new DateTime('now'), null, $this->l10n->t('Created at'), - 'created_at' + 'created_at', ); } else { $created_at = ''; @@ -183,6 +185,7 @@ class Compose extends BaseModule '$l10n' => [ 'compose_title' => $compose_title, 'default' => '', + 'summary' => $this->l10n->t('Summary'), 'visibility_title' => $this->l10n->t('Visibility'), 'mytitle' => $this->l10n->t('This is you'), 'submit' => $this->l10n->t('Submit'), @@ -204,14 +207,15 @@ class Compose extends BaseModule 'location_disabled' => $this->l10n->t('Location services are disabled. Please check the website\'s permissions on your device'), 'wait' => $this->l10n->t('Please wait'), 'placeholdertitle' => $this->l10n->t('Set title'), + 'placeholdersummary' => Feature::isEnabled($this->session->getLocalUserId(), Feature::SUMMARY) ? $this->l10n->t('Set summary, abstract or spoiler text') : '', 'placeholdercategory' => Feature::isEnabled($this->session->getLocalUserId(), Feature::CATEGORIES) ? $this->l10n->t('Categories (comma-separated list)') : '', 'always_open_compose' => $this->pConfig->get( $this->session->getLocalUserId(), 'frio', 'always_open_compose', - $this->config->get('frio', 'always_open_compose', false) - ) ? '' : - $this->l10n->t('If you want to always use this editor for posting, you can configure the New Post button to always open it in your Theme settings.'), + $this->config->get('frio', 'always_open_compose', false), + ) ? '' + : $this->l10n->t('If you want to always use this editor for posting, you can configure the New Post button to always open it in your Theme settings.'), ], '$id' => 0, @@ -220,15 +224,18 @@ class Compose extends BaseModule '$wall' => $wall, '$mylink' => $this->baseUrl->remove($contact['url']), '$myphoto' => $this->baseUrl->remove($contact['thumb']), + '$sensitive' => ['sensitive', $this->l10n->t('Sensitive post'), $request['sensitive'] ?? false], '$scheduled_at' => Temporal::getDateTimeField( new DateTime(), new DateTime('now + 6 months'), null, $this->l10n->t('Scheduled at'), - 'scheduled_at' + 'scheduled_at', ), '$created_at' => $created_at, '$title' => $title, + '$summary' => $summary, + 'sensitive' => $sensitive, '$category' => $category, '$body' => $body, '$location' => $location, diff --git a/src/Module/Post/Edit.php b/src/Module/Post/Edit.php index daac9aaf8d..96c654e737 100644 --- a/src/Module/Post/Edit.php +++ b/src/Module/Post/Edit.php @@ -79,8 +79,8 @@ class Edit extends BaseModule } $fields = [ - 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', 'gravity', - 'body', 'title', 'uri-id', 'wall', 'post-type', 'guid' + 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', 'gravity', 'sensitive', + 'body', 'title', 'content-warning', 'uri-id', 'wall', 'post-type', 'guid', ]; $item = Post::selectFirstForUser($this->session->getLocalUserId(), $fields, [ @@ -153,6 +153,8 @@ class Edit extends BaseModule '$public' => $this->t('Public post'), '$title' => $item['title'], '$placeholdertitle' => $this->t('Set title'), + '$summary' => $item['content-warning'], + '$placeholdersummary' => (Feature::isEnabled($this->session->getLocalUserId(), Feature::SUMMARY) ? $this->t('Set summary, abstract or spoiler text') : ''), '$category' => Post\Category::getCSVByURIId($item['uri-id'], $this->session->getLocalUserId(), Post\Category::CATEGORY), '$placeholdercategory' => (Feature::isEnabled($this->session->getLocalUserId(), Feature::CATEGORIES) ? $this->t("Categories \x28comma-separated list\x29") : ''), '$emtitle' => $this->t('Example: bob@example.com, mary@example.com'), diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index 9fa347861c..d7c4399dc1 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -1279,9 +1279,18 @@ msgstr "" #: src/Content/Conversation.php:393 src/Module/Item/Compose.php:207 #: src/Module/Post/Edit.php:157 +msgid "Set summary, abstract or spoiler text" +msgstr "" + +#: src/Content/Conversation.php:395 src/Module/Item/Compose.php:211 +#: src/Module/Post/Edit.php:159 msgid "Categories (comma-separated list)" msgstr "" +#: src/Content/Conversation.php:396 src/Module/Item/Compose.php:227 +msgid "Sensitive post" +msgstr "" + #: src/Content/Conversation.php:398 src/Module/Item/Compose.php:227 msgid "Scheduled at" msgstr "" @@ -1639,6 +1648,17 @@ msgstr "" msgid "Add categories to your posts" msgstr "" +#: src/Content/Feature.php:123 src/Model/Profile.php:807 +#: src/Module/Admin/Summary.php:207 src/Module/Item/Compose.php:188 +#: src/Module/Moderation/Report/Create.php:282 +#: src/Module/Moderation/Summary.php:65 +msgid "Summary" +msgstr "" + +#: src/Content/Feature.php:123 +msgid "Add a summary, abstract or spoiler text to your posts" +msgstr "" + #: src/Content/Feature.php:126 msgid "Network Widgets" msgstr "" @@ -3504,12 +3524,6 @@ msgstr "" msgid "Title/Description:" msgstr "" -#: src/Model/Profile.php:807 src/Module/Admin/Summary.php:207 -#: src/Module/Moderation/Report/Create.php:282 -#: src/Module/Moderation/Summary.php:65 -msgid "Summary" -msgstr "" - #: src/Model/Profile.php:808 msgid "Musical interests" msgstr "" diff --git a/view/templates/item/compose.tpl b/view/templates/item/compose.tpl index 777f260c45..6364c471e7 100644 --- a/view/templates/item/compose.tpl +++ b/view/templates/item/compose.tpl @@ -18,6 +18,11 @@
    + {{if $l10n.placeholdersummary}} +
    + +
    + {{/if}} {{if $l10n.placeholdercategory}}
    @@ -112,6 +117,7 @@ {{$jotplugins nofilter}}
    + {{include file="field_checkbox.tpl" field=$sensitive}} {{if $scheduled_at}}{{$scheduled_at nofilter}}{{/if}} {{if $created_at}}{{$created_at nofilter}}{{/if}} {{else}} diff --git a/view/templates/jot.tpl b/view/templates/jot.tpl index 274c937018..80468d83a8 100644 --- a/view/templates/jot.tpl +++ b/view/templates/jot.tpl @@ -24,6 +24,9 @@ {{/if}}
    + {{if $placeholdersummary}} +
    + {{/if}} {{if $placeholdercategory}}
    {{/if}} @@ -87,6 +90,7 @@
    {{$acl nofilter}} + {{include file="field_checkbox.tpl" field=$sensitive}} {{if $scheduled_at}}{{$scheduled_at nofilter}}{{/if}} {{if $created_at}}{{$created_at nofilter}}{{/if}}
    diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index 0d51beb121..64fd0fe99c 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -1534,6 +1534,7 @@ section #jotOpen { margin-right: 20px; } #jot-title-wrap, +#jot-summary-wrap, #jot-category-wrap { margin-bottom: 10px; } diff --git a/view/theme/frio/templates/jot.tpl b/view/theme/frio/templates/jot.tpl index 10f20019c1..a28aabb100 100644 --- a/view/theme/frio/templates/jot.tpl +++ b/view/theme/frio/templates/jot.tpl @@ -105,6 +105,9 @@ {{/if}}
    + {{if $placeholdersummary}} +
    + {{/if}} {{if $placeholdercategory}}
    {{/if}} @@ -147,6 +150,7 @@ diff --git a/view/theme/quattro/templates/jot.tpl b/view/theme/quattro/templates/jot.tpl index 45d4050489..6f6cd697a4 100644 --- a/view/theme/quattro/templates/jot.tpl +++ b/view/theme/quattro/templates/jot.tpl @@ -8,6 +8,9 @@
     
    + {{if $placeholdersummary}} + + {{/if}} {{if $placeholdercategory}} {{/if}} @@ -53,6 +56,7 @@
    {{$acl nofilter}} + {{include file="field_checkbox.tpl" field=$sensitive}} {{if $scheduled_at}}{{$scheduled_at nofilter}}{{/if}} {{if $created_at}}{{$created_at nofilter}}{{/if}}
    diff --git a/view/theme/smoothly/style.css b/view/theme/smoothly/style.css index 4d0264da0a..be480cde08 100644 --- a/view/theme/smoothly/style.css +++ b/view/theme/smoothly/style.css @@ -1420,6 +1420,7 @@ ul .sidebar-circle-li .icon { #jot-coord, #jot-preview, #jot-title-wrap, +#jot-summary-wrap, #jot-category-wrap, #jot-text-wrap, #profile-jot-text-loading, diff --git a/view/theme/smoothly/templates/jot.tpl b/view/theme/smoothly/templates/jot.tpl index 683614db6f..2977781ffc 100644 --- a/view/theme/smoothly/templates/jot.tpl +++ b/view/theme/smoothly/templates/jot.tpl @@ -24,6 +24,11 @@
    + {{if $placeholdersummary}} +
    + +
    + {{/if}} {{if $placeholdercategory}}
    @@ -76,6 +81,7 @@
    {{$acl nofilter}} + {{include file="field_checkbox.tpl" field=$sensitive}} {{if $scheduled_at}}{{$scheduled_at nofilter}}{{/if}} {{if $created_at}}{{$created_at nofilter}}{{/if}}
    From d8efe9f8919fc75e5e54826d72a5e3f53a1fde4e Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 1 Mar 2026 16:53:52 +0000 Subject: [PATCH 156/197] Infinite scrolling is fixed in general and on contacts --- src/Content/Text/HTML.php | 11 ++++- src/Model/Contact.php | 66 +++++++++++---------------- src/Module/Contact/Conversations.php | 24 ++++++---- src/Module/Contact/Follow.php | 2 +- src/Module/Contact/Media.php | 2 +- src/Module/Contact/Posts.php | 2 +- src/Module/Contact/Unfollow.php | 2 +- src/Module/Conversation/Channel.php | 9 +--- src/Module/Conversation/Community.php | 9 +--- src/Module/Conversation/Network.php | 9 +--- src/Module/Profile/Media.php | 2 +- src/Module/Search/Filed.php | 11 +---- src/Module/Search/Index.php | 7 +-- src/Module/Update/Contact.php | 2 +- 14 files changed, 66 insertions(+), 92 deletions(-) diff --git a/src/Content/Text/HTML.php b/src/Content/Text/HTML.php index 3d789e7fa0..a30c9d7e99 100644 --- a/src/Content/Text/HTML.php +++ b/src/Content/Text/HTML.php @@ -772,10 +772,17 @@ class HTML * @return string html for loader * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public static function scrollLoader(): string + public static function scrollLoader(array $request = []): string { + if (in_array($request['mode'] ?? '', ['minimal', 'raw'])) { + return ''; + } + + $tpl = Renderer::getMarkupTemplate('infinite_scroll_head.tpl'); + $loader = Renderer::replaceMacros($tpl, ['$reload_uri' => DI::args()->getQueryString()]); + $tpl = Renderer::getMarkupTemplate("scroll_loader.tpl"); - return Renderer::replaceMacros($tpl, [ + return $loader . Renderer::replaceMacros($tpl, [ 'wait' => DI::l10n()->t('Loading more entries...'), 'end' => DI::l10n()->t('The end') ]); diff --git a/src/Model/Contact.php b/src/Model/Contact.php index 8226786303..6bab4573ea 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -1625,29 +1625,29 @@ class Contact /** * Returns posts from a given contact url * - * @param string $contact_url Contact URL - * @param int $uid User ID - * @param bool $only_media Only display media content - * @param string $last_created Newest creation date, used for paging + * @param string $contact_url Contact URL + * @param int $uid User ID + * @param bool $only_media Only display media content + * @param array $request Request variables * @return string posts in HTML * @throws Exception */ - public static function getPostsFromUrl(string $contact_url, int $uid, bool $only_media = false, ?string $last_created = null): string + public static function getPostsFromUrl(string $contact_url, int $uid, bool $only_media = false, array $request = []): string { - return self::getPostsFromId(self::getIdForURL($contact_url), $uid, $only_media, $last_created); + return self::getPostsFromId(self::getIdForURL($contact_url), $uid, $only_media, $request); } /** * Returns posts from a given contact id * - * @param int $cid Contact ID - * @param int $uid User ID - * @param bool $only_media Only display media content - * @param string $last_created Newest creation date, used for paging + * @param int $cid Contact ID + * @param int $uid User ID + * @param bool $only_media Only display media content + * @param array $request Request variables * @return string posts in HTML * @throws Exception */ - public static function getPostsFromId(int $cid, int $uid, bool $only_media = false, ?string $last_created = null): string + public static function getPostsFromId(int $cid, int $uid, bool $only_media = false, array $request = []): string { $contact = DBA::selectFirst('contact', ['contact-type', 'network', 'name', 'nick'], ['id' => $cid]); if (!DBA::isResult($contact)) { @@ -1668,8 +1668,8 @@ class Contact $condition = DBA::mergeConditions($condition, ["`$contact_field` = ? AND `gravity` IN (?, ?)", $cid, Item::GRAVITY_PARENT, Item::GRAVITY_COMMENT]); - if (!empty($last_created)) { - $condition = DBA::mergeConditions($condition, ["`created` < ?", $last_created]); + if (!empty($request['last_created'])) { + $condition = DBA::mergeConditions($condition, ["`created` < ?", $request['last_created']]); } if ($only_media) { @@ -1688,21 +1688,13 @@ class Contact $pager = new Pager(DI::l10n(), DI::args()->getQueryString(), $itemsPerPage); $params = ['order' => ['created' => true], 'limit' => [$pager->getStart(), $pager->getItemsPerPage()]]; - - if (DI::pConfig()->get($uid, 'system', 'infinite_scroll', true)) { - $tpl = Renderer::getMarkupTemplate('infinite_scroll_head.tpl'); - $o = Renderer::replaceMacros($tpl, ['$reload_uri' => DI::args()->getQueryString()]); - } else { - $o = ''; - } - $fields = array_merge(Item::DISPLAY_FIELDLIST, ['featured']); $items = Post::toArray(Post::selectForUser($uid, $fields, $condition, $params)); - $o .= DI::conversation()->render($items, ConversationContent::MODE_CONTACT_POSTS); + $o = DI::conversation()->render($items, ConversationContent::MODE_CONTACT_POSTS, isset($request['mode']) && ($request['mode'] == 'raw')); if (DI::pConfig()->get($uid, 'system', 'infinite_scroll', true)) { - $o .= HTML::scrollLoader(); + $o .= HTML::scrollLoader($request); } else { $o .= $pager->renderMinimal(count($items)); } @@ -1713,13 +1705,14 @@ class Contact /** * Returns threads from a given contact id * - * @param int $cid Contact ID - * @param int $update Update mode - * @param int $parent Item parent ID for the update mode + * @param int $cid Contact ID + * @param int $update Update mode + * @param int $parent Item parent ID for the update mode + * @param array $request Request variables * @return string posts in HTML * @throws Exception */ - public static function getThreadsFromId(int $cid, int $uid, int $update = 0, int $parent = 0, string $last_created = ''): string + public static function getThreadsFromId(int $cid, int $uid, int $update = 0, int $parent = 0, array $request = []): string { $contact = DBA::selectFirst('contact', ['contact-type', 'network', 'name', 'nick'], ['id' => $cid]); if (!DBA::isResult($contact)) { @@ -1738,8 +1731,8 @@ class Contact if (!empty($parent)) { $condition = DBA::mergeConditions($condition, ['parent' => $parent]); - } elseif (!empty($last_created)) { - $condition = DBA::mergeConditions($condition, ["`created` < ?", $last_created]); + } elseif (isset($request['last_created'])) { + $condition = DBA::mergeConditions($condition, ["`created` < ?", $request['last_created']]); } $contact_field = ((($contact["contact-type"] == self::TYPE_COMMUNITY) || ($contact['network'] == Protocol::MAIL)) ? 'owner-id' : 'author-id'); @@ -1752,13 +1745,6 @@ class Contact $pager = new Pager(DI::l10n(), DI::args()->getQueryString(), $itemsPerPage); - if (!$update && DI::pConfig()->get($uid, 'system', 'infinite_scroll', true)) { - $tpl = Renderer::getMarkupTemplate('infinite_scroll_head.tpl'); - $o = Renderer::replaceMacros($tpl, ['$reload_uri' => DI::args()->getQueryString()]); - } else { - $o = ''; - } - $condition1 = DBA::mergeConditions($condition, ["`$contact_field` = ? AND `gravity` = ?", $cid, Item::GRAVITY_PARENT]); $condition2 = DBA::mergeConditions($condition, [ @@ -1776,17 +1762,19 @@ class Contact $union = array_merge($union, [$pager->getStart(), $pager->getItemsPerPage()]); $items = Post::toArray(DBA::p($sql, $union)); - if (empty($last_created) && ($pager->getStart() == 0)) { + $raw = isset($request['mode']) && ($request['mode'] == 'raw'); + + if (!$raw && !$update && ($pager->getStart() == 0)) { $fields = ['uri-id', 'thr-parent-id', 'gravity', 'author-id', 'created']; $pinned = Post\Collection::selectToArrayForContact($cid, Post\Collection::FEATURED, $fields); $items = array_merge($items, $pinned); } - $o .= DI::conversation()->render($items, ConversationContent::MODE_CONTACTS, $update, false, 'pinned_created', $uid); + $o = DI::conversation()->render($items, ConversationContent::MODE_CONTACTS, $update || $raw, false, 'pinned_created', $uid); if (!$update) { if (DI::pConfig()->get($uid, 'system', 'infinite_scroll', true)) { - $o .= HTML::scrollLoader(); + $o .= HTML::scrollLoader($request); } else { $o .= $pager->renderMinimal(count($items)); } diff --git a/src/Module/Contact/Conversations.php b/src/Module/Contact/Conversations.php index 4d10935303..66ea8dc0a8 100644 --- a/src/Module/Contact/Conversations.php +++ b/src/Module/Contact/Conversations.php @@ -88,19 +88,23 @@ class Conversations extends BaseModule $this->baseUrl->redirect('profile/' . $contact['nick']); } - // Load necessary libraries for the status editor - $this->page->registerFooterScript(Theme::getPathForFile('asset/typeahead.js/dist/typeahead.bundle.js')); - $this->page->registerFooterScript(Theme::getPathForFile('js/friendica-tagsinput/friendica-tagsinput.js')); - $this->page->registerStylesheet(Theme::getPathForFile('js/friendica-tagsinput/friendica-tagsinput.css')); - $this->page->registerStylesheet(Theme::getPathForFile('js/friendica-tagsinput/friendica-tagsinput-typeahead.css')); + $raw = isset($request['mode']) && ($request['mode'] == 'raw'); - $this->page['aside'] .= VCard::getHTML($contact, true); + if (!$raw) { + // Load necessary libraries for the status editor + $this->page->registerFooterScript(Theme::getPathForFile('asset/typeahead.js/dist/typeahead.bundle.js')); + $this->page->registerFooterScript(Theme::getPathForFile('js/friendica-tagsinput/friendica-tagsinput.js')); + $this->page->registerStylesheet(Theme::getPathForFile('js/friendica-tagsinput/friendica-tagsinput.css')); + $this->page->registerStylesheet(Theme::getPathForFile('js/friendica-tagsinput/friendica-tagsinput-typeahead.css')); + + $this->page['aside'] .= VCard::getHTML($contact, true); + } Nav::setSelected('contacts'); $output = ''; - if (!$contact['ap-posting-restricted']) { + if (!$contact['ap-posting-restricted'] && !$raw) { $options = [ 'lockstate' => ACL::getLockstateForUserId($this->userSession->getLocalUserId()) ? 'lock' : 'unlock', 'acl' => ACL::getFullSelectorHTML($this->page, $this->userSession->getLocalUserId(), true, []), @@ -111,8 +115,10 @@ class Conversations extends BaseModule } Contact::setPageTitle($contact); - $output .= Contact::getTabsHTML($contact, Contact::TAB_CONVERSATIONS); - $output .= ModelContact::getThreadsFromId($contact['id'], $this->userSession->getLocalUserId(), 0, 0, $request['last_created'] ?? ''); + if (!$raw) { + $output .= Contact::getTabsHTML($contact, Contact::TAB_CONVERSATIONS); + } + $output .= ModelContact::getThreadsFromId($contact['id'], $this->userSession->getLocalUserId(), 0, 0, $request); return $output; } diff --git a/src/Module/Contact/Follow.php b/src/Module/Contact/Follow.php index 68c556aa52..ce8162b9e7 100644 --- a/src/Module/Contact/Follow.php +++ b/src/Module/Contact/Follow.php @@ -179,7 +179,7 @@ class Follow extends BaseModule ); // Show last public posts - $output .= Contact::getPostsFromUrl($contact['url'], $this->session->getLocalUserId()); + $output .= Contact::getPostsFromUrl($contact['url'], $this->session->getLocalUserId(), false, $request); } return $output; diff --git a/src/Module/Contact/Media.php b/src/Module/Contact/Media.php index 892e4162c0..a054186cdd 100644 --- a/src/Module/Contact/Media.php +++ b/src/Module/Contact/Media.php @@ -53,7 +53,7 @@ class Media extends BaseModule $o = Contact::getTabsHTML($contact, Contact::TAB_MEDIA); - $o .= ModelContact::getPostsFromUrl($contact['url'], $this->userSession->getLocalUserId(), true, $request['last_created'] ?? ''); + $o .= ModelContact::getPostsFromUrl($contact['url'], $this->userSession->getLocalUserId(), true, $request); return $o; } diff --git a/src/Module/Contact/Posts.php b/src/Module/Contact/Posts.php index 2445b3b930..1a506606c5 100644 --- a/src/Module/Contact/Posts.php +++ b/src/Module/Contact/Posts.php @@ -87,7 +87,7 @@ class Posts extends BaseModule $o = Contact::getTabsHTML($contact, Contact::TAB_POSTS); - $o .= Model\Contact::getPostsFromId($contact['id'], $this->userSession->getLocalUserId(), false, $request['last_created'] ?? ''); + $o .= Model\Contact::getPostsFromId($contact['id'], $this->userSession->getLocalUserId(), false, $request); return $o; } diff --git a/src/Module/Contact/Unfollow.php b/src/Module/Contact/Unfollow.php index 6e0283cb3f..94efacc2f9 100644 --- a/src/Module/Contact/Unfollow.php +++ b/src/Module/Contact/Unfollow.php @@ -124,7 +124,7 @@ class Unfollow extends \Friendica\BaseModule $o .= Renderer::replaceMacros(Renderer::getMarkupTemplate('section_title.tpl'), ['$title' => $this->t('Posts and Replies')]); // Show last public posts - $o .= Contact::getPostsFromUrl($contact['url'], $this->userSession->getLocalUserId()); + $o .= Contact::getPostsFromUrl($contact['url'], $this->userSession->getLocalUserId(), false, $request); return $o; } diff --git a/src/Module/Conversation/Channel.php b/src/Module/Conversation/Channel.php index b8d8ba4ff0..d18c22d4a8 100644 --- a/src/Module/Conversation/Channel.php +++ b/src/Module/Conversation/Channel.php @@ -84,11 +84,6 @@ class Channel extends Timeline '$header' => '', ]); - if ($this->pConfig->get($this->session->getLocalUserId(), 'system', 'infinite_scroll', true)) { - $tpl = Renderer::getMarkupTemplate('infinite_scroll_head.tpl'); - $o .= Renderer::replaceMacros($tpl, ['$reload_uri' => $this->args->getQueryString()]); - } - if (!$this->raw) { $tabs = $this->getTabArray($this->channel->getTimelines($this->session->getLocalUserId()), 'channel'); $tabs = array_merge($tabs, $this->getTabArray($this->channelRepository->selectByUid($this->session->getLocalUserId()), 'channel')); @@ -126,7 +121,7 @@ class Channel extends Timeline return $o; } - $o .= $this->conversation->render($items, Conversation::MODE_CHANNEL, false, false, $order, $this->session->getLocalUserId()); + $o .= $this->conversation->render($items, Conversation::MODE_CHANNEL, $this->raw, false, $order, $this->session->getLocalUserId()); $pager = new BoundariesPager( $this->l10n, @@ -137,7 +132,7 @@ class Channel extends Timeline ); if ($this->pConfig->get($this->session->getLocalUserId(), 'system', 'infinite_scroll', true)) { - $o .= HTML::scrollLoader(); + $o .= HTML::scrollLoader($request); } else { $o .= $pager->renderMinimal(count($items)); } diff --git a/src/Module/Conversation/Community.php b/src/Module/Conversation/Community.php index 8787268e9f..40e680d42f 100644 --- a/src/Module/Conversation/Community.php +++ b/src/Module/Conversation/Community.php @@ -80,11 +80,6 @@ class Community extends Timeline '$global_community_hint' => $this->l10n->t("This community stream shows all public posts received by this node. They may not reflect the opinions of this node’s users.") ]); - if ($this->pConfig->get($this->session->getLocalUserId(), 'system', 'infinite_scroll', true)) { - $tpl = Renderer::getMarkupTemplate('infinite_scroll_head.tpl'); - $o .= Renderer::replaceMacros($tpl, ['$reload_uri' => $this->args->getQueryString()]); - } - if (!$this->raw) { $tabs = $this->getTabArray($this->community->getTimelines($this->session->isAuthenticated()), 'community'); $tab_tpl = Renderer::getMarkupTemplate('common_tabs.tpl'); @@ -117,7 +112,7 @@ class Community extends Timeline return $o; } - $o .= $this->conversation->render($items, Conversation::MODE_COMMUNITY, false, false, 'received', $this->session->getLocalUserId()); + $o .= $this->conversation->render($items, Conversation::MODE_COMMUNITY, $this->raw, false, 'received', $this->session->getLocalUserId()); $pager = new BoundariesPager( $this->l10n, @@ -128,7 +123,7 @@ class Community extends Timeline ); if ($this->pConfig->get($this->session->getLocalUserId(), 'system', 'infinite_scroll', true)) { - $o .= HTML::scrollLoader(); + $o .= HTML::scrollLoader($request); } else { $o .= $pager->renderMinimal(count($items)); } diff --git a/src/Module/Conversation/Network.php b/src/Module/Conversation/Network.php index aa832bd8b3..f5f32237bd 100644 --- a/src/Module/Conversation/Network.php +++ b/src/Module/Conversation/Network.php @@ -224,11 +224,6 @@ class Network extends Timeline } } - if ($this->pConfig->get($this->session->getLocalUserId(), 'system', 'infinite_scroll', true) && ($_GET['mode'] ?? '') != 'minimal') { - $tpl = Renderer::getMarkupTemplate('infinite_scroll_head.tpl'); - $o .= Renderer::replaceMacros($tpl, ['$reload_uri' => $this->args->getQueryString()]); - } - if (!$this->raw) { $o .= $this->getTabsHTML(); @@ -294,7 +289,7 @@ class Network extends Timeline $items = $this->getItems(); } - $o .= $this->conversation->render($items, Conversation::MODE_NETWORK, false, false, $this->getOrder(), $this->session->getLocalUserId()); + $o .= $this->conversation->render($items, Conversation::MODE_NETWORK, $this->raw, false, $this->getOrder(), $this->session->getLocalUserId()); } catch (\Exception $e) { $this->logger->error('Exception when fetching items', ['code' => $e->getCode(), 'message' => $e->getMessage()]); $o .= $this->l10n->t('Error %d (%s) while fetching the timeline.', $e->getCode(), $e->getMessage()); @@ -302,7 +297,7 @@ class Network extends Timeline } if ($this->pConfig->get($this->session->getLocalUserId(), 'system', 'infinite_scroll', true)) { - $o .= HTML::scrollLoader(); + $o .= HTML::scrollLoader($request); } else { $pager = new BoundariesPager( $this->l10n, diff --git a/src/Module/Profile/Media.php b/src/Module/Profile/Media.php index 489d93eeaa..78c97c0bec 100644 --- a/src/Module/Profile/Media.php +++ b/src/Module/Profile/Media.php @@ -66,7 +66,7 @@ class Media extends BaseProfile $o = self::getTabsHTML('media', $is_owner, $profile['nickname'], $profile['hide-friends']); - $o .= Contact::getPostsFromUrl($profile['url'], $this->userSession->getLocalUserId(), true, $request['last_created'] ?? ''); + $o .= Contact::getPostsFromUrl($profile['url'], $this->userSession->getLocalUserId(), true, $request); return $o; } diff --git a/src/Module/Search/Filed.php b/src/Module/Search/Filed.php index b90dd7d923..17884ede64 100644 --- a/src/Module/Search/Filed.php +++ b/src/Module/Search/Filed.php @@ -31,13 +31,6 @@ class Filed extends BaseSearch DI::page()['aside'] .= Widget::fileAs(DI::args()->getCommand(), $_GET['file'] ?? ''); - if (DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'infinite_scroll', true) && ($_GET['mode'] ?? '') != 'minimal') { - $tpl = Renderer::getMarkupTemplate('infinite_scroll_head.tpl'); - $o = Renderer::replaceMacros($tpl, ['$reload_uri' => DI::args()->getQueryString()]); - } else { - $o = ''; - } - $file = $_GET['file'] ?? ''; // Rawmode is used for fetching new content at the end of the page @@ -93,10 +86,10 @@ class Filed extends BaseSearch $items = Post::toArray(Post::selectForUser(DI::userSession()->getLocalUserId(), Item::DISPLAY_FIELDLIST, $item_condition, $item_params)); - $o .= DI::conversation()->render($items, Conversation::MODE_FILED, false, false, '', DI::userSession()->getLocalUserId()); + $o = DI::conversation()->render($items, Conversation::MODE_FILED, false, false, '', DI::userSession()->getLocalUserId()); if (DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'infinite_scroll', true)) { - $o .= HTML::scrollLoader(); + $o .= HTML::scrollLoader($request); } else { $o .= $pager->renderMinimal($count); } diff --git a/src/Module/Search/Index.php b/src/Module/Search/Index.php index 7fcb6a6b94..49d0609277 100644 --- a/src/Module/Search/Index.php +++ b/src/Module/Search/Index.php @@ -195,11 +195,6 @@ class Index extends BaseSearch return $o; } - if (DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'infinite_scroll', true)) { - $tpl = Renderer::getMarkupTemplate('infinite_scroll_head.tpl'); - $o .= Renderer::replaceMacros($tpl, ['$reload_uri' => DI::args()->getQueryString()]); - } - if ($tag) { $title = DI::l10n()->t('Items tagged with: %s', $search); } else { @@ -215,7 +210,7 @@ class Index extends BaseSearch $o .= DI::conversation()->render($items, Conversation::MODE_SEARCH, false, false, 'commented', DI::userSession()->getLocalUserId()); if (DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'infinite_scroll', true)) { - $o .= HTML::scrollLoader(); + $o .= HTML::scrollLoader($request); } else { $o .= $pager->renderMinimal($count); } diff --git a/src/Module/Update/Contact.php b/src/Module/Update/Contact.php index 44de5c2d73..0fbf603177 100644 --- a/src/Module/Update/Contact.php +++ b/src/Module/Update/Contact.php @@ -77,6 +77,6 @@ final class Contact extends ContactModule throw new NotFoundException(); } - System::htmlUpdateExit(ModelContact::getThreadsFromId($pcid, $this->userSession->getLocalUserId(), true, $item['parent'] ?? 0, $request['last_received'] ?? '')); + System::htmlUpdateExit(ModelContact::getThreadsFromId($pcid, $this->userSession->getLocalUserId(), true, $item['parent'] ?? 0, $request)); } } From 309f22bf75a42c6e41646c99ed460076bd794256 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 1 Mar 2026 17:23:11 +0000 Subject: [PATCH 157/197] Fix code style --- src/Content/Text/HTML.php | 36 +++++++++++++-------------- src/Model/Contact.php | 1 - src/Module/Contact/Follow.php | 2 +- src/Module/Contact/Unfollow.php | 2 +- src/Module/Conversation/Channel.php | 2 +- src/Module/Conversation/Community.php | 16 ++++++------ src/Module/Conversation/Network.php | 18 +++++++------- src/Module/Profile/Media.php | 2 +- src/Module/Search/Filed.php | 5 ++-- src/Module/Search/Index.php | 14 +++++------ 10 files changed, 48 insertions(+), 50 deletions(-) diff --git a/src/Content/Text/HTML.php b/src/Content/Text/HTML.php index a30c9d7e99..c908345ab8 100644 --- a/src/Content/Text/HTML.php +++ b/src/Content/Text/HTML.php @@ -153,7 +153,7 @@ class HTML "
  • ", "
  • ", ], - $message + $message, ); // remove namespaces @@ -209,7 +209,7 @@ class HTML 'div', ['style' => 'border:none;border-left:solid blue 1.5pt;padding:0cm 0cm 0cm 4.0pt'], '[quote]', - '[/quote]' + '[/quote]', ); // MyBB-Stuff @@ -244,7 +244,7 @@ class HTML $elements = [ 'b', 'del', 'em', 'i', 'ins', 'kbd', 'mark', - 's', 'samp', 'strong', 'sub', 'sup', 'u', 'var' + 's', 'samp', 'strong', 'sub', 'sup', 'u', 'var', ]; foreach ($elements as $element) { self::tagToBBCode($doc, $element, [], '[' . $element . ']', '[/' . $element . ']'); @@ -348,7 +348,7 @@ class HTML $message = str_replace( ['[b][b]', '[/b][/b]', '[i][i]', '[/i][/i]'], ['[b]', '[/b]', '[i]', '[/i]'], - $message + $message, ); // Handling Yahoo style of mails @@ -367,7 +367,7 @@ class HTML return $prefix . "\n" . html_entity_decode($matches[2]) . "\n" . '[/code]'; }, - $message + $message, ); $message = trim($message); @@ -402,7 +402,7 @@ class HTML } $parts = array_merge($base, parse_url($url)); - $url2 = (string)Uri::fromParts((array)$parts); + $url2 = (string) Uri::fromParts((array) $parts); return str_replace($url, $url2, $link); } @@ -436,7 +436,7 @@ class HTML function ($match) use ($basepath) { return self::qualifyURLsSub($match, $basepath); }, - $body + $body, ); } return $body; @@ -531,7 +531,7 @@ class HTML // A list of some links that should be ignored $list = [ "/user/", "/tag/", "/group/", "/circle/", "/profile/", "/search?search=", "/search?tag=", "mailto:", "/u/", "/node/", - "//plus.google.com/", "//twitter.com/" + "//plus.google.com/", "//twitter.com/", ]; foreach ($list as $listitem) { if (strpos($treffer[1], $listitem) !== false) { @@ -708,19 +708,19 @@ class HTML $s = preg_replace( '#]+>(.*?)https?://www.youtube.com/((?:v|cp)/[A-Za-z0-9\-_=]+)(.*?)#ism', '[youtube]$2[/youtube]', - $s + $s, ); $s = preg_replace( '#](.*?)https?://www.youtube.com/embed/([A-Za-z0-9\-_=]+)(.*?)#ism', '[youtube]$2[/youtube]', - $s + $s, ); $s = preg_replace( '#](.*?)https?://player.vimeo.com/video/([0-9]+)(.*?)#ism', '[vimeo]$2[/vimeo]', - $s + $s, ); return $s; @@ -778,13 +778,13 @@ class HTML return ''; } - $tpl = Renderer::getMarkupTemplate('infinite_scroll_head.tpl'); + $tpl = Renderer::getMarkupTemplate('infinite_scroll_head.tpl'); $loader = Renderer::replaceMacros($tpl, ['$reload_uri' => DI::args()->getQueryString()]); $tpl = Renderer::getMarkupTemplate("scroll_loader.tpl"); return $loader . Renderer::replaceMacros($tpl, [ 'wait' => DI::l10n()->t('Loading more entries...'), - 'end' => DI::l10n()->t('The end') + 'end' => DI::l10n()->t('The end'), ]); } @@ -839,7 +839,7 @@ class HTML '$name' => $contact['name'], 'title' => $contact['name'] . ' [' . $contact['addr'] . ']', '$parkle' => $sparkle, - '$redir' => $redir + '$redir' => $redir, ]); } @@ -877,7 +877,7 @@ class HTML $values['$search_options'] = [ 'fulltext' => DI::l10n()->t('Full Text'), 'tags' => DI::l10n()->t('Tags'), - 'contacts' => DI::l10n()->t('Contacts') + 'contacts' => DI::l10n()->t('Contacts'), ]; if (DI::config()->get('system', 'poco_local_search')) { @@ -906,7 +906,7 @@ class HTML '$reasons' => $reasons, '$rnd' => Strings::getRandomHex(8), '$openclose' => DI::l10n()->t('Click to open/close'), - '$html' => $html + '$html' => $html, ]); } @@ -954,7 +954,7 @@ class HTML ' . implode('|', $allowedIframeDomains) . ' ) (?:/|$) # Prevents bogus domains like youtube.com.fake.tld - %xi' + %xi', ); $config->set('Attr.AllowedRel', [ @@ -1080,7 +1080,7 @@ class HTML * * @param string $html * @param string $className - * @return string the HTML without the removed HTML element + * @return string the HTML without the removed HTML element */ public static function removeElementByClass(string $html, string $className): string { diff --git a/src/Model/Contact.php b/src/Model/Contact.php index 6bab4573ea..623e82ea1e 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -15,7 +15,6 @@ use Friendica\Content\Conversation as ConversationContent; use Friendica\Content\Pager; use Friendica\Content\Text\HTML; use Friendica\Core\Protocol; -use Friendica\Core\Renderer; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\Database; diff --git a/src/Module/Contact/Follow.php b/src/Module/Contact/Follow.php index ce8162b9e7..04f131acac 100644 --- a/src/Module/Contact/Follow.php +++ b/src/Module/Contact/Follow.php @@ -175,7 +175,7 @@ class Follow extends BaseModule $output .= Renderer::replaceMacros( Renderer::getMarkupTemplate('section_title.tpl'), - ['$title' => $this->t('Posts and Replies')] + ['$title' => $this->t('Posts and Replies')], ); // Show last public posts diff --git a/src/Module/Contact/Unfollow.php b/src/Module/Contact/Unfollow.php index 94efacc2f9..b50afaab71 100644 --- a/src/Module/Contact/Unfollow.php +++ b/src/Module/Contact/Unfollow.php @@ -116,7 +116,7 @@ class Unfollow extends \Friendica\BaseModule '$myaddr' => $self['url'], '$action' => $this->baseUrl . '/contact/unfollow', '$keywords' => '', - '$keywords_label' => '' + '$keywords_label' => '', ]); $this->page['aside'] = Widget\VCard::getHTML(Contact::getByURL($contact['url'], false), false, true); diff --git a/src/Module/Conversation/Channel.php b/src/Module/Conversation/Channel.php index d18c22d4a8..762fb0eaf7 100644 --- a/src/Module/Conversation/Channel.php +++ b/src/Module/Conversation/Channel.php @@ -128,7 +128,7 @@ class Channel extends Timeline $this->args->getQueryString(), $items[array_key_first($items)][$order], $items[array_key_last($items)][$order], - $this->itemsPerPage + $this->itemsPerPage, ); if ($this->pConfig->get($this->session->getLocalUserId(), 'system', 'infinite_scroll', true)) { diff --git a/src/Module/Conversation/Community.php b/src/Module/Conversation/Community.php index 40e680d42f..4783cb769b 100644 --- a/src/Module/Conversation/Community.php +++ b/src/Module/Conversation/Community.php @@ -41,11 +41,11 @@ class Community extends Timeline * Type of the community page * @{ */ - const DISABLED = -2; - const DISABLED_VISITOR = -1; - const LOCAL = 0; - const GLOBAL = 1; - const LOCAL_AND_GLOBAL = 2; + public const DISABLED = -2; + public const DISABLED_VISITOR = -1; + public const LOCAL = 0; + public const GLOBAL = 1; + public const LOCAL_AND_GLOBAL = 2; protected $pageStyle; @@ -77,7 +77,7 @@ class Community extends Timeline '$content' => '', '$header' => '', '$show_global_community_hint' => ($this->selectedTab == CommunityEntity::GLOBAL) && $this->config->get('system', 'show_global_community_hint'), - '$global_community_hint' => $this->l10n->t("This community stream shows all public posts received by this node. They may not reflect the opinions of this node’s users.") + '$global_community_hint' => $this->l10n->t("This community stream shows all public posts received by this node. They may not reflect the opinions of this node’s users."), ]); if (!$this->raw) { @@ -107,7 +107,7 @@ class Community extends Timeline if (!$this->database->isResult($items)) { $o .= Renderer::replaceMacros(Renderer::getMarkupTemplate('section_title.tpl'), [ - '$title' => $this->l10n->t('No results.') + '$title' => $this->l10n->t('No results.'), ]); return $o; } @@ -119,7 +119,7 @@ class Community extends Timeline $this->args->getQueryString(), $items[array_key_first($items)]['received'], $items[array_key_last($items)]['received'], - $this->itemsPerPage + $this->itemsPerPage, ); if ($this->pConfig->get($this->session->getLocalUserId(), 'system', 'infinite_scroll', true)) { diff --git a/src/Module/Conversation/Network.php b/src/Module/Conversation/Network.php index f5f32237bd..03a99d6356 100644 --- a/src/Module/Conversation/Network.php +++ b/src/Module/Conversation/Network.php @@ -163,7 +163,7 @@ class Network extends Timeline ]; $this->eventDispatcher->dispatch( - new ArrayFilterEvent(ArrayFilterEvent::NETWORK_CONTENT_START, $hook_data) + new ArrayFilterEvent(ArrayFilterEvent::NETWORK_CONTENT_START, $hook_data), ); $o = ''; @@ -180,7 +180,7 @@ class Network extends Timeline Feature::SEARCHES, Feature::FOLDERS, Feature::NOSHARER, - Feature::TRENDING_TAGS + Feature::TRENDING_TAGS, ]; } @@ -215,8 +215,8 @@ class Network extends Timeline $this->page['aside'] .= TrendingTags::getHTML($this->selectedTab); break; case Feature::NOSHARER: - if (($this->channel->isTimeline($this->selectedTab) || $this->userDefinedChannel->isTimeline($this->selectedTab, $this->session->getLocalUserId())) && - !in_array($this->selectedTab, [Channel::FOLLOWERS, Channel::FORYOU, Channel::DISCOVER])) { + if (($this->channel->isTimeline($this->selectedTab) || $this->userDefinedChannel->isTimeline($this->selectedTab, $this->session->getLocalUserId())) + && !in_array($this->selectedTab, [Channel::FOLLOWERS, Channel::FORYOU, Channel::DISCOVER])) { $this->page['aside'] .= $this->getNoSharerWidget('network'); } break; @@ -272,7 +272,7 @@ class Network extends Timeline } $o = Renderer::replaceMacros(Renderer::getMarkupTemplate('section_title.tpl'), [ - '$title' => $this->l10n->t('Circle: %s', $circle['name']) + '$title' => $this->l10n->t('Circle: %s', $circle['name']), ]) . $o; } elseif (Profile::shouldDisplayEventList($this->session->getLocalUserId(), $this->mode)) { $o .= Profile::getBirthdays($this->session->getLocalUserId()); @@ -304,7 +304,7 @@ class Network extends Timeline $this->args->getQueryString(), $items[array_key_first($items)][$this->order] ?? null, $items[array_key_last($items)][$this->order] ?? null, - $this->itemsPerPage + $this->itemsPerPage, ); $o .= $pager->renderMinimal(count($items)); @@ -359,7 +359,7 @@ class Network extends Timeline ]; $hook_data = $this->eventDispatcher->dispatch( - new ArrayFilterEvent(ArrayFilterEvent::NETWORK_CONTENT_TABS, $hook_data) + new ArrayFilterEvent(ArrayFilterEvent::NETWORK_CONTENT_TABS, $hook_data), )->getArray(); if (!empty($network_timelines)) { @@ -383,7 +383,7 @@ class Network extends Timeline { parent::parseRequest($request); - $this->circleId = (int)($this->parameters['circle_id'] ?? 0); + $this->circleId = (int) ($this->parameters['circle_id'] ?? 0); if (!$this->selectedTab) { $this->selectedTab = $this->getTimelineOrderBySession(); @@ -560,7 +560,7 @@ class Network extends Timeline if (!$this->mention && !$this->star) { foreach ($this->pConfig->get($this->session->getLocalUserId(), 'channel', 'timeline_channels') ?? [] as $channel) { if (is_numeric($channel)) { - $userchannels[] = (int)$channel; + $userchannels[] = (int) $channel; } else { $systemchannels[] = $channel; } diff --git a/src/Module/Profile/Media.php b/src/Module/Profile/Media.php index 78c97c0bec..64015cea05 100644 --- a/src/Module/Profile/Media.php +++ b/src/Module/Profile/Media.php @@ -47,7 +47,7 @@ class Media extends BaseProfile ) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); - $this->appHelper = $appHelper; + $this->appHelper = $appHelper; $this->userSession = $userSession; } diff --git a/src/Module/Search/Filed.php b/src/Module/Search/Filed.php index 17884ede64..0615faa483 100644 --- a/src/Module/Search/Filed.php +++ b/src/Module/Search/Filed.php @@ -12,7 +12,6 @@ use Friendica\Content\Nav; use Friendica\Content\Pager; use Friendica\Content\Text\HTML; use Friendica\Content\Widget; -use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Item; @@ -43,14 +42,14 @@ class Filed extends BaseSearch DI::userSession()->getLocalUserId(), 'system', 'itemspage_mobile_network', - DI::config()->get('system', 'itemspage_network_mobile') + DI::config()->get('system', 'itemspage_network_mobile'), ); } else { $itemspage_network = DI::pConfig()->get( DI::userSession()->getLocalUserId(), 'system', 'itemspage_network', - DI::config()->get('system', 'itemspage_network') + DI::config()->get('system', 'itemspage_network'), ); } diff --git a/src/Module/Search/Index.php b/src/Module/Search/Index.php index 49d0609277..018fca1383 100644 --- a/src/Module/Search/Index.php +++ b/src/Module/Search/Index.php @@ -98,7 +98,7 @@ class Index extends BaseSearch 'name' => 'search-header', '$title' => DI::l10n()->t('Search'), '$title_size' => 3, - '$content' => HTML::search($search, 'search-box', false) + '$content' => HTML::search($search, 'search-box', false), ]); if (!$search) { @@ -137,7 +137,7 @@ class Index extends BaseSearch if (parse_url($search, PHP_URL_SCHEME) && parse_url($search, PHP_URL_HOST)) { $this->logger->info('Skipping tag and fulltext search since the search looks like a URL.', ['q' => $search]); $o .= Renderer::replaceMacros(Renderer::getMarkupTemplate('section_title.tpl'), [ - '$title' => DI::l10n()->t('No results.') + '$title' => DI::l10n()->t('No results.'), ]); return $o; } @@ -154,14 +154,14 @@ class Index extends BaseSearch DI::userSession()->getLocalUserId(), 'system', 'itemspage_mobile_network', - DI::config()->get('system', 'itemspage_network_mobile') + DI::config()->get('system', 'itemspage_network_mobile'), ); } else { $itemsPerPage = DI::pConfig()->get( DI::userSession()->getLocalUserId(), 'system', 'itemspage_network', - DI::config()->get('system', 'itemspage_network') + DI::config()->get('system', 'itemspage_network'), ); } @@ -189,7 +189,7 @@ class Index extends BaseSearch if (empty($items)) { if (empty($last_uriid)) { $o .= Renderer::replaceMacros(Renderer::getMarkupTemplate('section_title.tpl'), [ - '$title' => DI::l10n()->t('No results.') + '$title' => DI::l10n()->t('No results.'), ]); } return $o; @@ -202,7 +202,7 @@ class Index extends BaseSearch } $o .= Renderer::replaceMacros(Renderer::getMarkupTemplate('section_title.tpl'), [ - '$title' => $title + '$title' => $title, ]); $this->logger->info('Start Conversation.', ['q' => $search]); @@ -238,7 +238,7 @@ class Index extends BaseSearch { $search = Network::convertToIdn($search); $isUrl = !empty(parse_url($search, PHP_URL_SCHEME)); - $isAddr = (bool)preg_match('/^@?([a-z0-9.-_]+@[a-z0-9.-_:]+)$/i', trim($search), $matches); + $isAddr = (bool) preg_match('/^@?([a-z0-9.-_]+@[a-z0-9.-_:]+)$/i', trim($search), $matches); if (!$isUrl && !$isAddr) { return; From 49243ddf5bddc99fb0c3f5b59d84a31270c6691e Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 23 Feb 2026 22:47:40 +0000 Subject: [PATCH 158/197] "lostpass" is now a module as well --- mod/lostpass.php | 172 -------------------------- src/Module/LostPass.php | 193 +++++++++++++++++++++++++++++ static/routes.config.php | 1 + view/lang/C/messages.po | 256 +++++++++++++++++++-------------------- 4 files changed, 322 insertions(+), 300 deletions(-) delete mode 100644 mod/lostpass.php create mode 100644 src/Module/LostPass.php diff --git a/mod/lostpass.php b/mod/lostpass.php deleted file mode 100644 index 39c1e14a81..0000000000 --- a/mod/lostpass.php +++ /dev/null @@ -1,172 +0,0 @@ -redirect(); - } - - $condition = ['(`email` = ? OR `nickname` = ?) AND `verified` AND NOT `blocked` AND NOT `account_removed` AND NOT `account_expired`', $loginame, $loginame]; - $user = DBA::selectFirst('user', ['uid', 'username', 'nickname', 'email', 'language'], $condition); - if (!DBA::isResult($user)) { - DI::sysmsg()->addNotice(DI::l10n()->t('No valid account found.')); - DI::baseUrl()->redirect(); - } - - $pwdreset_token = Strings::getRandomHex(32); - - $fields = [ - 'pwdreset' => hash('sha256', $pwdreset_token), - 'pwdreset_time' => DateTimeFormat::utcNow() - ]; - $result = DBA::update('user', $fields, ['uid' => $user['uid']]); - if ($result) { - DI::sysmsg()->addInfo(DI::l10n()->t('Password reset request issued. Check your email.')); - } - - $sitename = DI::config()->get('config', 'sitename'); - $resetlink = DI::baseUrl() . '/lostpass/' . $pwdreset_token; - - $preamble = Strings::deindent(DI::l10n()->t(' - Dear %1$s, - A request was recently received at "%2$s" to reset your account - password. In order to confirm this request, please select the verification link - below or paste it into your web browser address bar. - - If you did NOT request this change, please DO NOT follow the link - provided and ignore and/or delete this email, the request will expire shortly. - - Your password will not be changed unless we can verify that you - issued this request.', $user['username'], $sitename)); - $body = Strings::deindent(DI::l10n()->t(' - Follow this link soon to verify your identity: - - %1$s - - You will then receive a follow-up message containing the new password. - You may change that password from your account settings page after logging in. - - The login details are as follows: - - Site Location: %2$s - Login Name: %3$s', $resetlink, DI::baseUrl(), $user['nickname'])); - - $email = DI::emailer() - ->newSystemMail() - ->withMessage(DI::l10n()->t('Password reset requested at %s', $sitename), $preamble, $body) - ->forUser($user) - ->withRecipient($user['email']) - ->build(); - - DI::emailer()->send($email); - DI::baseUrl()->redirect(); -} - -function lostpass_content() -{ - if (DI::args()->getArgc() > 1) { - $pwdreset_token = DI::args()->getArgv()[1]; - - $user = DBA::selectFirst('user', ['uid', 'username', 'nickname', 'email', 'pwdreset_time', 'language'], ['pwdreset' => hash('sha256', $pwdreset_token)]); - if (!DBA::isResult($user)) { - DI::sysmsg()->addNotice(DI::l10n()->t("Request could not be verified. \x28You may have previously submitted it.\x29 Password reset failed.")); - - return lostpass_form(); - } - - // Password reset requests expire in 60 minutes - if ($user['pwdreset_time'] < DateTimeFormat::utc('now - 1 hour')) { - $fields = [ - 'pwdreset' => null, - 'pwdreset_time' => null - ]; - DBA::update('user', $fields, ['uid' => $user['uid']]); - - DI::sysmsg()->addNotice(DI::l10n()->t('Request has expired, please make a new one.')); - - return lostpass_form(); - } - - return lostpass_generate_password($user); - } else { - return lostpass_form(); - } -} - -function lostpass_form() -{ - $tpl = Renderer::getMarkupTemplate('lostpass.tpl'); - $o = Renderer::replaceMacros($tpl, [ - '$title' => DI::l10n()->t('Forgot your Password?'), - '$desc' => DI::l10n()->t('Enter your email address and submit to have your password reset. Then check your email for further instructions.'), - '$name' => DI::l10n()->t('Nickname or email'), - '$submit' => DI::l10n()->t('Reset my password') - ]); - - return $o; -} - -function lostpass_generate_password($user) -{ - $o = ''; - - $new_password = User::generateNewPassword(); - $result = User::updatePassword($user['uid'], $new_password); - if (DBA::isResult($result)) { - $tpl = Renderer::getMarkupTemplate('pwdreset.tpl'); - $o .= Renderer::replaceMacros($tpl, [ - '$lbl1' => DI::l10n()->t('Password Reset'), - '$lbl2' => DI::l10n()->t('Your password has been reset as requested.'), - '$lbl3' => DI::l10n()->t('Your new password is'), - '$lbl4' => DI::l10n()->t('Save or copy your new password - and then'), - '$lbl5' => '' . DI::l10n()->t('click here to login') . '.', - '$lbl6' => DI::l10n()->t('Your password may be changed from the Settings page after successful login.'), - '$newpass' => $new_password, - ]); - - DI::sysmsg()->addInfo(DI::l10n()->t("Your password has been reset.")); - - $sitename = DI::config()->get('config', 'sitename'); - $preamble = Strings::deindent(DI::l10n()->t(' - Dear %1$s, - Your password has been changed as requested. Please retain this - information for your records ' . "\x28" . 'or change your password immediately to - something that you will remember' . "\x29" . '. - ', $user['username'])); - $body = Strings::deindent(DI::l10n()->t(' - Your login details are as follows: - - Site Location: %1$s - Login Name: %2$s - Password: %3$s - - You may change that password from your account settings page after logging in. - ', DI::baseUrl(), $user['nickname'], $new_password)); - - $email = DI::emailer() - ->newSystemMail() - ->withMessage(DI::l10n()->t('Your password has been changed at %s', $sitename), $preamble, $body) - ->forUser($user) - ->withRecipient($user['email']) - ->build(); - DI::emailer()->send($email); - } - - return $o; -} diff --git a/src/Module/LostPass.php b/src/Module/LostPass.php new file mode 100644 index 0000000000..533e20dc1c --- /dev/null +++ b/src/Module/LostPass.php @@ -0,0 +1,193 @@ +sysMessages = $sysMessages; + $this->config = $config; + $this->emailer = $emailer; + } + + protected function post(array $request = []) + { + $loginame = trim($request['login-name'] ?? ''); + if (!$loginame) { + $this->baseUrl->redirect(); + } + + $condition = ['(`email` = ? OR `nickname` = ?) AND `verified` AND NOT `blocked` AND NOT `account_removed` AND NOT `account_expired`', $loginame, $loginame]; + $user = DBA::selectFirst('user', ['uid', 'username', 'nickname', 'email', 'language'], $condition); + if (!DBA::isResult($user)) { + $this->sysMessages->addNotice($this->l10n->t('No valid account found.')); + $this->baseUrl->redirect(); + } + + $pwdreset_token = Strings::getRandomHex(32); + + $fields = [ + 'pwdreset' => hash('sha256', $pwdreset_token), + 'pwdreset_time' => DateTimeFormat::utcNow(), + ]; + $result = DBA::update('user', $fields, ['uid' => $user['uid']]); + if ($result) { + $this->sysMessages->addInfo($this->l10n->t('Password reset request issued. Check your email.')); + } + + $sitename = $this->config->get('config', 'sitename'); + $resetlink = $this->baseUrl . '/lostpass/' . $pwdreset_token; + + $preamble = Strings::deindent($this->l10n->t(' + Dear %1$s, + A request was recently received at "%2$s" to reset your account + password. In order to confirm this request, please select the verification link + below or paste it into your web browser address bar. + + If you did NOT request this change, please DO NOT follow the link + provided and ignore and/or delete this email, the request will expire shortly. + + Your password will not be changed unless we can verify that you + issued this request.', $user['username'], $sitename)); + $body = Strings::deindent($this->l10n->t(' + Follow this link soon to verify your identity: + + %1$s + + You will then receive a follow-up message containing the new password. + You may change that password from your account settings page after logging in. + + The login details are as follows: + + Site Location: %2$s + Login Name: %3$s', $resetlink, $this->baseUrl, $user['nickname'])); + + $email = $this->emailer->newSystemMail() + ->withMessage($this->l10n->t('Password reset requested at %s', $sitename), $preamble, $body) + ->forUser($user) + ->withRecipient($user['email']) + ->build(); + + $this->emailer->send($email); + $this->baseUrl->redirect(); + } + + protected function content(array $request = []): string + { + if (isset($this->parameters['token'])) { + $pwdreset_token = $this->parameters['token']; + + $user = DBA::selectFirst('user', ['uid', 'username', 'nickname', 'email', 'pwdreset_time', 'language'], ['pwdreset' => hash('sha256', $pwdreset_token)]); + if (!DBA::isResult($user)) { + $this->sysMessages->addNotice($this->l10n->t("Request could not be verified. \x28You may have previously submitted it.\x29 Password reset failed.")); + + return $this->form(); + } + + // Password reset requests expire in 60 minutes + if ($user['pwdreset_time'] < DateTimeFormat::utc('now - 1 hour')) { + $fields = [ + 'pwdreset' => null, + 'pwdreset_time' => null, + ]; + DBA::update('user', $fields, ['uid' => $user['uid']]); + + $this->sysMessages->addNotice($this->l10n->t('Request has expired, please make a new one.')); + + return $this->form(); + } + + return $this->generatePassword($user); + } else { + return $this->form(); + } + } + + private function form(): string + { + $tpl = Renderer::getMarkupTemplate('lostpass.tpl'); + $o = Renderer::replaceMacros($tpl, [ + '$title' => $this->l10n->t('Forgot your Password?'), + '$desc' => $this->l10n->t('Enter your email address and submit to have your password reset. Then check your email for further instructions.'), + '$name' => $this->l10n->t('Nickname or email'), + '$submit' => $this->l10n->t('Reset my password'), + ]); + + return $o; + } + + private function generatePassword(array $user): string + { + $o = ''; + + $new_password = User::generateNewPassword(); + $result = User::updatePassword($user['uid'], $new_password); + if (DBA::isResult($result)) { + $tpl = Renderer::getMarkupTemplate('pwdreset.tpl'); + $o .= Renderer::replaceMacros($tpl, [ + '$lbl1' => $this->l10n->t('Password Reset'), + '$lbl2' => $this->l10n->t('Your password has been reset as requested.'), + '$lbl3' => $this->l10n->t('Your new password is'), + '$lbl4' => $this->l10n->t('Save or copy your new password - and then'), + '$lbl5' => '' . $this->l10n->t('click here to login') . '.', + '$lbl6' => $this->l10n->t('Your password may be changed from the Settings page after successful login.'), + '$newpass' => $new_password, + ]); + + $this->sysMessages->addInfo($this->l10n->t("Your password has been reset.")); + + $sitename = $this->config->get('config', 'sitename'); + $preamble = Strings::deindent($this->l10n->t(' + Dear %1$s, + Your password has been changed as requested. Please retain this + information for your records ' . "\x28" . 'or change your password immediately to + something that you will remember' . "\x29" . '. + ', $user['username'])); + $body = Strings::deindent($this->l10n->t(' + Your login details are as follows: + + Site Location: %1$s + Login Name: %2$s + Password: %3$s + + You may change that password from your account settings page after logging in. + ', $this->baseUrl, $user['nickname'], $new_password)); + + $email = $this->emailer->newSystemMail() + ->withMessage($this->l10n->t('Your password has been changed at %s', $sitename), $preamble, $body) + ->forUser($user) + ->withRecipient($user['email']) + ->build(); + $this->emailer->send($email); + } + + return $o; + } +} diff --git a/static/routes.config.php b/static/routes.config.php index 9cf450338f..269dddad9d 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -479,6 +479,7 @@ return [ '/localtime' => [Module\Debug\Localtime::class, [R::GET, R::POST]], '/login' => [Module\Security\Login::class, [R::GET, R::POST]], '/logout' => [Module\Security\Logout::class, [R::GET, R::POST]], + '/lostpass[/{token}]' => [Module\LostPass::class, [R::GET, R::POST]], '/magic' => [Module\Magic::class, [R::GET]], '/manifest' => [Module\Manifest::class, [R::GET]], '/manifest.json' => [Module\Manifest::class, [R::GET]], diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index d7c4399dc1..e9f895d263 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -82,134 +82,6 @@ msgstr "" msgid "Permission denied." msgstr "" -#: mod/lostpass.php:28 -msgid "No valid account found." -msgstr "" - -#: mod/lostpass.php:40 -msgid "Password reset request issued. Check your email." -msgstr "" - -#: mod/lostpass.php:46 -#, php-format -msgid "" -"\n" -"\t\tDear %1$s,\n" -"\t\t\tA request was recently received at \"%2$s\" to reset your account\n" -"\t\tpassword. In order to confirm this request, please select the verification link\n" -"\t\tbelow or paste it into your web browser address bar.\n" -"\n" -"\t\tIf you did NOT request this change, please DO NOT follow the link\n" -"\t\tprovided and ignore and/or delete this email, the request will expire shortly.\n" -"\n" -"\t\tYour password will not be changed unless we can verify that you\n" -"\t\tissued this request." -msgstr "" - -#: mod/lostpass.php:57 -#, php-format -msgid "" -"\n" -"\t\tFollow this link soon to verify your identity:\n" -"\n" -"\t\t%1$s\n" -"\n" -"\t\tYou will then receive a follow-up message containing the new password.\n" -"\t\tYou may change that password from your account settings page after logging in.\n" -"\n" -"\t\tThe login details are as follows:\n" -"\n" -"\t\tSite Location:\t%2$s\n" -"\t\tLogin Name:\t%3$s" -msgstr "" - -#: mod/lostpass.php:72 -#, php-format -msgid "Password reset requested at %s" -msgstr "" - -#: mod/lostpass.php:88 -msgid "Request could not be verified. (You may have previously submitted it.) Password reset failed." -msgstr "" - -#: mod/lostpass.php:101 -msgid "Request has expired, please make a new one." -msgstr "" - -#: mod/lostpass.php:116 -msgid "Forgot your Password?" -msgstr "" - -#: mod/lostpass.php:117 -msgid "Enter your email address and submit to have your password reset. Then check your email for further instructions." -msgstr "" - -#: mod/lostpass.php:118 src/Module/Security/Login.php:167 -msgid "Nickname or email" -msgstr "" - -#: mod/lostpass.php:119 -msgid "Reset my password" -msgstr "" - -#: mod/lostpass.php:134 src/Module/Security/Login.php:179 -msgid "Password Reset" -msgstr "" - -#: mod/lostpass.php:135 -msgid "Your password has been reset as requested." -msgstr "" - -#: mod/lostpass.php:136 -msgid "Your new password is" -msgstr "" - -#: mod/lostpass.php:137 -msgid "Save or copy your new password - and then" -msgstr "" - -#: mod/lostpass.php:138 -msgid "click here to login" -msgstr "" - -#: mod/lostpass.php:139 -msgid "Your password may be changed from the Settings page after successful login." -msgstr "" - -#: mod/lostpass.php:143 -msgid "Your password has been reset." -msgstr "" - -#: mod/lostpass.php:146 -#, php-format -msgid "" -"\n" -"\t\t\tDear %1$s,\n" -"\t\t\t\tYour password has been changed as requested. Please retain this\n" -"\t\t\tinformation for your records (or change your password immediately to\n" -"\t\t\tsomething that you will remember).\n" -"\t\t" -msgstr "" - -#: mod/lostpass.php:152 -#, php-format -msgid "" -"\n" -"\t\t\tYour login details are as follows:\n" -"\n" -"\t\t\tSite Location:\t%1$s\n" -"\t\t\tLogin Name:\t%2$s\n" -"\t\t\tPassword:\t%3$s\n" -"\n" -"\t\t\tYou may change that password from your account settings page after logging in.\n" -"\t\t" -msgstr "" - -#: mod/lostpass.php:164 -#, php-format -msgid "Your password has been changed at %s" -msgstr "" - #: mod/message.php:28 mod/message.php:124 src/Content/Nav.php:315 #: view/theme/frio/theme.php:229 msgid "Messages" @@ -7245,6 +7117,134 @@ msgstr "" msgid "Unable to follow this item." msgstr "" +#: src/Module/LostPass.php:50 +msgid "No valid account found." +msgstr "" + +#: src/Module/LostPass.php:62 +msgid "Password reset request issued. Check your email." +msgstr "" + +#: src/Module/LostPass.php:68 +#, php-format +msgid "" +"\n" +"\t\t\tDear %1$s,\n" +"\t\t\t\tA request was recently received at \"%2$s\" to reset your account\n" +"\t\t\tpassword. In order to confirm this request, please select the verification link\n" +"\t\t\tbelow or paste it into your web browser address bar.\n" +"\n" +"\t\t\tIf you did NOT request this change, please DO NOT follow the link\n" +"\t\t\tprovided and ignore and/or delete this email, the request will expire shortly.\n" +"\n" +"\t\t\tYour password will not be changed unless we can verify that you\n" +"\t\t\tissued this request." +msgstr "" + +#: src/Module/LostPass.php:79 +#, php-format +msgid "" +"\n" +"\t\t\tFollow this link soon to verify your identity:\n" +"\n" +"\t\t\t%1$s\n" +"\n" +"\t\t\tYou will then receive a follow-up message containing the new password.\n" +"\t\t\tYou may change that password from your account settings page after logging in.\n" +"\n" +"\t\t\tThe login details are as follows:\n" +"\n" +"\t\t\tSite Location:\t%2$s\n" +"\t\t\tLogin Name:\t%3$s" +msgstr "" + +#: src/Module/LostPass.php:93 +#, php-format +msgid "Password reset requested at %s" +msgstr "" + +#: src/Module/LostPass.php:109 +msgid "Request could not be verified. (You may have previously submitted it.) Password reset failed." +msgstr "" + +#: src/Module/LostPass.php:122 +msgid "Request has expired, please make a new one." +msgstr "" + +#: src/Module/LostPass.php:137 +msgid "Forgot your Password?" +msgstr "" + +#: src/Module/LostPass.php:138 +msgid "Enter your email address and submit to have your password reset. Then check your email for further instructions." +msgstr "" + +#: src/Module/LostPass.php:139 src/Module/Security/Login.php:167 +msgid "Nickname or email" +msgstr "" + +#: src/Module/LostPass.php:140 +msgid "Reset my password" +msgstr "" + +#: src/Module/LostPass.php:155 src/Module/Security/Login.php:179 +msgid "Password Reset" +msgstr "" + +#: src/Module/LostPass.php:156 +msgid "Your password has been reset as requested." +msgstr "" + +#: src/Module/LostPass.php:157 +msgid "Your new password is" +msgstr "" + +#: src/Module/LostPass.php:158 +msgid "Save or copy your new password - and then" +msgstr "" + +#: src/Module/LostPass.php:159 +msgid "click here to login" +msgstr "" + +#: src/Module/LostPass.php:160 +msgid "Your password may be changed from the Settings page after successful login." +msgstr "" + +#: src/Module/LostPass.php:164 +msgid "Your password has been reset." +msgstr "" + +#: src/Module/LostPass.php:167 +#, php-format +msgid "" +"\n" +"\t\t\t\tDear %1$s,\n" +"\t\t\t\t\tYour password has been changed as requested. Please retain this\n" +"\t\t\t\tinformation for your records (or change your password immediately to\n" +"\t\t\t\tsomething that you will remember).\n" +"\t\t\t" +msgstr "" + +#: src/Module/LostPass.php:173 +#, php-format +msgid "" +"\n" +"\t\t\t\tYour login details are as follows:\n" +"\n" +"\t\t\t\tSite Location:\t%1$s\n" +"\t\t\t\tLogin Name:\t%2$s\n" +"\t\t\t\tPassword:\t%3$s\n" +"\n" +"\t\t\t\tYou may change that password from your account settings page after logging in.\n" +"\t\t\t" +msgstr "" + +#: src/Module/LostPass.php:184 +#, php-format +msgid "Your password has been changed at %s" +msgstr "" + #: src/Module/Maintenance.php:34 src/Module/Maintenance.php:39 msgid "System down for maintenance" msgstr "" From d9b28f86a7bb72aeb485cde935c5f294ae3caf82 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 2 Mar 2026 20:59:36 +0000 Subject: [PATCH 159/197] Changed git branch --- .github/workflows/code-quality.yml | 8 ++++---- .github/workflows/tests.yml | 4 ++-- .woodpecker/.phpunit.yml | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml index f9c150f2c7..729829159c 100644 --- a/.github/workflows/code-quality.yml +++ b/.github/workflows/code-quality.yml @@ -35,7 +35,7 @@ jobs: tools: none - name: Clone addon repository - run: git clone -b 2025.07-rc --single-branch https://git.friendi.ca/friendica/friendica-addons.git addon + run: git clone -b develop --single-branch https://git.friendi.ca/friendica/friendica-addons.git addon - name: Install Composer dependencies uses: "ramsey/composer-install@v2" @@ -68,7 +68,7 @@ jobs: tools: none - name: Clone addon repository - run: git clone -b 2025.07-rc --single-branch https://git.friendi.ca/friendica/friendica-addons.git addon + run: git clone -b develop --single-branch https://git.friendi.ca/friendica/friendica-addons.git addon - name: Install Composer dependencies uses: "ramsey/composer-install@v2" @@ -100,7 +100,7 @@ jobs: tools: none - name: Clone addon repository - run: git clone -b 2025.07-rc --single-branch https://git.friendi.ca/friendica/friendica-addons.git addon + run: git clone -b develop --single-branch https://git.friendi.ca/friendica/friendica-addons.git addon - name: Install Composer dependencies uses: "ramsey/composer-install@v2" @@ -132,7 +132,7 @@ jobs: tools: none - name: Clone addon repository - run: git clone -b 2025.07-rc --single-branch https://git.friendi.ca/friendica/friendica-addons.git addon + run: git clone -b develop --single-branch https://git.friendi.ca/friendica/friendica-addons.git addon - name: Install Composer dependencies uses: "ramsey/composer-install@v2" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 31b92fefd6..d0aa623842 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -34,7 +34,7 @@ jobs: tools: none - name: Clone addon repository - run: git clone -b 2025.07-rc --single-branch https://git.friendi.ca/friendica/friendica-addons.git addon + run: git clone -b develop --single-branch https://git.friendi.ca/friendica/friendica-addons.git addon - name: Install Composer dependencies uses: "ramsey/composer-install@v2" @@ -88,7 +88,7 @@ jobs: ini-values: apc.enabled=1, apc.enable_cli=1 - name: Clone addon repository - run: git clone -b 2025.07-rc --single-branch https://git.friendi.ca/friendica/friendica-addons.git addon + run: git clone -b develop --single-branch https://git.friendi.ca/friendica/friendica-addons.git addon # Install composer dependencies and handle caching in one go. # @link https://github.com/marketplace/actions/install-php-dependencies-with-composer diff --git a/.woodpecker/.phpunit.yml b/.woodpecker/.phpunit.yml index c13f00b589..997d50a52e 100644 --- a/.woodpecker/.phpunit.yml +++ b/.woodpecker/.phpunit.yml @@ -57,7 +57,7 @@ steps: composer_install: image: friendicaci/php${PHP_MAJOR_VERSION}:php${PHP_VERSION} commands: - - git clone -b 2025.07-rc --single-branch https://git.friendi.ca/friendica/friendica-addons.git addon + - git clone -b develop --single-branch https://git.friendi.ca/friendica/friendica-addons.git addon - export COMPOSER_HOME=.composer - ./bin/composer.phar validate - ./bin/composer.phar install --prefer-dist From 1402509351acaba5978ab00c2c86201e318f9eae Mon Sep 17 00:00:00 2001 From: "Marcus F." Date: Mon, 2 Mar 2026 22:04:21 +0100 Subject: [PATCH 160/197] Directory: No results from sysmsg to page --- src/Module/Directory.php | 33 +- view/lang/C/messages.po | 290 +++++++++--------- view/templates/directory_header.tpl | 2 + .../theme/frio/templates/directory_header.tpl | 2 + 4 files changed, 165 insertions(+), 162 deletions(-) diff --git a/src/Module/Directory.php b/src/Module/Directory.php index 9d7864fb38..37c04bc2d3 100644 --- a/src/Module/Directory.php +++ b/src/Module/Directory.php @@ -29,8 +29,8 @@ class Directory extends BaseModule { $config = DI::config(); - if (($config->get('system', 'block_public') && !DI::userSession()->isAuthenticated()) || - ($config->get('system', 'block_local_dir') && !DI::userSession()->isAuthenticated())) { + if (($config->get('system', 'block_public') && !DI::userSession()->isAuthenticated()) + || ($config->get('system', 'block_local_dir') && !DI::userSession()->isAuthenticated())) { throw new HTTPException\ForbiddenException(DI::l10n()->t('Public access denied.')); } @@ -56,9 +56,7 @@ class Directory extends BaseModule $profiles = Profile::searchProfiles($pager->getStart(), $pager->getItemsPerPage(), $search); - if ($profiles['total'] === 0) { - DI::sysmsg()->addNotice(DI::l10n()->t('No entries (some entries may be hidden).')); - } else { + if ($profiles['total'] !== 0) { foreach ($profiles['entries'] as $entry) { $contact = Model\Contact::getByURLForUser($entry['url'], DI::userSession()->getLocalUserId()); if (!empty($contact)) { @@ -70,17 +68,18 @@ class Directory extends BaseModule $tpl = Renderer::getMarkupTemplate('directory_header.tpl'); $output .= Renderer::replaceMacros($tpl, [ - '$search' => $search, - '$globaldir' => DI::l10n()->t('Global Directory'), - '$gDirPath' => $gDirPath, - '$desc' => DI::l10n()->t('Find on this site'), - '$contacts' => $entries, - '$finding' => DI::l10n()->t('Results for:'), - '$findterm' => (strlen($search) ? $search : ""), - '$title' => DI::l10n()->t('Site Directory'), - '$search_mod' => 'directory', - '$submit' => DI::l10n()->t('Find'), - '$paginate' => $pager->renderFull($profiles['total']), + '$search' => $search, + '$globaldir' => DI::l10n()->t('Global Directory'), + '$gDirPath' => $gDirPath, + '$desc' => DI::l10n()->t('Find on this site'), + '$contacts' => $entries, + '$no_results' => DI::l10n()->t('No accounts found (some may be hidden).'), + '$finding' => DI::l10n()->t('Results for:'), + '$findterm' => (strlen($search) ? $search : ""), + '$title' => DI::l10n()->t('Site Directory'), + '$search_mod' => 'directory', + '$submit' => DI::l10n()->t('Find'), + '$paginate' => $pager->renderFull($profiles['total']), '$num_results_text' => DI::l10n()->t("Accounts listed: %s", $profiles['total']), ]); @@ -141,7 +140,7 @@ class Directory extends BaseModule $location_e = $location; $photo_menu = [ - 'profile' => [DI::l10n()->t("View Profile"), Model\Contact::magicLink($profile_link)] + 'profile' => [DI::l10n()->t("View Profile"), Model\Contact::magicLink($profile_link)], ]; $entry = [ diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index d7c4399dc1..70703677cf 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 2026.04-dev\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-02-28 16:18+0100\n" +"POT-Creation-Date: 2026-03-02 21:37+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,33 +18,33 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" -#: mod/item.php:91 mod/item.php:94 mod/item.php:161 mod/item.php:164 +#: mod/item.php:92 mod/item.php:95 mod/item.php:164 mod/item.php:167 msgid "Unable to locate original post." msgstr "" -#: mod/item.php:129 +#: mod/item.php:132 msgid "Post updated." msgstr "" -#: mod/item.php:194 mod/item.php:198 +#: mod/item.php:197 mod/item.php:201 msgid "Item wasn't stored." msgstr "" -#: mod/item.php:208 +#: mod/item.php:211 msgid "Item couldn't be fetched." msgstr "" -#: mod/item.php:252 mod/item.php:256 +#: mod/item.php:255 mod/item.php:259 msgid "Empty post discarded." msgstr "" -#: mod/item.php:439 src/Module/Admin/Themes/Details.php:31 +#: mod/item.php:442 src/Module/Admin/Themes/Details.php:31 #: src/Module/Admin/Themes/Index.php:51 src/Module/Debug/ItemBody.php:34 #: src/Module/Debug/ItemBody.php:42 src/Module/Item/Feed.php:66 msgid "Item not found." msgstr "" -#: mod/item.php:463 mod/message.php:56 mod/message.php:102 mod/photos.php:117 +#: mod/item.php:466 mod/message.php:56 mod/message.php:102 mod/photos.php:117 #: mod/photos.php:418 src/Model/Event.php:510 src/Module/Attach.php:40 #: src/Module/BaseApi.php:91 src/Module/BaseNotifications.php:83 #: src/Module/BaseSettings.php:38 src/Module/Calendar/Event/API.php:75 @@ -283,8 +283,8 @@ msgstr "" msgid "Insert web link" msgstr "" -#: mod/message.php:190 mod/message.php:348 src/Content/Conversation.php:402 -#: src/Content/Conversation.php:1611 src/Module/Item/Compose.php:205 +#: mod/message.php:190 mod/message.php:348 src/Content/Conversation.php:405 +#: src/Content/Conversation.php:1614 src/Module/Item/Compose.php:208 #: src/Module/Post/Edit.php:143 src/Object/Post.php:620 msgid "Please wait" msgstr "" @@ -430,8 +430,8 @@ msgstr "" msgid "If you want to add this photo to an album, begin typing its name, and existing albums will be suggested, which you can select. If you choose something new, it will be created." msgstr "" -#: mod/photos.php:487 mod/photos.php:806 src/Content/Conversation.php:404 -#: src/Module/Calendar/Event/Form.php:241 src/Module/Post/Edit.php:181 +#: mod/photos.php:487 mod/photos.php:806 src/Content/Conversation.php:407 +#: src/Module/Calendar/Event/Form.php:241 src/Module/Post/Edit.php:183 msgid "Permissions" msgstr "" @@ -443,11 +443,11 @@ msgstr "" msgid "Delete Album" msgstr "" -#: mod/photos.php:556 mod/photos.php:655 src/Content/Conversation.php:419 +#: mod/photos.php:556 mod/photos.php:655 src/Content/Conversation.php:422 #: src/Module/Contact/Follow.php:158 src/Module/Contact/Revoke.php:92 #: src/Module/Contact/Unfollow.php:112 #: src/Module/Media/Attachment/Browser.php:64 -#: src/Module/Media/Photo/Browser.php:76 src/Module/Post/Edit.php:165 +#: src/Module/Media/Photo/Browser.php:76 src/Module/Post/Edit.php:167 #: src/Module/Post/Tag/Remove.php:96 src/Module/Profile/RemoteFollow.php:120 #: src/Module/Security/TwoFactor/SignOut.php:106 msgid "Cancel" @@ -546,7 +546,7 @@ msgstr "" msgid "Edit" msgstr "" -#: mod/photos.php:828 src/Content/Conversation.php:1534 +#: mod/photos.php:828 src/Content/Conversation.php:1537 #: src/Module/Moderation/Users/Active.php:92 #: src/Module/Moderation/Users/Blocked.php:92 #: src/Module/Moderation/Users/Index.php:100 @@ -1143,7 +1143,7 @@ msgstr[1] "" msgid "Visible to everybody" msgstr "" -#: src/Content/Conversation.php:337 src/Module/Item/Compose.php:199 +#: src/Content/Conversation.php:337 src/Module/Item/Compose.php:202 #: src/Object/Post.php:1178 msgid "Please enter a image/video/audio/webpage URL:" msgstr "" @@ -1172,7 +1172,7 @@ msgstr "" msgid "Go to post" msgstr "" -#: src/Content/Conversation.php:356 src/Module/Item/Compose.php:174 +#: src/Content/Conversation.php:356 src/Module/Item/Compose.php:176 msgid "Created at" msgstr "" @@ -1201,53 +1201,53 @@ msgstr "" msgid "attach file" msgstr "" -#: src/Content/Conversation.php:375 src/Module/Item/Compose.php:189 -#: src/Module/Post/Edit.php:169 src/Object/Post.php:1168 +#: src/Content/Conversation.php:375 src/Module/Item/Compose.php:192 +#: src/Module/Post/Edit.php:171 src/Object/Post.php:1168 msgid "Bold" msgstr "" -#: src/Content/Conversation.php:376 src/Module/Item/Compose.php:190 -#: src/Module/Post/Edit.php:170 src/Object/Post.php:1169 +#: src/Content/Conversation.php:376 src/Module/Item/Compose.php:193 +#: src/Module/Post/Edit.php:172 src/Object/Post.php:1169 msgid "Italic" msgstr "" -#: src/Content/Conversation.php:377 src/Module/Item/Compose.php:191 -#: src/Module/Post/Edit.php:171 src/Object/Post.php:1170 +#: src/Content/Conversation.php:377 src/Module/Item/Compose.php:194 +#: src/Module/Post/Edit.php:173 src/Object/Post.php:1170 msgid "Underline" msgstr "" -#: src/Content/Conversation.php:378 src/Module/Item/Compose.php:192 -#: src/Module/Post/Edit.php:172 src/Object/Post.php:1172 +#: src/Content/Conversation.php:378 src/Module/Item/Compose.php:195 +#: src/Module/Post/Edit.php:174 src/Object/Post.php:1172 msgid "Quote" msgstr "" -#: src/Content/Conversation.php:379 src/Module/Item/Compose.php:193 -#: src/Module/Post/Edit.php:173 src/Object/Post.php:1173 +#: src/Content/Conversation.php:379 src/Module/Item/Compose.php:196 +#: src/Module/Post/Edit.php:175 src/Object/Post.php:1173 msgid "Add emojis" msgstr "" -#: src/Content/Conversation.php:380 src/Module/Item/Compose.php:194 +#: src/Content/Conversation.php:380 src/Module/Item/Compose.php:197 #: src/Object/Post.php:1171 msgid "Content Warning" msgstr "" -#: src/Content/Conversation.php:381 src/Module/Item/Compose.php:195 -#: src/Module/Post/Edit.php:174 src/Object/Post.php:1174 +#: src/Content/Conversation.php:381 src/Module/Item/Compose.php:198 +#: src/Module/Post/Edit.php:176 src/Object/Post.php:1174 msgid "Code" msgstr "" -#: src/Content/Conversation.php:382 src/Module/Item/Compose.php:196 +#: src/Content/Conversation.php:382 src/Module/Item/Compose.php:199 #: src/Object/Post.php:1175 msgid "Image" msgstr "" -#: src/Content/Conversation.php:383 src/Module/Item/Compose.php:197 -#: src/Module/Post/Edit.php:175 src/Object/Post.php:1176 +#: src/Content/Conversation.php:383 src/Module/Item/Compose.php:200 +#: src/Module/Post/Edit.php:177 src/Object/Post.php:1176 msgid "Link" msgstr "" -#: src/Content/Conversation.php:384 src/Module/Item/Compose.php:198 -#: src/Module/Post/Edit.php:176 src/Object/Post.php:1177 +#: src/Content/Conversation.php:384 src/Module/Item/Compose.php:201 +#: src/Module/Post/Edit.php:178 src/Object/Post.php:1177 msgid "Link or Media" msgstr "" @@ -1255,7 +1255,7 @@ msgstr "" msgid "Video" msgstr "" -#: src/Content/Conversation.php:386 src/Module/Item/Compose.php:201 +#: src/Content/Conversation.php:386 src/Module/Item/Compose.php:204 #: src/Module/Post/Edit.php:139 msgid "Set your location" msgstr "" @@ -1272,12 +1272,12 @@ msgstr "" msgid "clear location" msgstr "" -#: src/Content/Conversation.php:391 src/Module/Item/Compose.php:206 +#: src/Content/Conversation.php:391 src/Module/Item/Compose.php:209 #: src/Module/Post/Edit.php:155 msgid "Set title" msgstr "" -#: src/Content/Conversation.php:393 src/Module/Item/Compose.php:207 +#: src/Content/Conversation.php:393 src/Module/Item/Compose.php:210 #: src/Module/Post/Edit.php:157 msgid "Set summary, abstract or spoiler text" msgstr "" @@ -1291,171 +1291,171 @@ msgstr "" msgid "Sensitive post" msgstr "" -#: src/Content/Conversation.php:398 src/Module/Item/Compose.php:227 +#: src/Content/Conversation.php:401 src/Module/Item/Compose.php:232 msgid "Scheduled at" msgstr "" -#: src/Content/Conversation.php:403 src/Module/Post/Edit.php:144 +#: src/Content/Conversation.php:406 src/Module/Post/Edit.php:144 msgid "Permission settings" msgstr "" -#: src/Content/Conversation.php:412 src/Module/Post/Edit.php:153 +#: src/Content/Conversation.php:415 src/Module/Post/Edit.php:153 msgid "Public post" msgstr "" -#: src/Content/Conversation.php:416 src/Module/Calendar/Event/Form.php:236 -#: src/Module/Item/Compose.php:200 src/Module/Post/Edit.php:163 +#: src/Content/Conversation.php:419 src/Module/Calendar/Event/Form.php:236 +#: src/Module/Item/Compose.php:203 src/Module/Post/Edit.php:165 #: src/Object/Post.php:1179 msgid "Preview" msgstr "" -#: src/Content/Conversation.php:426 src/Content/Item.php:442 +#: src/Content/Conversation.php:429 src/Content/Item.php:442 #: src/Content/Widget/VCard.php:120 src/Model/Contact.php:1307 #: src/Model/Profile.php:467 src/Module/Admin/Logs/View.php:79 -#: src/Module/Post/Edit.php:179 +#: src/Module/Post/Edit.php:181 msgid "Message" msgstr "" -#: src/Content/Conversation.php:427 src/Module/Post/Edit.php:180 +#: src/Content/Conversation.php:430 src/Module/Post/Edit.php:182 msgid "Add file" msgstr "" -#: src/Content/Conversation.php:429 src/Module/Post/Edit.php:183 +#: src/Content/Conversation.php:432 src/Module/Post/Edit.php:185 msgid "Open Compose page" msgstr "" -#: src/Content/Conversation.php:599 +#: src/Content/Conversation.php:602 msgid "remove" msgstr "" -#: src/Content/Conversation.php:603 +#: src/Content/Conversation.php:606 msgid "Delete Selected Items" msgstr "" -#: src/Content/Conversation.php:735 src/Content/Conversation.php:738 -#: src/Content/Conversation.php:741 src/Content/Conversation.php:744 -#: src/Content/Conversation.php:747 +#: src/Content/Conversation.php:738 src/Content/Conversation.php:741 +#: src/Content/Conversation.php:744 src/Content/Conversation.php:747 +#: src/Content/Conversation.php:750 #, php-format msgid "You had been addressed (%s)." msgstr "" -#: src/Content/Conversation.php:750 +#: src/Content/Conversation.php:753 #, php-format msgid "You are following %s." msgstr "" -#: src/Content/Conversation.php:755 +#: src/Content/Conversation.php:758 #, php-format msgid "You subscribed to %s." msgstr "" -#: src/Content/Conversation.php:757 +#: src/Content/Conversation.php:760 msgid "You subscribed to one or more tags in this post." msgstr "" -#: src/Content/Conversation.php:777 +#: src/Content/Conversation.php:780 #, php-format msgid "%s reshared this." msgstr "" -#: src/Content/Conversation.php:779 +#: src/Content/Conversation.php:782 msgid "Reshared" msgstr "" -#: src/Content/Conversation.php:779 -#, php-format -msgid "Reshared by %s <%s>" -msgstr "" - #: src/Content/Conversation.php:782 #, php-format -msgid "%s is participating in this thread." +msgid "Reshared by %s <%s>" msgstr "" #: src/Content/Conversation.php:785 -msgid "Stored for general reasons" +#, php-format +msgid "%s is participating in this thread." msgstr "" #: src/Content/Conversation.php:788 +msgid "Stored for general reasons" +msgstr "" + +#: src/Content/Conversation.php:791 msgid "Global post" msgstr "" -#: src/Content/Conversation.php:791 +#: src/Content/Conversation.php:794 msgid "Sent via an relay server" msgstr "" -#: src/Content/Conversation.php:791 +#: src/Content/Conversation.php:794 #, php-format msgid "Sent via the relay server %s <%s>" msgstr "" -#: src/Content/Conversation.php:794 +#: src/Content/Conversation.php:797 msgid "Fetched" msgstr "" -#: src/Content/Conversation.php:794 +#: src/Content/Conversation.php:797 #, php-format msgid "Fetched because of %s <%s>" msgstr "" -#: src/Content/Conversation.php:797 +#: src/Content/Conversation.php:800 msgid "Stored because of a child post to complete this thread." msgstr "" -#: src/Content/Conversation.php:800 +#: src/Content/Conversation.php:803 msgid "Local delivery" msgstr "" -#: src/Content/Conversation.php:803 +#: src/Content/Conversation.php:806 msgid "Stored because of your activity (like, comment, star, ...)" msgstr "" -#: src/Content/Conversation.php:806 +#: src/Content/Conversation.php:809 msgid "Distributed" msgstr "" -#: src/Content/Conversation.php:809 +#: src/Content/Conversation.php:812 msgid "Pushed to us" msgstr "" -#: src/Content/Conversation.php:816 +#: src/Content/Conversation.php:819 #, php-format msgid "Channel \"%s\": %s" msgstr "" -#: src/Content/Conversation.php:818 +#: src/Content/Conversation.php:821 #, php-format msgid "Channel \"%s\"" msgstr "" -#: src/Content/Conversation.php:1533 src/Object/Post.php:266 +#: src/Content/Conversation.php:1536 src/Object/Post.php:266 msgid "Select" msgstr "" -#: src/Content/Conversation.php:1553 src/Object/Post.php:253 +#: src/Content/Conversation.php:1556 src/Object/Post.php:253 msgid "Pinned item" msgstr "" -#: src/Content/Conversation.php:1570 src/Object/Post.php:555 +#: src/Content/Conversation.php:1573 src/Object/Post.php:555 #: src/Object/Post.php:556 #, php-format msgid "View %s's profile @ %s" msgstr "" -#: src/Content/Conversation.php:1584 src/Object/Post.php:543 +#: src/Content/Conversation.php:1587 src/Object/Post.php:543 msgid "Categories:" msgstr "" -#: src/Content/Conversation.php:1585 src/Object/Post.php:544 +#: src/Content/Conversation.php:1588 src/Object/Post.php:544 msgid "Filed under:" msgstr "" -#: src/Content/Conversation.php:1593 src/Object/Post.php:571 +#: src/Content/Conversation.php:1596 src/Object/Post.php:571 #, php-format msgid "%s from %s" msgstr "" -#: src/Content/Conversation.php:1609 +#: src/Content/Conversation.php:1612 msgid "View in context" msgstr "" @@ -1596,55 +1596,55 @@ msgstr "" msgid "Favourite Posts" msgstr "" -#: src/Content/Feature.php:105 +#: src/Content/Feature.php:106 msgid "General Features" msgstr "" -#: src/Content/Feature.php:107 +#: src/Content/Feature.php:108 msgid "Photo Location" msgstr "" -#: src/Content/Feature.php:107 +#: src/Content/Feature.php:108 msgid "Photo metadata is normally stripped. This extracts the location (if present) prior to stripping metadata and links it to a map." msgstr "" -#: src/Content/Feature.php:108 +#: src/Content/Feature.php:109 msgid "Display the community in the navigation" msgstr "" -#: src/Content/Feature.php:108 +#: src/Content/Feature.php:109 msgid "If enabled, the community can be accessed via the navigation menu. Independent from this setting, the community timelines can always be accessed via the channels." msgstr "" -#: src/Content/Feature.php:113 +#: src/Content/Feature.php:114 msgid "Post Composition Features" msgstr "" -#: src/Content/Feature.php:114 +#: src/Content/Feature.php:115 msgid "Explicit Mentions" msgstr "" -#: src/Content/Feature.php:114 +#: src/Content/Feature.php:115 msgid "Add explicit mentions to comment box for manual control over who gets mentioned in replies." msgstr "" -#: src/Content/Feature.php:115 +#: src/Content/Feature.php:116 msgid "Add an abstract from ActivityPub content warnings" msgstr "" -#: src/Content/Feature.php:115 +#: src/Content/Feature.php:116 msgid "Add an abstract when commenting on ActivityPub posts with a content warning. Abstracts are displayed as content warning on systems like Mastodon or Pleroma." msgstr "" -#: src/Content/Feature.php:120 +#: src/Content/Feature.php:121 msgid "Post/Comment Tools" msgstr "" -#: src/Content/Feature.php:121 +#: src/Content/Feature.php:122 msgid "Post Categories" msgstr "" -#: src/Content/Feature.php:121 +#: src/Content/Feature.php:122 msgid "Add categories to your posts" msgstr "" @@ -1659,126 +1659,126 @@ msgstr "" msgid "Add a summary, abstract or spoiler text to your posts" msgstr "" -#: src/Content/Feature.php:126 +#: src/Content/Feature.php:128 msgid "Network Widgets" msgstr "" -#: src/Content/Feature.php:127 src/Content/Widget.php:239 +#: src/Content/Feature.php:129 src/Content/Widget.php:239 #: src/Model/Circle.php:587 src/Module/Circle.php:132 #: src/Module/Contact.php:385 src/Module/Welcome.php:63 msgid "Circles" msgstr "" -#: src/Content/Feature.php:127 +#: src/Content/Feature.php:129 msgid "Display posts that have been created by accounts of the selected circle." msgstr "" -#: src/Content/Feature.php:128 src/Content/GroupManager.php:131 +#: src/Content/Feature.php:130 src/Content/GroupManager.php:131 #: src/Content/Nav.php:275 src/Content/Text/HTML.php:877 #: src/Content/Widget.php:564 src/Model/User.php:1400 msgid "Groups" msgstr "" -#: src/Content/Feature.php:128 +#: src/Content/Feature.php:130 msgid "Display posts that have been distributed by the selected group." msgstr "" -#: src/Content/Feature.php:129 src/Content/Widget.php:533 +#: src/Content/Feature.php:131 src/Content/Widget.php:533 msgid "Archives" msgstr "" -#: src/Content/Feature.php:129 +#: src/Content/Feature.php:131 msgid "Display an archive where posts can be selected by month and year." msgstr "" -#: src/Content/Feature.php:130 src/Content/Widget.php:312 +#: src/Content/Feature.php:132 src/Content/Widget.php:312 msgid "Protocols" msgstr "" -#: src/Content/Feature.php:130 +#: src/Content/Feature.php:132 msgid "Display posts with the selected protocols." msgstr "" -#: src/Content/Feature.php:131 src/Content/Widget.php:570 +#: src/Content/Feature.php:133 src/Content/Widget.php:570 #: src/Module/Settings/Account.php:391 msgid "Account Types" msgstr "" -#: src/Content/Feature.php:131 +#: src/Content/Feature.php:133 msgid "Display posts done by accounts with the selected account type." msgstr "" -#: src/Content/Feature.php:132 src/Content/Widget.php:632 +#: src/Content/Feature.php:134 src/Content/Widget.php:632 #: src/Module/Admin/Site.php:474 src/Module/BaseSettings.php:113 #: src/Module/Settings/Channels.php:224 src/Module/Settings/Display.php:433 msgid "Channels" msgstr "" -#: src/Content/Feature.php:132 +#: src/Content/Feature.php:134 msgid "Display posts in the system channels and user defined channels." msgstr "" -#: src/Content/Feature.php:133 src/Content/Widget/SavedSearches.php:46 +#: src/Content/Feature.php:135 src/Content/Widget/SavedSearches.php:46 msgid "Saved Searches" msgstr "" -#: src/Content/Feature.php:133 +#: src/Content/Feature.php:135 msgid "Display posts that contain subscribed hashtags." msgstr "" -#: src/Content/Feature.php:134 src/Content/Widget.php:342 +#: src/Content/Feature.php:136 src/Content/Widget.php:342 msgid "Saved Folders" msgstr "" -#: src/Content/Feature.php:134 +#: src/Content/Feature.php:136 msgid "Display a list of folders in which posts are stored." msgstr "" -#: src/Content/Feature.php:135 src/Module/Conversation/Timeline.php:188 +#: src/Content/Feature.php:137 src/Module/Conversation/Timeline.php:188 msgid "Own Contacts" msgstr "" -#: src/Content/Feature.php:135 +#: src/Content/Feature.php:137 msgid "Include or exclude posts from subscribed accounts. This widget is not visible on all channels." msgstr "" -#: src/Content/Feature.php:136 src/Content/Widget/TrendingTags.php:39 +#: src/Content/Feature.php:138 src/Content/Widget/TrendingTags.php:39 msgid "Trending Tags" msgstr "" -#: src/Content/Feature.php:136 +#: src/Content/Feature.php:138 msgid "Display a list of the most popular tags in recent public posts." msgstr "" -#: src/Content/Feature.php:141 +#: src/Content/Feature.php:143 msgid "Advanced Profile Settings" msgstr "" -#: src/Content/Feature.php:142 +#: src/Content/Feature.php:144 msgid "Tag Cloud" msgstr "" -#: src/Content/Feature.php:142 +#: src/Content/Feature.php:144 msgid "Provide a personal tag cloud on your profile page" msgstr "" -#: src/Content/Feature.php:143 +#: src/Content/Feature.php:145 msgid "Display Membership Date" msgstr "" -#: src/Content/Feature.php:143 +#: src/Content/Feature.php:145 msgid "Display membership date in profile" msgstr "" -#: src/Content/Feature.php:148 +#: src/Content/Feature.php:150 msgid "Advanced Calendar Settings" msgstr "" -#: src/Content/Feature.php:149 +#: src/Content/Feature.php:151 msgid "Allow anonymous access to your calendar" msgstr "" -#: src/Content/Feature.php:149 +#: src/Content/Feature.php:151 msgid "Allows anonymous visitors to consult your calendar and your public events. Contact birthday events are private to you." msgstr "" @@ -1835,7 +1835,7 @@ msgstr "" #: src/Content/Item.php:438 src/Content/Item.php:461 src/Model/Contact.php:1237 #: src/Model/Contact.php:1293 src/Model/Contact.php:1303 -#: src/Module/Directory.php:144 src/Module/Settings/Profile/Index.php:279 +#: src/Module/Directory.php:143 src/Module/Settings/Profile/Index.php:279 msgid "View Profile" msgstr "" @@ -2307,7 +2307,7 @@ msgid "Examples: Robert Morgenstein, Fishing" msgstr "" #: src/Content/Widget.php:73 src/Module/Contact.php:445 -#: src/Module/Directory.php:82 view/theme/vier/theme.php:184 +#: src/Module/Directory.php:81 view/theme/vier/theme.php:184 msgid "Find" msgstr "" @@ -2328,7 +2328,7 @@ msgstr "" msgid "Invite Friends" msgstr "" -#: src/Content/Widget.php:78 src/Module/Directory.php:74 +#: src/Content/Widget.php:78 src/Module/Directory.php:72 #: view/theme/vier/theme.php:189 msgid "Global Directory" msgstr "" @@ -2470,7 +2470,7 @@ msgstr "" #: src/Content/Widget/VCard.php:111 src/Model/Event.php:67 #: src/Model/Event.php:94 src/Model/Event.php:461 src/Model/Event.php:947 #: src/Model/Profile.php:352 src/Module/Contact/Profile.php:458 -#: src/Module/Directory.php:134 src/Module/Notifications/Introductions.php:187 +#: src/Module/Directory.php:133 src/Module/Notifications/Introductions.php:187 #: src/Module/Profile/Profile.php:230 msgid "Location:" msgstr "" @@ -2542,7 +2542,7 @@ msgstr "" msgid "CC: email addresses" msgstr "" -#: src/Core/ACL.php:323 src/Module/Post/Edit.php:158 +#: src/Core/ACL.php:323 src/Module/Post/Edit.php:160 msgid "Example: bob@example.com, mary@example.com" msgstr "" @@ -3438,7 +3438,7 @@ msgstr "" msgid "Change profile picture" msgstr "" -#: src/Model/Profile.php:355 src/Module/Directory.php:139 +#: src/Model/Profile.php:355 src/Module/Directory.php:138 #: src/Module/Profile/Profile.php:218 msgid "Homepage:" msgstr "" @@ -5907,7 +5907,7 @@ msgstr "" #: src/Module/Debug/Probe.php:40 src/Module/Debug/WebFinger.php:37 #: src/Module/FriendSuggest.php:138 src/Module/Install.php:219 #: src/Module/Install.php:259 src/Module/Install.php:296 -#: src/Module/Invite.php:162 src/Module/Item/Compose.php:188 +#: src/Module/Invite.php:162 src/Module/Item/Compose.php:191 #: src/Module/Moderation/Item/Source.php:75 #: src/Module/Moderation/Report/Create.php:157 #: src/Module/Moderation/Report/Create.php:172 @@ -6191,7 +6191,7 @@ msgstr "" msgid "Pending incoming contact request" msgstr "" -#: src/Module/Contact.php:609 src/Module/Item/Compose.php:187 +#: src/Module/Contact.php:609 src/Module/Item/Compose.php:190 #: src/Object/Post.php:1163 msgid "This is you" msgstr "" @@ -6861,23 +6861,23 @@ msgstr "" msgid "Lookup address:" msgstr "" -#: src/Module/Directory.php:60 -msgid "No entries (some entries may be hidden)." -msgstr "" - -#: src/Module/Directory.php:76 +#: src/Module/Directory.php:74 msgid "Find on this site" msgstr "" -#: src/Module/Directory.php:78 +#: src/Module/Directory.php:76 +msgid "No accounts found (some may be hidden)." +msgstr "" + +#: src/Module/Directory.php:77 msgid "Results for:" msgstr "" -#: src/Module/Directory.php:80 +#: src/Module/Directory.php:79 msgid "Site Directory" msgstr "" -#: src/Module/Directory.php:84 +#: src/Module/Directory.php:83 #, php-format msgid "Accounts listed: %s" msgstr "" @@ -7212,23 +7212,23 @@ msgstr "" msgid "Compose new post" msgstr "" -#: src/Module/Item/Compose.php:186 +#: src/Module/Item/Compose.php:189 msgid "Visibility" msgstr "" -#: src/Module/Item/Compose.php:202 +#: src/Module/Item/Compose.php:205 msgid "Clear the location" msgstr "" -#: src/Module/Item/Compose.php:203 +#: src/Module/Item/Compose.php:206 msgid "Location services are unavailable on your device" msgstr "" -#: src/Module/Item/Compose.php:204 +#: src/Module/Item/Compose.php:207 msgid "Location services are disabled. Please check the website's permissions on your device" msgstr "" -#: src/Module/Item/Compose.php:214 +#: src/Module/Item/Compose.php:218 msgid "If you want to always use this editor for posting, you can configure the New Post button to always open it in your Theme settings." msgstr "" diff --git a/view/templates/directory_header.tpl b/view/templates/directory_header.tpl index acf4627ae8..84a8f0d5f1 100644 --- a/view/templates/directory_header.tpl +++ b/view/templates/directory_header.tpl @@ -30,6 +30,8 @@ {{foreach $contacts as $contact}} {{include file="contact/entry.tpl"}} +{{foreachelse}} +
    {{$no_results}}
    {{/foreach}}
    diff --git a/view/theme/frio/templates/directory_header.tpl b/view/theme/frio/templates/directory_header.tpl index 71d1ad5552..93690376f2 100644 --- a/view/theme/frio/templates/directory_header.tpl +++ b/view/theme/frio/templates/directory_header.tpl @@ -39,6 +39,8 @@
      {{foreach $contacts as $contact}}
    • {{include file="contact/entry.tpl"}}
    • + {{foreachelse}} +
    • {{$no_results}}
    • {{/foreach}}
    From 299bb864d81f90318307d31074593747402dbd8b Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 3 Mar 2026 21:41:17 +0000 Subject: [PATCH 161/197] Don't create item containers for photos --- src/Content/Feature.php | 2 - src/Module/Profile/Photos.php | 75 ++----------------- view/lang/C/messages.po | 132 ++++++++++++++++------------------ 3 files changed, 66 insertions(+), 143 deletions(-) diff --git a/src/Content/Feature.php b/src/Content/Feature.php index 1e9211b567..1f3e1e79f2 100644 --- a/src/Content/Feature.php +++ b/src/Content/Feature.php @@ -17,7 +17,6 @@ class Feature public const COMMUNITY = 'community'; public const EXPLICIT_MENTIONS = 'explicit_mentions'; public const MEMBER_SINCE = 'profile_membersince'; - public const PHOTO_LOCATION = 'photo_location'; public const PUBLIC_CALENDAR = 'public_calendar'; public const SUMMARY = 'summary'; public const TAGCLOUD = 'tagadelic'; @@ -105,7 +104,6 @@ class Feature 'general' => [ $l10n->t('General Features'), //array('expire', $l10n->t('Content Expiration'), $l10n->t('Remove old posts/comments after a period of time')), - [self::PHOTO_LOCATION, $l10n->t('Photo Location'), $l10n->t("Photo metadata is normally stripped. This extracts the location \x28if present\x29 prior to stripping metadata and links it to a map."), false, $config->get('feature_lock', self::PHOTO_LOCATION, false)], [self::COMMUNITY, $l10n->t('Display the community in the navigation'), $l10n->t('If enabled, the community can be accessed via the navigation menu. Independent from this setting, the community timelines can always be accessed via the channels.'), true, $config->get('feature_lock', self::COMMUNITY, false)], ], diff --git a/src/Module/Profile/Photos.php b/src/Module/Profile/Photos.php index feb8834c5d..70ab405723 100644 --- a/src/Module/Profile/Photos.php +++ b/src/Module/Profile/Photos.php @@ -11,17 +11,14 @@ use Friendica\App\Arguments; use Friendica\App\BaseURL; use Friendica\App\Page; use Friendica\AppHelper; -use Friendica\Content\Feature; use Friendica\Content\Pager; use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\L10n; use Friendica\Core\Renderer; use Friendica\Core\Session\Capability\IHandleUserSessions; -use Friendica\Core\System; use Friendica\Database\Database; use Friendica\Event\ArrayFilterEvent; use Friendica\Model\Contact; -use Friendica\Model\Item; use Friendica\Model\Photo; use Friendica\Model\Profile; use Friendica\Module\Response; @@ -135,25 +132,6 @@ class Photos extends \Friendica\Module\BaseProfile $album = $album ?: $newalbum ?: DateTimeFormat::localNow('Y'); - /* - * We create a wall item for every photo, but we don't want to - * overwhelm the data stream with a hundred newly uploaded photos. - * So we will make the first photo uploaded to this album in the last several hours - * visible by default, the rest will become visible over time when and if - * they acquire comments, likes, dislikes, and/or tags - */ - - $r = Photo::selectToArray([], ['`album` = ? AND `uid` = ? AND `created` > ?', $album, $this->owner['uid'], DateTimeFormat::utc('now - 3 hours')]); - if (!$r || ($album == $this->t(Photo::PROFILE_PHOTOS))) { - $visible = 1; - } else { - $visible = 0; - } - - if (!empty($request['not_visible']) && $request['not_visible'] !== 'false') { - $visible = 0; - } - $hook_data = [ 'src' => '', 'filename' => '', @@ -218,7 +196,7 @@ class Photos extends \Friendica\Module\BaseProfile return; } - $this->logger->info('photos: upload: received file: ' . $filename . ' as ' . $src . ' ('. $type . ') ' . $filesize . ' bytes'); + $this->logger->info('photos: upload: received file: ' . $filename . ' as ' . $src . ' (' . $type . ') ' . $filesize . ' bytes'); $maximagesize = Strings::getBytesFromShorthand($this->config->get('system', 'maximagesize')); @@ -262,7 +240,6 @@ class Photos extends \Friendica\Module\BaseProfile return; } - $exif = $image->orient($src); @unlink($src); $max_length = $this->config->get('system', 'max_image_length'); @@ -279,53 +256,9 @@ class Photos extends \Friendica\Module\BaseProfile return; } - $uri = Item::newURI(); - - // Create item container - $lat = $lon = null; - if (!empty($exif['GPS']) && Feature::isEnabled($this->owner['uid'], Feature::PHOTO_LOCATION)) { - $lat = Photo::getGps($exif['GPS']['GPSLatitude'], $exif['GPS']['GPSLatitudeRef']); - $lon = Photo::getGps($exif['GPS']['GPSLongitude'], $exif['GPS']['GPSLongitudeRef']); - } - - $arr = []; - if ($lat && $lon) { - $arr['coord'] = $lat . ' ' . $lon; - } - - $arr['guid'] = System::createUUID(); - $arr['uid'] = $this->owner['uid']; - $arr['uri'] = $uri; - $arr['post-type'] = Item::PT_IMAGE; - $arr['wall'] = 1; - $arr['resource-id'] = $resource_id; - $arr['contact-id'] = $this->owner['id']; - $arr['owner-name'] = $this->owner['name']; - $arr['owner-link'] = $this->owner['url']; - $arr['owner-avatar'] = $this->owner['thumb']; - $arr['author-name'] = $this->owner['name']; - $arr['author-link'] = $this->owner['url']; - $arr['author-avatar'] = $this->owner['thumb']; - $arr['title'] = ''; - $arr['allow_cid'] = $str_contact_allow; - $arr['allow_gid'] = $str_circle_allow; - $arr['deny_cid'] = $str_contact_deny; - $arr['deny_gid'] = $str_circle_deny; - $arr['visible'] = $visible; - $arr['origin'] = 1; - - $arr['body'] = Images::getBBCodeByResource($resource_id, $this->owner['nickname'], $preview, $image->getExt()); - - $item_id = Item::insert($arr); // Update the photo albums cache Photo::clearAlbumCache($this->owner['uid']); - // addon uploaders should call "exit()" within the PHOTO_UPLOAD_END event - // if they do not wish to be redirected - $this->eventDispatcher->dispatch( - new ArrayFilterEvent(ArrayFilterEvent::PHOTO_UPLOAD_END, ['id' => $item_id]), - ); - $this->baseUrl->redirect($this->session->get('photo_return') ?? 'profile/' . $this->owner['nickname'] . '/photos'); } @@ -380,7 +313,7 @@ class Photos extends \Friendica\Module\BaseProfile $this->owner['uid'], Photo::DEFAULT, $pager->getStart(), - $pager->getItemsPerPage() + $pager->getItemsPerPage(), )); $photos = array_map(function ($photo) { @@ -400,7 +333,7 @@ class Photos extends \Friendica\Module\BaseProfile $tpl = Renderer::getMarkupTemplate('photos_head.tpl'); $this->page['htmlhead'] .= Renderer::replaceMacros($tpl, [ - '$ispublic' => $this->t('everybody') + '$ispublic' => $this->t('everybody'), ]); if ($albums = Photo::getAlbums($this->owner['uid'])) { @@ -410,7 +343,7 @@ class Photos extends \Friendica\Module\BaseProfile 'total' => $album['total'], 'url' => 'photos/' . $this->owner['nickname'] . '/album/' . bin2hex($album['album']), 'urlencode' => urlencode($album['album']), - 'bin2hex' => bin2hex($album['album']) + 'bin2hex' => bin2hex($album['album']), ]; }, $albums); diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index 70703677cf..f561bc9a67 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 2026.04-dev\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-03-02 21:37+0100\n" +"POT-Creation-Date: 2026-03-03 22:25+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -61,7 +61,7 @@ msgstr "" #: src/Module/Notifications/Notification.php:93 #: src/Module/OStatus/Subscribe.php:54 src/Module/Post/Edit.php:72 #: src/Module/Profile/Common.php:63 src/Module/Profile/Contacts.php:66 -#: src/Module/Profile/Photos.php:100 src/Module/Profile/Schedule.php:27 +#: src/Module/Profile/Photos.php:97 src/Module/Profile/Schedule.php:27 #: src/Module/Profile/Schedule.php:44 src/Module/Register.php:74 #: src/Module/Register.php:221 src/Module/Register.php:260 #: src/Module/Search/Directory.php:23 src/Module/Settings/Account.php:34 @@ -274,8 +274,8 @@ msgstr "" #: mod/message.php:188 mod/message.php:345 mod/photos.php:76 mod/photos.php:624 #: src/Content/Conversation.php:371 src/Module/Post/Edit.php:129 -#: src/Module/Profile/Photos.php:422 src/Module/Profile/Photos.php:442 -#: src/Module/Profile/Photos.php:445 +#: src/Module/Profile/Photos.php:355 src/Module/Profile/Photos.php:375 +#: src/Module/Profile/Photos.php:378 msgid "Upload photo" msgstr "" @@ -350,23 +350,23 @@ msgstr[1] "" #: src/Module/Profile/Common.php:50 src/Module/Profile/Common.php:59 #: src/Module/Profile/Contacts.php:52 src/Module/Profile/Contacts.php:60 #: src/Module/Profile/Conversations.php:81 src/Module/Profile/Media.php:58 -#: src/Module/Profile/Photos.php:91 src/Module/Profile/RemoteFollow.php:57 +#: src/Module/Profile/Photos.php:88 src/Module/Profile/RemoteFollow.php:57 #: src/Module/Register.php:282 msgid "User not found." msgstr "" #: mod/photos.php:73 src/Module/BaseProfile.php:53 -#: src/Module/Profile/Photos.php:419 +#: src/Module/Profile/Photos.php:352 msgid "Photo Albums" msgstr "" -#: mod/photos.php:74 src/Module/Profile/Photos.php:420 -#: src/Module/Profile/Photos.php:440 +#: mod/photos.php:74 src/Module/Profile/Photos.php:353 +#: src/Module/Profile/Photos.php:373 msgid "Recent Photos" msgstr "" #: mod/photos.php:88 src/Module/BaseSettings.php:60 -#: src/Module/Profile/Photos.php:403 +#: src/Module/Profile/Photos.php:336 msgid "everybody" msgstr "" @@ -391,7 +391,7 @@ msgid "Failed to delete the photo." msgstr "" #: mod/photos.php:332 src/Module/Conversation/Community.php:150 -#: src/Module/Directory.php:34 src/Module/Profile/Photos.php:337 +#: src/Module/Directory.php:34 src/Module/Profile/Photos.php:270 #: src/Module/Search/Index.php:50 msgid "Public access denied." msgstr "" @@ -478,7 +478,7 @@ msgstr "" msgid "Show Oldest First" msgstr "" -#: mod/photos.php:609 src/Module/Profile/Photos.php:390 +#: mod/photos.php:609 src/Module/Profile/Photos.php:323 msgid "View Photo" msgstr "" @@ -1596,189 +1596,181 @@ msgstr "" msgid "Favourite Posts" msgstr "" -#: src/Content/Feature.php:106 +#: src/Content/Feature.php:105 msgid "General Features" msgstr "" -#: src/Content/Feature.php:108 -msgid "Photo Location" -msgstr "" - -#: src/Content/Feature.php:108 -msgid "Photo metadata is normally stripped. This extracts the location (if present) prior to stripping metadata and links it to a map." -msgstr "" - -#: src/Content/Feature.php:109 +#: src/Content/Feature.php:107 msgid "Display the community in the navigation" msgstr "" -#: src/Content/Feature.php:109 +#: src/Content/Feature.php:107 msgid "If enabled, the community can be accessed via the navigation menu. Independent from this setting, the community timelines can always be accessed via the channels." msgstr "" -#: src/Content/Feature.php:114 +#: src/Content/Feature.php:112 msgid "Post Composition Features" msgstr "" -#: src/Content/Feature.php:115 +#: src/Content/Feature.php:113 msgid "Explicit Mentions" msgstr "" -#: src/Content/Feature.php:115 +#: src/Content/Feature.php:113 msgid "Add explicit mentions to comment box for manual control over who gets mentioned in replies." msgstr "" -#: src/Content/Feature.php:116 +#: src/Content/Feature.php:114 msgid "Add an abstract from ActivityPub content warnings" msgstr "" -#: src/Content/Feature.php:116 +#: src/Content/Feature.php:114 msgid "Add an abstract when commenting on ActivityPub posts with a content warning. Abstracts are displayed as content warning on systems like Mastodon or Pleroma." msgstr "" -#: src/Content/Feature.php:121 +#: src/Content/Feature.php:119 msgid "Post/Comment Tools" msgstr "" -#: src/Content/Feature.php:122 +#: src/Content/Feature.php:120 msgid "Post Categories" msgstr "" -#: src/Content/Feature.php:122 +#: src/Content/Feature.php:120 msgid "Add categories to your posts" msgstr "" -#: src/Content/Feature.php:123 src/Model/Profile.php:807 +#: src/Content/Feature.php:121 src/Model/Profile.php:807 #: src/Module/Admin/Summary.php:207 src/Module/Item/Compose.php:188 #: src/Module/Moderation/Report/Create.php:282 #: src/Module/Moderation/Summary.php:65 msgid "Summary" msgstr "" -#: src/Content/Feature.php:123 +#: src/Content/Feature.php:121 msgid "Add a summary, abstract or spoiler text to your posts" msgstr "" -#: src/Content/Feature.php:128 +#: src/Content/Feature.php:126 msgid "Network Widgets" msgstr "" -#: src/Content/Feature.php:129 src/Content/Widget.php:239 +#: src/Content/Feature.php:127 src/Content/Widget.php:239 #: src/Model/Circle.php:587 src/Module/Circle.php:132 #: src/Module/Contact.php:385 src/Module/Welcome.php:63 msgid "Circles" msgstr "" -#: src/Content/Feature.php:129 +#: src/Content/Feature.php:127 msgid "Display posts that have been created by accounts of the selected circle." msgstr "" -#: src/Content/Feature.php:130 src/Content/GroupManager.php:131 +#: src/Content/Feature.php:128 src/Content/GroupManager.php:131 #: src/Content/Nav.php:275 src/Content/Text/HTML.php:877 #: src/Content/Widget.php:564 src/Model/User.php:1400 msgid "Groups" msgstr "" -#: src/Content/Feature.php:130 +#: src/Content/Feature.php:128 msgid "Display posts that have been distributed by the selected group." msgstr "" -#: src/Content/Feature.php:131 src/Content/Widget.php:533 +#: src/Content/Feature.php:129 src/Content/Widget.php:533 msgid "Archives" msgstr "" -#: src/Content/Feature.php:131 +#: src/Content/Feature.php:129 msgid "Display an archive where posts can be selected by month and year." msgstr "" -#: src/Content/Feature.php:132 src/Content/Widget.php:312 +#: src/Content/Feature.php:130 src/Content/Widget.php:312 msgid "Protocols" msgstr "" -#: src/Content/Feature.php:132 +#: src/Content/Feature.php:130 msgid "Display posts with the selected protocols." msgstr "" -#: src/Content/Feature.php:133 src/Content/Widget.php:570 +#: src/Content/Feature.php:131 src/Content/Widget.php:570 #: src/Module/Settings/Account.php:391 msgid "Account Types" msgstr "" -#: src/Content/Feature.php:133 +#: src/Content/Feature.php:131 msgid "Display posts done by accounts with the selected account type." msgstr "" -#: src/Content/Feature.php:134 src/Content/Widget.php:632 +#: src/Content/Feature.php:132 src/Content/Widget.php:632 #: src/Module/Admin/Site.php:474 src/Module/BaseSettings.php:113 #: src/Module/Settings/Channels.php:224 src/Module/Settings/Display.php:433 msgid "Channels" msgstr "" -#: src/Content/Feature.php:134 +#: src/Content/Feature.php:132 msgid "Display posts in the system channels and user defined channels." msgstr "" -#: src/Content/Feature.php:135 src/Content/Widget/SavedSearches.php:46 +#: src/Content/Feature.php:133 src/Content/Widget/SavedSearches.php:46 msgid "Saved Searches" msgstr "" -#: src/Content/Feature.php:135 +#: src/Content/Feature.php:133 msgid "Display posts that contain subscribed hashtags." msgstr "" -#: src/Content/Feature.php:136 src/Content/Widget.php:342 +#: src/Content/Feature.php:134 src/Content/Widget.php:342 msgid "Saved Folders" msgstr "" -#: src/Content/Feature.php:136 +#: src/Content/Feature.php:134 msgid "Display a list of folders in which posts are stored." msgstr "" -#: src/Content/Feature.php:137 src/Module/Conversation/Timeline.php:188 +#: src/Content/Feature.php:135 src/Module/Conversation/Timeline.php:188 msgid "Own Contacts" msgstr "" -#: src/Content/Feature.php:137 +#: src/Content/Feature.php:135 msgid "Include or exclude posts from subscribed accounts. This widget is not visible on all channels." msgstr "" -#: src/Content/Feature.php:138 src/Content/Widget/TrendingTags.php:39 +#: src/Content/Feature.php:136 src/Content/Widget/TrendingTags.php:39 msgid "Trending Tags" msgstr "" -#: src/Content/Feature.php:138 +#: src/Content/Feature.php:136 msgid "Display a list of the most popular tags in recent public posts." msgstr "" -#: src/Content/Feature.php:143 +#: src/Content/Feature.php:141 msgid "Advanced Profile Settings" msgstr "" -#: src/Content/Feature.php:144 +#: src/Content/Feature.php:142 msgid "Tag Cloud" msgstr "" -#: src/Content/Feature.php:144 +#: src/Content/Feature.php:142 msgid "Provide a personal tag cloud on your profile page" msgstr "" -#: src/Content/Feature.php:145 +#: src/Content/Feature.php:143 msgid "Display Membership Date" msgstr "" -#: src/Content/Feature.php:145 +#: src/Content/Feature.php:143 msgid "Display membership date in profile" msgstr "" -#: src/Content/Feature.php:150 +#: src/Content/Feature.php:148 msgid "Advanced Calendar Settings" msgstr "" -#: src/Content/Feature.php:151 +#: src/Content/Feature.php:149 msgid "Allow anonymous access to your calendar" msgstr "" -#: src/Content/Feature.php:151 +#: src/Content/Feature.php:149 msgid "Allows anonymous visitors to consult your calendar and your public events. Contact birthday events are private to you." msgstr "" @@ -7312,12 +7304,12 @@ msgid "File upload failed." msgstr "" #: src/Module/Media/Photo/Upload.php:136 src/Module/Media/Photo/Upload.php:137 -#: src/Module/Profile/Photos.php:255 +#: src/Module/Profile/Photos.php:233 #: src/Module/Settings/Profile/Photo/Index.php:53 msgid "Unable to process image." msgstr "" -#: src/Module/Media/Photo/Upload.php:162 src/Module/Profile/Photos.php:278 +#: src/Module/Media/Photo/Upload.php:162 src/Module/Profile/Photos.php:255 #: src/Module/Settings/Profile/Photo/Index.php:80 msgid "Image upload failed." msgstr "" @@ -8580,30 +8572,30 @@ msgstr "" msgid "Personal notes are visible only by yourself." msgstr "" -#: src/Module/Profile/Photos.php:192 src/Module/Profile/Photos.php:195 -#: src/Module/Profile/Photos.php:226 +#: src/Module/Profile/Photos.php:170 src/Module/Profile/Photos.php:173 +#: src/Module/Profile/Photos.php:204 #: src/Module/Settings/Profile/Photo/Index.php:44 #, php-format msgid "Image exceeds size limit of %s" msgstr "" -#: src/Module/Profile/Photos.php:198 +#: src/Module/Profile/Photos.php:176 msgid "Image upload didn't complete, please try again" msgstr "" -#: src/Module/Profile/Photos.php:201 +#: src/Module/Profile/Photos.php:179 msgid "Image file is missing" msgstr "" -#: src/Module/Profile/Photos.php:206 +#: src/Module/Profile/Photos.php:184 msgid "Server can't accept new file upload at this time, please contact your administrator" msgstr "" -#: src/Module/Profile/Photos.php:237 +#: src/Module/Profile/Photos.php:215 msgid "Image file is empty." msgstr "" -#: src/Module/Profile/Photos.php:396 +#: src/Module/Profile/Photos.php:329 msgid "View Album" msgstr "" From 494d919c25940651885c0bcbfb31db9a97ef32ce Mon Sep 17 00:00:00 2001 From: "Marcus F." Date: Sun, 22 Feb 2026 17:19:18 +0100 Subject: [PATCH 162/197] Move profile edit to vcard --- src/Model/Profile.php | 7 +- src/Module/Profile/Profile.php | 6 +- view/global.css | 4 + view/lang/C/messages.po | 84 ++++++++++----------- view/templates/profile/profile.tpl | 5 -- view/theme/frio/css/style.css | 2 +- view/theme/frio/templates/profile/vcard.tpl | 12 ++- view/theme/vier/templates/profile/vcard.tpl | 8 ++ 8 files changed, 72 insertions(+), 56 deletions(-) diff --git a/src/Model/Profile.php b/src/Model/Profile.php index f1071ee4a8..e8931b2ad8 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -452,7 +452,12 @@ class Profile $tpl = Renderer::getMarkupTemplate('profile/vcard.tpl'); $o .= Renderer::replaceMacros($tpl, [ - '$profile' => $p, + '$is_owner' => DI::userSession()->getLocalUserId() == $profile['uid'], + '$profile' => $p, + '$edit_profile_link' => [ + 'url' => 'settings/profile', + 'text' => DI::l10n()->t('Edit profile'), + ], '$picture_dest_url' => $picture_dest_url, '$change_profile_picture_text' => $change_profile_picture_text, '$xmpp' => $xmpp, diff --git a/src/Module/Profile/Profile.php b/src/Module/Profile/Profile.php index a8798deeec..297f3ebb7d 100644 --- a/src/Module/Profile/Profile.php +++ b/src/Module/Profile/Profile.php @@ -289,11 +289,7 @@ class Profile extends BaseProfile '$custom_fields' => $custom_fields, '$profile' => $profile, '$homepage_verified' => $this->l10n->t('This website has been verified to belong to the same person.'), - '$edit_link' => [ - 'url' => 'settings/profile', $this->t('Edit profile'), - 'label' => $this->t('Edit profile'), - ], - '$viewas_link' => [ + '$viewas_link' => [ 'url' => $this->args->getQueryString() . '#viewas', 'label' => $this->t('View as'), ], diff --git a/view/global.css b/view/global.css index 573c62be64..5dcb6fcfa6 100644 --- a/view/global.css +++ b/view/global.css @@ -899,3 +899,7 @@ a:has(img.has-alt-description)::after { #profile-page .profile-entry a { word-break: break-all; } + +.edit-profile-link-wrapper { + text-align: center; +} diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index f561bc9a67..ae944ad5a4 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 2026.04-dev\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-03-03 22:25+0000\n" +"POT-Creation-Date: 2026-03-04 20:06+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -1311,7 +1311,7 @@ msgstr "" #: src/Content/Conversation.php:429 src/Content/Item.php:442 #: src/Content/Widget/VCard.php:120 src/Model/Contact.php:1307 -#: src/Model/Profile.php:467 src/Module/Admin/Logs/View.php:79 +#: src/Model/Profile.php:472 src/Module/Admin/Logs/View.php:79 #: src/Module/Post/Edit.php:181 msgid "Message" msgstr "" @@ -1640,7 +1640,7 @@ msgstr "" msgid "Add categories to your posts" msgstr "" -#: src/Content/Feature.php:121 src/Model/Profile.php:807 +#: src/Content/Feature.php:121 src/Model/Profile.php:812 #: src/Module/Admin/Summary.php:207 src/Module/Item/Compose.php:188 #: src/Module/Moderation/Report/Create.php:282 #: src/Module/Moderation/Summary.php:65 @@ -2467,18 +2467,18 @@ msgstr "" msgid "Location:" msgstr "" -#: src/Content/Widget/VCard.php:114 src/Model/Profile.php:474 +#: src/Content/Widget/VCard.php:114 src/Model/Profile.php:479 #: src/Module/Notifications/Introductions.php:201 msgid "Network:" msgstr "" -#: src/Content/Widget/VCard.php:116 src/Model/Profile.php:461 +#: src/Content/Widget/VCard.php:116 src/Model/Profile.php:466 #: src/Module/Contact/Profile.php:529 msgid "Follow" msgstr "" #: src/Content/Widget/VCard.php:118 src/Model/Contact.php:1297 -#: src/Model/Contact.php:1309 src/Model/Profile.php:463 +#: src/Model/Contact.php:1309 src/Model/Profile.php:468 #: src/Module/Contact/Profile.php:521 msgid "Unfollow" msgstr "" @@ -3444,115 +3444,119 @@ msgstr "" msgid "Joined:" msgstr "" -#: src/Model/Profile.php:465 +#: src/Model/Profile.php:459 +msgid "Edit profile" +msgstr "" + +#: src/Model/Profile.php:470 msgid "Atom feed" msgstr "" -#: src/Model/Profile.php:472 src/Module/Profile/Profile.php:291 +#: src/Model/Profile.php:477 src/Module/Profile/Profile.php:291 msgid "This website has been verified to belong to the same person." msgstr "" -#: src/Model/Profile.php:593 src/Model/Profile.php:673 +#: src/Model/Profile.php:598 src/Model/Profile.php:678 msgid "[today]" msgstr "" -#: src/Model/Profile.php:602 +#: src/Model/Profile.php:607 msgid "Birthday Reminders" msgstr "" -#: src/Model/Profile.php:603 +#: src/Model/Profile.php:608 msgid "Birthdays this week:" msgstr "" -#: src/Model/Profile.php:660 +#: src/Model/Profile.php:665 msgid "[No description]" msgstr "" -#: src/Model/Profile.php:686 +#: src/Model/Profile.php:691 msgid "Event Reminders" msgstr "" -#: src/Model/Profile.php:687 +#: src/Model/Profile.php:692 msgid "Upcoming events the next 7 days:" msgstr "" -#: src/Model/Profile.php:797 +#: src/Model/Profile.php:802 msgid "Hometown:" msgstr "" -#: src/Model/Profile.php:798 +#: src/Model/Profile.php:803 msgid "Marital Status:" msgstr "" -#: src/Model/Profile.php:799 +#: src/Model/Profile.php:804 msgid "With:" msgstr "" -#: src/Model/Profile.php:800 +#: src/Model/Profile.php:805 msgid "Since:" msgstr "" -#: src/Model/Profile.php:801 +#: src/Model/Profile.php:806 msgid "Sexual Preference:" msgstr "" -#: src/Model/Profile.php:802 +#: src/Model/Profile.php:807 msgid "Political Views:" msgstr "" -#: src/Model/Profile.php:803 +#: src/Model/Profile.php:808 msgid "Religious Views:" msgstr "" -#: src/Model/Profile.php:804 +#: src/Model/Profile.php:809 msgid "Likes:" msgstr "" -#: src/Model/Profile.php:805 +#: src/Model/Profile.php:810 msgid "Dislikes:" msgstr "" -#: src/Model/Profile.php:806 +#: src/Model/Profile.php:811 msgid "Title/Description:" msgstr "" -#: src/Model/Profile.php:808 +#: src/Model/Profile.php:813 msgid "Musical interests" msgstr "" -#: src/Model/Profile.php:809 +#: src/Model/Profile.php:814 msgid "Books, literature" msgstr "" -#: src/Model/Profile.php:810 +#: src/Model/Profile.php:815 msgid "Television" msgstr "" -#: src/Model/Profile.php:811 +#: src/Model/Profile.php:816 msgid "Film/dance/culture/entertainment" msgstr "" -#: src/Model/Profile.php:812 +#: src/Model/Profile.php:817 msgid "Hobbies/Interests" msgstr "" -#: src/Model/Profile.php:813 +#: src/Model/Profile.php:818 msgid "Love/romance" msgstr "" -#: src/Model/Profile.php:814 +#: src/Model/Profile.php:819 msgid "Work/employment" msgstr "" -#: src/Model/Profile.php:815 +#: src/Model/Profile.php:820 msgid "School/education" msgstr "" -#: src/Model/Profile.php:816 +#: src/Model/Profile.php:821 msgid "Contact information and Social Networks" msgstr "" -#: src/Model/Profile.php:864 +#: src/Model/Profile.php:869 #, php-format msgid "Responsible account: %s" msgstr "" @@ -8550,19 +8554,19 @@ msgstr "" msgid "No contacts." msgstr "" -#: src/Module/Profile/Conversations.php:96 src/Module/Profile/Profile.php:361 +#: src/Module/Profile/Conversations.php:96 src/Module/Profile/Profile.php:357 #: src/Protocol/Feed.php:1105 #, php-format msgid "%s's posts" msgstr "" -#: src/Module/Profile/Conversations.php:97 src/Module/Profile/Profile.php:362 +#: src/Module/Profile/Conversations.php:97 src/Module/Profile/Profile.php:358 #: src/Protocol/Feed.php:1108 #, php-format msgid "%s's comments" msgstr "" -#: src/Module/Profile/Conversations.php:98 src/Module/Profile/Profile.php:363 +#: src/Module/Profile/Conversations.php:98 src/Module/Profile/Profile.php:359 #: src/Protocol/Feed.php:1101 #, php-format msgid "%s's timeline" @@ -8651,11 +8655,7 @@ msgstr "" msgid "View as selected profile" msgstr "" -#: src/Module/Profile/Profile.php:293 src/Module/Profile/Profile.php:294 -msgid "Edit profile" -msgstr "" - -#: src/Module/Profile/Profile.php:298 +#: src/Module/Profile/Profile.php:294 msgid "View as" msgstr "" diff --git a/view/templates/profile/profile.tpl b/view/templates/profile/profile.tpl index e1f94b80ad..5f417cdc67 100644 --- a/view/templates/profile/profile.tpl +++ b/view/templates/profile/profile.tpl @@ -21,11 +21,6 @@  {{$viewas_link.label}} -
  • - -  {{$edit_link.label}} - -
{{/if}} diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index 64fd0fe99c..d02607685d 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -1292,7 +1292,7 @@ aside .vcard .fn { } aside .vcard .p-addr { font-style: italic; - padding-bottom: 2px; + padding-bottom: 7px; text-align: center; word-wrap: break-word; } diff --git a/view/theme/frio/templates/profile/vcard.tpl b/view/theme/frio/templates/profile/vcard.tpl index 5ebba33d2b..5773dd5515 100644 --- a/view/theme/frio/templates/profile/vcard.tpl +++ b/view/theme/frio/templates/profile/vcard.tpl @@ -5,10 +5,11 @@ * SPDX-License-Identifier: AGPL-3.0-or-later *}}
+
{{$profile.name}} - {{if $change_profile_picture_text }} + {{if $is_owner }}
{{$change_profile_picture_text}}
{{/if}}
@@ -32,7 +33,14 @@

{{$profile.name}}

- {{if $profile.addr}}
{{include file="sub/punct_wrap.tpl" text=$profile.addr}}
+ {{if $profile.addr}}
{{include file="sub/punct_wrap.tpl" text=$profile.addr}}
{{/if}} + {{if $is_owner }} + {{/if}} {{if $profile.about}}
{{$profile.about nofilter}}
{{/if}} diff --git a/view/theme/vier/templates/profile/vcard.tpl b/view/theme/vier/templates/profile/vcard.tpl index ac09607bc2..1748438dd7 100644 --- a/view/theme/vier/templates/profile/vcard.tpl +++ b/view/theme/vier/templates/profile/vcard.tpl @@ -23,6 +23,14 @@ {{if $account_type}}{{/if}} {{if $profile.network_link}}
{{$network}}
{{$profile.network_link nofilter}}
{{/if}} + {{if $is_owner }} + + {{/if}} {{if $location}}
{{$location}}
From 6e71306e9ba8b21dbe61034f7dccdf3f03043a60 Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 4 Mar 2026 20:15:03 +0000 Subject: [PATCH 163/197] update rector and phpstan --- composer.lock | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/composer.lock b/composer.lock index 4fba462ad5..7a3ad4bc56 100644 --- a/composer.lock +++ b/composer.lock @@ -7395,11 +7395,11 @@ }, { "name": "phpstan/phpstan", - "version": "2.1.39", + "version": "2.1.40", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c6f73a2af4cbcd99c931d0fb8f08548cc0fa8224", - "reference": "c6f73a2af4cbcd99c931d0fb8f08548cc0fa8224", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9b2c7aeb83a75d8680ea5e7c9b7fca88052b766b", + "reference": "9b2c7aeb83a75d8680ea5e7c9b7fca88052b766b", "shasum": "" }, "require": { @@ -7444,7 +7444,7 @@ "type": "github" } ], - "time": "2026-02-11T14:48:56+00:00" + "time": "2026-02-23T15:04:35+00:00" }, { "name": "phpstan/phpstan-strict-rules", @@ -8455,21 +8455,21 @@ }, { "name": "rector/rector", - "version": "2.2.7", + "version": "2.3.8", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", - "reference": "022038537838bc8a4e526af86c2d6e38eaeff7ef" + "reference": "bbd37aedd8df749916cffa2a947cfc4714d1ba2c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/022038537838bc8a4e526af86c2d6e38eaeff7ef", - "reference": "022038537838bc8a4e526af86c2d6e38eaeff7ef", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/bbd37aedd8df749916cffa2a947cfc4714d1ba2c", + "reference": "bbd37aedd8df749916cffa2a947cfc4714d1ba2c", "shasum": "" }, "require": { "php": "^7.4|^8.0", - "phpstan/phpstan": "^2.1.26" + "phpstan/phpstan": "^2.1.38" }, "conflict": { "rector/rector-doctrine": "*", @@ -8503,7 +8503,7 @@ ], "support": { "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/2.2.7" + "source": "https://github.com/rectorphp/rector/tree/2.3.8" }, "funding": [ { @@ -8511,7 +8511,7 @@ "type": "github" } ], - "time": "2025-10-29T15:46:12+00:00" + "time": "2026-02-22T09:45:50+00:00" }, { "name": "sebastian/cli-parser", From 6b782ba617706b951fe659638cf320c0103e1047 Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 4 Mar 2026 20:20:25 +0000 Subject: [PATCH 164/197] update downgrade level to php 8.2 --- .rector.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.rector.php b/.rector.php index cea3607ff8..e41780c96c 100644 --- a/.rector.php +++ b/.rector.php @@ -27,6 +27,6 @@ return \Rector\Config\RectorConfig::configure() ]) ->withSets([ \Rector\Set\ValueObject\LevelSetList::UP_TO_PHP_55, - \Rector\Set\ValueObject\DowngradeLevelSetList::DOWN_TO_PHP_74, + \Rector\Set\ValueObject\DowngradeLevelSetList::DOWN_TO_PHP_82, ]) ; From dc30924759bda289763673475fd5e4f2e0dd67c1 Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 4 Mar 2026 21:23:50 +0000 Subject: [PATCH 165/197] update rector for PHP 7.0 --- .rector.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.rector.php b/.rector.php index e41780c96c..5a36975c70 100644 --- a/.rector.php +++ b/.rector.php @@ -18,15 +18,15 @@ return \Rector\Config\RectorConfig::configure() ]) ->withIndent("\t", 4) ->withPhpVersion(70400) - ->withPhpLevel(15) + ->withPhpLevel(36) // ->withTypeCoverageLevel(0) // ->withDeadCodeLevel(0) // ->withCodeQualityLevel(0) - ->withRules([ - \Rector\Php71\Rector\List_\ListToArrayDestructRector::class, - ]) ->withSets([ - \Rector\Set\ValueObject\LevelSetList::UP_TO_PHP_55, + \Rector\Set\ValueObject\LevelSetList::UP_TO_PHP_70, \Rector\Set\ValueObject\DowngradeLevelSetList::DOWN_TO_PHP_82, ]) + ->withSkip([ + \Rector\Php56\Rector\FuncCall\PowToExpRector::class, + ]) ; From 47ef2741767a90df32dfd4cf4189c0254157e56d Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 4 Mar 2026 21:26:00 +0000 Subject: [PATCH 166/197] Update codebase to PHP 7.0 --- mod/photos.php | 2 +- src/Content/Widget/TagCloud.php | 5 +---- src/Core/Cache/Type/ArrayCache.php | 5 +---- src/Core/Lock/Type/CacheLock.php | 2 +- src/Core/Lock/Type/DatabaseLock.php | 2 +- src/Core/Logger/Handler/ErrorHandler.php | 2 +- src/Core/PConfig/Type/JitPConfig.php | 2 +- src/Core/PConfig/Type/PreloadPConfig.php | 2 +- src/Core/Worker.php | 4 ++-- src/Module/Notifications/Ping.php | 6 +----- src/Module/Photo.php | 2 +- src/Navigation/Notifications/Repository/Notify.php | 2 +- src/Network/HTTPClient/Response/CurlResult.php | 6 +----- src/Network/Probe.php | 4 ++-- src/Object/Image.php | 2 +- src/Security/OAuth1/OAuthRequest.php | 2 +- src/Util/Emailer.php | 8 ++++---- src/Util/XML.php | 4 ++-- 18 files changed, 24 insertions(+), 38 deletions(-) diff --git a/mod/photos.php b/mod/photos.php index 4cb8f46c1b..288aeda535 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -603,7 +603,7 @@ function photos_content() $photos[] = [ 'id' => $rr['id'], - 'twist' => ' ' . ($twist ? 'rotleft' : 'rotright') . rand(2, 4), + 'twist' => ' ' . ($twist ? 'rotleft' : 'rotright') . random_int(2, 4), 'link' => 'photos/' . $user['nickname'] . '/image/' . $rr['resource-id'] . ($order_field === 'created' ? '?order=created' : ''), 'title' => DI::l10n()->t('View Photo'), diff --git a/src/Content/Widget/TagCloud.php b/src/Content/Widget/TagCloud.php index c285b3cb83..c2ba1fd1ed 100644 --- a/src/Content/Widget/TagCloud.php +++ b/src/Content/Widget/TagCloud.php @@ -150,9 +150,6 @@ class TagCloud */ private static function tagsSort($a, $b) { - if (strtolower($a[0]) == strtolower($b[0])) { - return 0; - } - return ((strtolower($a[0]) < strtolower($b[0])) ? -1 : 1); + return strtolower($a[0]) <=> strtolower($b[0]); } } diff --git a/src/Core/Cache/Type/ArrayCache.php b/src/Core/Cache/Type/ArrayCache.php index 148210b4e8..74368b29c4 100644 --- a/src/Core/Cache/Type/ArrayCache.php +++ b/src/Core/Cache/Type/ArrayCache.php @@ -34,10 +34,7 @@ class ArrayCache extends AbstractCache implements ICanCacheInMemory */ public function get(string $key) { - if (isset($this->cachedData[$key])) { - return $this->cachedData[$key]; - } - return null; + return $this->cachedData[$key] ?? null; } /** diff --git a/src/Core/Lock/Type/CacheLock.php b/src/Core/Lock/Type/CacheLock.php index c7fa75e021..cb61a55b39 100644 --- a/src/Core/Lock/Type/CacheLock.php +++ b/src/Core/Lock/Type/CacheLock.php @@ -66,7 +66,7 @@ class CacheLock extends AbstractLock } if (!$got_lock && ($timeout > 0)) { - usleep(rand(10000, 200000)); + usleep(random_int(10000, 200000)); } } while (!$got_lock && ((time() - $start) < $timeout)); } catch (CachePersistenceException $exception) { diff --git a/src/Core/Lock/Type/DatabaseLock.php b/src/Core/Lock/Type/DatabaseLock.php index d05871689c..0bc13c9420 100644 --- a/src/Core/Lock/Type/DatabaseLock.php +++ b/src/Core/Lock/Type/DatabaseLock.php @@ -82,7 +82,7 @@ class DatabaseLock extends AbstractLock $this->dba->unlock(); if (!$got_lock && ($timeout > 0)) { - usleep(rand(100000, 2000000)); + usleep(random_int(100000, 2000000)); } } while (!$got_lock && ((time() - $start) < $timeout)); } catch (\Exception $exception) { diff --git a/src/Core/Logger/Handler/ErrorHandler.php b/src/Core/Logger/Handler/ErrorHandler.php index 6d47674581..15cff99e24 100644 --- a/src/Core/Logger/Handler/ErrorHandler.php +++ b/src/Core/Logger/Handler/ErrorHandler.php @@ -160,7 +160,7 @@ class ErrorHandler register_shutdown_function([$this, 'handleFatalError']); $this->reservedMemory = str_repeat(' ', 1024 * $reservedMemorySize); - $this->fatalLevel = null === $level ? LogLevel::ALERT : $level; + $this->fatalLevel = $level ?? LogLevel::ALERT; $this->hasFatalErrorHandler = true; return $this; diff --git a/src/Core/PConfig/Type/JitPConfig.php b/src/Core/PConfig/Type/JitPConfig.php index 3234446c5b..c11ab2b73e 100644 --- a/src/Core/PConfig/Type/JitPConfig.php +++ b/src/Core/PConfig/Type/JitPConfig.php @@ -86,7 +86,7 @@ class JitPConfig extends AbstractPConfigValues // use the config cache for return $result = $this->configCache->get($uid, $cat, $key); - return (isset($result)) ? $result : $default_value; + return $result ?? $default_value; } /** diff --git a/src/Core/PConfig/Type/PreloadPConfig.php b/src/Core/PConfig/Type/PreloadPConfig.php index 1aa95d4a18..e21d52927b 100644 --- a/src/Core/PConfig/Type/PreloadPConfig.php +++ b/src/Core/PConfig/Type/PreloadPConfig.php @@ -83,7 +83,7 @@ class PreloadPConfig extends AbstractPConfigValues // use the config cache for return $result = $this->configCache->get($uid, $cat, $key); - return (isset($result)) ? $result : $default_value; + return $result ?? $default_value; } /** diff --git a/src/Core/Worker.php b/src/Core/Worker.php index 3454b12219..4aeed1dfb8 100644 --- a/src/Core/Worker.php +++ b/src/Core/Worker.php @@ -1374,7 +1374,7 @@ class Worker $new_retrial = $queue['retrial'] + 1; $total = 0; for ($retrial = 0; $retrial <= $max_level + 1; ++$retrial) { - $delay = (($retrial + 3) ** 4) + (rand(1, 30) * ($retrial + 1)); + $delay = (($retrial + 3) ** 4) + (random_int(1, 30) * ($retrial + 1)); $total += $delay; if (($total < $retrial_time) && ($retrial > $queue['retrial'])) { $new_retrial = $retrial; @@ -1427,7 +1427,7 @@ class Worker } // Calculate the delay until the next trial - $delay = (($new_retrial + 2) ** 4) + (rand(1, 30) * ($new_retrial)); + $delay = (($new_retrial + 2) ** 4) + (random_int(1, 30) * ($new_retrial)); $next = DateTimeFormat::utc('now + ' . $delay . ' seconds'); if (($priority < self::PRIORITY_MEDIUM) && ($new_retrial > 3)) { diff --git a/src/Module/Notifications/Ping.php b/src/Module/Notifications/Ping.php index 8e280ef0cb..5885b41a2e 100644 --- a/src/Module/Notifications/Ping.php +++ b/src/Module/Notifications/Ping.php @@ -227,11 +227,7 @@ class Ping extends BaseModule // Unseen messages are kept at the top if ($a['seen'] == $b['seen']) { - if ($a['timestamp'] == $b['timestamp']) { - return 0; - } else { - return $a['timestamp'] < $b['timestamp'] ? 1 : -1; - } + return $b['timestamp'] <=> $a['timestamp']; } else { return $a['seen'] ? 1 : -1; } diff --git a/src/Module/Photo.php b/src/Module/Photo.php index 0901d0c05d..d1ada02573 100644 --- a/src/Module/Photo.php +++ b/src/Module/Photo.php @@ -142,7 +142,7 @@ class Photo extends BaseApi throw new HTTPException\NotFoundException(); } - $cacheable = ($photo['allow_cid'] . $photo['allow_gid'] . $photo['deny_cid'] . $photo['deny_gid'] === '') && (isset($photo['cacheable']) ? $photo['cacheable'] : true); + $cacheable = ($photo['allow_cid'] . $photo['allow_gid'] . $photo['deny_cid'] . $photo['deny_gid'] === '') && ($photo['cacheable'] ?? true); $stamp = microtime(true); $imgdata = ''; diff --git a/src/Navigation/Notifications/Repository/Notify.php b/src/Navigation/Notifications/Repository/Notify.php index 1f3385a366..2a97573e8a 100644 --- a/src/Navigation/Notifications/Repository/Notify.php +++ b/src/Navigation/Notifications/Repository/Notify.php @@ -267,7 +267,7 @@ class Notify extends BaseRepository // with $params['show_in_notification_page'] == false, the notification isn't inserted into // the database, and an email is sent if applicable. // default, if not specified: true - $show_in_notification_page = isset($params['show_in_notification_page']) ? $params['show_in_notification_page'] : true; + $show_in_notification_page = $params['show_in_notification_page'] ?? true; $title = $params['item']['title'] ?? ''; $body = $params['item']['body'] ?? ''; diff --git a/src/Network/HTTPClient/Response/CurlResult.php b/src/Network/HTTPClient/Response/CurlResult.php index a38de01336..039f7d5619 100644 --- a/src/Network/HTTPClient/Response/CurlResult.php +++ b/src/Network/HTTPClient/Response/CurlResult.php @@ -266,11 +266,7 @@ class CurlResult implements ICanHandleHttpResponses $headers = $this->getHeaderArray(); - if (isset($headers[$header])) { - return $headers[$header]; - } - - return []; + return $headers[$header] ?? []; } /** {@inheritDoc} */ diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 3a292f8824..20f11a1e4d 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -1440,9 +1440,9 @@ class Probe // And put them together again $scheme = isset($parts['scheme']) ? $parts['scheme'] . '://' : ''; - $host = isset($parts['host']) ? $parts['host'] : ''; + $host = $parts['host'] ?? ''; $port = isset($parts['port']) ? ':' . $parts['port'] : ''; - $path = isset($parts['path']) ? $parts['path'] : ''; + $path = $parts['path'] ?? ''; $query = isset($parts['query']) ? '?' . $parts['query'] : ''; $fragment = isset($parts['fragment']) ? '#' . $parts['fragment'] : ''; diff --git a/src/Object/Image.php b/src/Object/Image.php index 1039f8ac1a..8d598e8ccb 100644 --- a/src/Object/Image.php +++ b/src/Object/Image.php @@ -473,7 +473,7 @@ class Image return; } - $ort = isset($exif['IFD0']['Orientation']) ? $exif['IFD0']['Orientation'] : 1; + $ort = $exif['IFD0']['Orientation'] ?? 1; switch ($ort) { case 1: // nothing diff --git a/src/Security/OAuth1/OAuthRequest.php b/src/Security/OAuth1/OAuthRequest.php index b3564d2d1b..283a1abace 100644 --- a/src/Security/OAuth1/OAuthRequest.php +++ b/src/Security/OAuth1/OAuthRequest.php @@ -139,7 +139,7 @@ class OAuthRequest public function get_parameter($name) { - return isset($this->parameters[$name]) ? $this->parameters[$name] : null; + return $this->parameters[$name] ?? null; } public function get_parameters() diff --git a/src/Util/Emailer.php b/src/Util/Emailer.php index 3ced3e8afc..e7313db272 100644 --- a/src/Util/Emailer.php +++ b/src/Util/Emailer.php @@ -158,10 +158,10 @@ class Emailer $messageSubject = Email::encodeHeader(html_entity_decode($email->getSubject(), ENT_QUOTES, 'UTF-8'), 'UTF-8'); // generate a mime boundary - $mimeBoundary = rand(0, 9) . '-' - . rand(100000000, 999999999) . '-' - . rand(100000000, 999999999) . '=:' - . rand(10000, 99999); + $mimeBoundary = random_int(0, 9) . '-' + . random_int(100000000, 999999999) . '-' + . random_int(100000000, 999999999) . '=:' + . random_int(10000, 99999); $messageHeader = $email->getAdditionalMailHeaderString(); if ($countMessageId === 0) { diff --git a/src/Util/XML.php b/src/Util/XML.php index 4c099fb78e..8e4df82d89 100644 --- a/src/Util/XML.php +++ b/src/Util/XML.php @@ -303,8 +303,8 @@ class XML $tag = $data['tag']; $type = $data['type']; $level = $data['level']; - $attributes = isset($data['attributes']) ? $data['attributes'] : null; - $value = isset($data['value']) ? $data['value'] : null; + $attributes = $data['attributes'] ?? null; + $value = $data['value'] ?? null; $result = []; $attributes_data = []; From df7e15d1df286fbeff2286544e7d191afaa32877 Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 4 Mar 2026 21:52:09 +0000 Subject: [PATCH 167/197] update rector config to PHP 7.4 --- .rector.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.rector.php b/.rector.php index 5a36975c70..fdfa43139e 100644 --- a/.rector.php +++ b/.rector.php @@ -18,15 +18,14 @@ return \Rector\Config\RectorConfig::configure() ]) ->withIndent("\t", 4) ->withPhpVersion(70400) - ->withPhpLevel(36) // ->withTypeCoverageLevel(0) // ->withDeadCodeLevel(0) // ->withCodeQualityLevel(0) ->withSets([ - \Rector\Set\ValueObject\LevelSetList::UP_TO_PHP_70, - \Rector\Set\ValueObject\DowngradeLevelSetList::DOWN_TO_PHP_82, + \Rector\Set\ValueObject\LevelSetList::UP_TO_PHP_74, ]) ->withSkip([ \Rector\Php56\Rector\FuncCall\PowToExpRector::class, + \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class, ]) ; From 64af3c6b8aa330561e7d41b2de9b602e99b0f3b1 Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 4 Mar 2026 21:52:35 +0000 Subject: [PATCH 168/197] refactor: update codebase to PHP 7.4 --- src/App.php | 2 +- src/Console/PhpToPo.php | 2 +- src/Contact/Avatar.php | 2 +- src/Content/Conversation.php | 16 ++++++++-------- src/Content/Item.php | 10 +++++----- src/Content/PageInfo.php | 2 +- src/Content/Text/BBCode.php | 14 +++++++------- src/Content/Text/HTML.php | 2 +- src/Content/Text/Plaintext.php | 6 +++--- src/Core/Logger/Factory/StreamLogger.php | 2 +- src/Core/Protocol.php | 2 +- src/Core/Storage/Repository/StorageManager.php | 2 +- src/Core/Worker.php | 2 +- src/Database/DBA.php | 4 +--- src/Database/Database.php | 4 +--- src/Database/PostUpdate.php | 4 ++-- src/Model/Contact.php | 16 ++++------------ src/Model/GServer.php | 2 +- src/Model/Post/Media.php | 4 ++-- src/Model/Profile.php | 2 +- src/Model/User.php | 2 +- src/Model/User/Cookie.php | 2 +- src/Module/Api/ApiResponse.php | 2 +- src/Module/Conversation/Network.php | 2 +- src/Module/Debug/Babel.php | 2 +- src/Module/Response.php | 10 +++++----- src/Module/User/Import.php | 4 ++-- src/Network/HTTPClient/Client/HttpClient.php | 2 +- src/Network/Probe.php | 4 ++-- src/Object/Api/Mastodon/Status.php | 3 +-- src/Object/Post.php | 2 +- src/Protocol/ActivityPub/Transmitter.php | 4 ++-- src/Protocol/DFRN.php | 2 +- src/Protocol/Diaspora.php | 2 +- src/Protocol/Feed.php | 2 +- src/Security/OAuth1/OAuthRequest.php | 2 +- src/Util/EMailer/MailBuilder.php | 2 +- src/Util/ParseUrl.php | 2 +- src/Util/Strings.php | 2 +- src/Util/Temporal.php | 2 +- static/routes.config.php | 6 +++--- view/theme/frio/php/default.php | 2 +- view/theme/frio/php/frio_boot.php | 4 ++-- 43 files changed, 77 insertions(+), 90 deletions(-) diff --git a/src/App.php b/src/App.php index e69a7c02ca..0212bbe909 100644 --- a/src/App.php +++ b/src/App.php @@ -616,7 +616,7 @@ class App /** @var Router $router */ $router = $this->container->create(Router::class); - $moduleClass = $moduleClass ?? $router->getModuleClass(); + $moduleClass ??= $router->getModuleClass(); $parameters = $router->getParameters(); $dice_profiler_threshold = $this->config->get('system', 'dice_profiler_threshold', 0); diff --git a/src/Console/PhpToPo.php b/src/Console/PhpToPo.php index d38b602680..c1ab617afd 100644 --- a/src/Console/PhpToPo.php +++ b/src/Console/PhpToPo.php @@ -214,7 +214,7 @@ HELP; private function startsWith($haystack, $needle) { // search backwards starting from haystack length characters from the end - return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== false; + return $needle === "" || strrpos($haystack, (string) $needle, -strlen($haystack)) !== false; } /** diff --git a/src/Contact/Avatar.php b/src/Contact/Avatar.php index 677ab8e048..0a1f6b40ee 100644 --- a/src/Contact/Avatar.php +++ b/src/Contact/Avatar.php @@ -215,7 +215,7 @@ class Avatar } $avatarpath = parse_url(self::baseUrl(), PHP_URL_PATH); - $pos = strpos($parts['path'], $avatarpath); + $pos = strpos($parts['path'], (string) $avatarpath); if ($pos !== 0) { return ''; } diff --git a/src/Content/Conversation.php b/src/Content/Conversation.php index a72c572e91..3b659a5e7a 100644 --- a/src/Content/Conversation.php +++ b/src/Content/Conversation.php @@ -315,15 +315,15 @@ class Conversation $this->profiler->startRecording('rendering'); $o = ''; - $x['allow_location'] = $x['allow_location'] ?? $user['allow_location']; - $x['default_location'] = $x['default_location'] ?? $user['default-location']; - $x['nickname'] = $x['nickname'] ?? $user['nickname']; + $x['allow_location'] ??= $user['allow_location']; + $x['default_location'] ??= $user['default-location']; + $x['nickname'] ??= $user['nickname']; $x['lockstate'] = $x['lockstate'] ?? ACL::getLockstateForUserId($user['uid']) ? 'lock' : 'unlock'; - $x['acl'] = $x['acl'] ?? ACL::getFullSelectorHTML($this->page, $user['uid'], true); - $x['bang'] = $x['bang'] ?? ''; - $x['visitor'] = $x['visitor'] ?? 'block'; - $x['is_owner'] = $x['is_owner'] ?? true; - $x['profile_uid'] = $x['profile_uid'] ?? $this->session->getLocalUserId(); + $x['acl'] ??= ACL::getFullSelectorHTML($this->page, $user['uid'], true); + $x['bang'] ??= ''; + $x['visitor'] ??= 'block'; + $x['is_owner'] ??= true; + $x['profile_uid'] ??= $this->session->getLocalUserId(); $geotag = !empty($x['allow_location']) ? Renderer::replaceMacros(Renderer::getMarkupTemplate('jot_geotag.tpl'), []) : ''; diff --git a/src/Content/Item.php b/src/Content/Item.php index afbc0e7124..5c6fabd342 100644 --- a/src/Content/Item.php +++ b/src/Content/Item.php @@ -945,11 +945,11 @@ class Item $post['direction'] = Conversation::PUSH; $post['received'] = DateTimeFormat::utcNow(); $post['origin'] = true; - $post['wall'] = $post['wall'] ?? true; - $post['guid'] = $post['guid'] ?? System::createUUID(); - $post['verb'] = $post['verb'] ?? Activity::POST; - $post['uri'] = $post['uri'] ?? ItemModel::newURI($post['guid']); - $post['thr-parent'] = $post['thr-parent'] ?? $post['uri']; + $post['wall'] ??= true; + $post['guid'] ??= System::createUUID(); + $post['verb'] ??= Activity::POST; + $post['uri'] ??= ItemModel::newURI($post['guid']); + $post['thr-parent'] ??= $post['uri']; if (empty($post['gravity'])) { $post['gravity'] = ($post['uri'] == $post['thr-parent']) ? ItemModel::GRAVITY_PARENT : ItemModel::GRAVITY_COMMENT; diff --git a/src/Content/PageInfo.php b/src/Content/PageInfo.php index a53c36b68c..dfa672024a 100644 --- a/src/Content/PageInfo.php +++ b/src/Content/PageInfo.php @@ -108,7 +108,7 @@ class PageInfo $data['type'] = 'link'; } - $data['title'] = $data['title'] ?? ''; + $data['title'] ??= ''; if ((($data['type'] != 'link') && ($data['type'] != 'video') && ($data['type'] != 'photo')) || ($data['title'] == $data['url'])) { return ''; diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index 6634e2202c..e31e215974 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -183,7 +183,7 @@ class BBCode $attach_data = self::getAttachmentData($match[0]); if (empty($attach_data['url'])) { return $match[0]; - } elseif (strpos(str_replace($match[0], '', $body), $attach_data['url']) !== false) { + } elseif (strpos(str_replace($match[0], '', $body), (string) $attach_data['url']) !== false) { return ''; } elseif (empty($attach_data['title']) || $no_link_desc) { return " \n[url]" . $attach_data['url'] . "[/url]\n"; @@ -245,12 +245,12 @@ class BBCode // Add text from attached media if (!empty($uri_id)) { foreach (Post\Media::getByURIId($uri_id) as $media) { - if (!empty($media['description']) && (stripos($text, $media['description']) === false)) { + if (!empty($media['description']) && (stripos($text, (string) $media['description']) === false)) { $text .= ' ' . $media['description']; } if (in_array($media['type'], [Post\Media::HTML, Post\Media::ACTIVITY])) { foreach (['name', 'author-name', 'publisher-name'] as $key) { - if (!empty($media[$key] && stripos($text, $media[$key]) === false)) { + if (!empty($media[$key] && stripos($text, (string) $media[$key]) === false)) { $text .= ' ' . $media[$key]; } } @@ -535,7 +535,7 @@ class BBCode } // If the link already is included in the post, don't add it again - if (!empty($data['url']) && strpos($data['text'], $data['url'])) { + if (!empty($data['url']) && strpos($data['text'], (string) $data['url'])) { DI::profiler()->stopRecording(); return $data['text'] . $data['after']; } @@ -812,8 +812,8 @@ class BBCode $attributes = self::extractShareAttributes($match[2]); $author_contact = Contact::getByURL($attributes['profile'], false, ['id', 'url', 'addr', 'name', 'micro']); - $author_contact['url'] = ($author_contact['url'] ?? $attributes['profile']); - $author_contact['addr'] = ($author_contact['addr'] ?? ''); + $author_contact['url'] ??= $attributes['profile']; + $author_contact['addr'] ??= ''; $attributes['author'] = ($author_contact['name'] ?? '') ?: $attributes['author']; $attributes['avatar'] = ($author_contact['micro'] ?? '') ?: $attributes['avatar']; @@ -1027,7 +1027,7 @@ class BBCode */ private static function expandLinksCallback(array $match): string { - if (($match[3] == '') || ($match[2] == $match[3]) || stristr($match[2], $match[3])) { + if (($match[3] == '') || ($match[2] == $match[3]) || stristr($match[2], (string) $match[3])) { return ($match[1] . '[url]' . $match[2] . '[/url]'); } else { return ($match[1] . $match[3] . ' [url]' . $match[2] . '[/url]'); diff --git a/src/Content/Text/HTML.php b/src/Content/Text/HTML.php index 3d789e7fa0..085613c3a2 100644 --- a/src/Content/Text/HTML.php +++ b/src/Content/Text/HTML.php @@ -660,7 +660,7 @@ class HTML if (!$compact && ($message != '')) { foreach ($urls as $id => $url) { - if ($url != '' && strpos($message, $url) === false) { + if ($url != '' && strpos($message, (string) $url) === false) { $message .= "\n" . $url . ' '; } } diff --git a/src/Content/Text/Plaintext.php b/src/Content/Text/Plaintext.php index 8a1b479937..96b2e5c159 100644 --- a/src/Content/Text/Plaintext.php +++ b/src/Content/Text/Plaintext.php @@ -170,8 +170,8 @@ class Plaintext // If the link is already contained in the post, then it needn't to be added again // But: if the link is beyond the limit, then it has to be added. - if (($link != '') && strstr($msg, $link)) { - $pos = strpos($msg, $link); + if (($link != '') && strstr($msg, (string) $link)) { + $pos = strpos($msg, (string) $link); // Will the text be shortened in the link? // Or is the link the last item in the post? @@ -200,7 +200,7 @@ class Plaintext $msg = str_replace(' ', ' ', $msg); } - if (!in_array($link, ['', $item['plink']]) && ($post['type'] != 'photo') && (strpos($complete_msg, $link) === false)) { + if (!in_array($link, ['', $item['plink']]) && ($post['type'] != 'photo') && (strpos($complete_msg, (string) $link) === false)) { $complete_msg .= "\n" . $link; } diff --git a/src/Core/Logger/Factory/StreamLogger.php b/src/Core/Logger/Factory/StreamLogger.php index 2e1265df3a..abb0af5608 100644 --- a/src/Core/Logger/Factory/StreamLogger.php +++ b/src/Core/Logger/Factory/StreamLogger.php @@ -44,7 +44,7 @@ class StreamLogger extends AbstractLoggerTypeFactory $fileSystem = new FileSystem(); - $logfile = $logfile ?? $config->get('system', 'logfile'); + $logfile ??= $config->get('system', 'logfile'); if (!@file_exists($logfile) || !@is_writable($logfile)) { throw new LoggerArgumentException(sprintf('%s is not a valid logfile', $logfile)); } diff --git a/src/Core/Protocol.php b/src/Core/Protocol.php index ef57c22f18..c41f696232 100644 --- a/src/Core/Protocol.php +++ b/src/Core/Protocol.php @@ -131,7 +131,7 @@ class Protocol return true; } - $protocol = $protocol ?? $contact['protocol']; + $protocol ??= $contact['protocol']; if ($protocol == self::DIASPORA) { $contact = Diaspora::sendShare($owner, $contact); diff --git a/src/Core/Storage/Repository/StorageManager.php b/src/Core/Storage/Repository/StorageManager.php index 36efa3a1bf..63d21d16db 100644 --- a/src/Core/Storage/Repository/StorageManager.php +++ b/src/Core/Storage/Repository/StorageManager.php @@ -240,7 +240,7 @@ class StorageManager */ public function isValidBackend(string $name = null, array $validBackends = null): bool { - $validBackends = $validBackends ?? array_merge( + $validBackends ??= array_merge( $this->validBackends, [ Type\SystemResource::getName(), diff --git a/src/Core/Worker.php b/src/Core/Worker.php index 4aeed1dfb8..fdbf9e7bb9 100644 --- a/src/Core/Worker.php +++ b/src/Core/Worker.php @@ -294,7 +294,7 @@ class Worker $file = realpath($file); - if (strpos($file, getcwd()) !== 0) { + if (strpos($file, (string) getcwd()) !== 0) { return false; } diff --git a/src/Database/DBA.php b/src/Database/DBA.php index c001384f99..6566181570 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -571,9 +571,7 @@ class DBA if (count($condition) < 1) { return ['1']; } - - reset($condition); - $first_key = key($condition); + $first_key = array_key_first($condition); if (is_int($first_key)) { // Already collapsed diff --git a/src/Database/Database.php b/src/Database/Database.php index b07cc1319e..8fc6bbc550 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -831,9 +831,7 @@ class Database if (empty($condition)) { return DBStructure::existsTable($table); } - - reset($condition); - $first_key = key($condition); + $first_key = array_key_first($condition); if (!is_int($first_key)) { $fields = [$first_key]; } diff --git a/src/Database/PostUpdate.php b/src/Database/PostUpdate.php index 031c2fec1d..52c3387253 100644 --- a/src/Database/PostUpdate.php +++ b/src/Database/PostUpdate.php @@ -357,7 +357,7 @@ class PostUpdate } while ($term = DBA::fetch($terms)) { - if (($term['type'] == Tag::MENTION) && !empty($term['url']) && !strstr($term['body'], $term['url'])) { + if (($term['type'] == Tag::MENTION) && !empty($term['url']) && !strstr($term['body'], (string) $term['url'])) { $condition = ['nurl' => Strings::normaliseLink($term['url']), 'uid' => 0, 'deleted' => false]; $contact = DBA::selectFirst('contact', ['url', 'alias'], $condition, ['order' => ['id']]); if (!DBA::isResult($contact)) { @@ -366,7 +366,7 @@ class PostUpdate $contact = DBA::selectFirst('contact', ['url', 'alias'], $condition, ['order' => ['id']]); } - if (DBA::isResult($contact) && (!strstr($term['body'], $contact['url']) && (empty($contact['alias']) || !strstr($term['body'], $contact['alias'])))) { + if (DBA::isResult($contact) && (!strstr($term['body'], (string) $contact['url']) && (empty($contact['alias']) || !strstr($term['body'], (string) $contact['alias'])))) { $term['type'] = Tag::IMPLICIT_MENTION; } } diff --git a/src/Model/Contact.php b/src/Model/Contact.php index 8226786303..c1ab7fa5fa 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -1506,17 +1506,13 @@ class Contact if ($data['network'] == Protocol::DIASPORA) { try { DI::dsprContact()->updateFromProbeArray($data); - } catch (NotFoundException $e) { - DI::logger()->notice($e->getMessage(), ['url' => $url, 'data' => $data]); - } catch (\InvalidArgumentException $e) { + } catch (NotFoundException|\InvalidArgumentException $e) { DI::logger()->notice($e->getMessage(), ['url' => $url, 'data' => $data]); } } elseif (!empty($data['networks'][Protocol::DIASPORA])) { try { DI::dsprContact()->updateFromProbeArray($data['networks'][Protocol::DIASPORA]); - } catch (NotFoundException $e) { - DI::logger()->notice($e->getMessage(), ['url' => $url, 'data' => $data['networks'][Protocol::DIASPORA]]); - } catch (\InvalidArgumentException $e) { + } catch (NotFoundException|\InvalidArgumentException $e) { DI::logger()->notice($e->getMessage(), ['url' => $url, 'data' => $data['networks'][Protocol::DIASPORA]]); } } @@ -2764,17 +2760,13 @@ class Contact if ($data['network'] == Protocol::DIASPORA) { try { DI::dsprContact()->updateFromProbeArray($data); - } catch (NotFoundException $e) { - DI::logger()->notice($e->getMessage(), ['id' => $id, 'network' => $network, 'contact' => $contact, 'data' => $data]); - } catch (\InvalidArgumentException $e) { + } catch (NotFoundException|\InvalidArgumentException $e) { DI::logger()->notice($e->getMessage(), ['id' => $id, 'network' => $network, 'contact' => $contact, 'data' => $data]); } } elseif (!empty($data['networks'][Protocol::DIASPORA])) { try { DI::dsprContact()->updateFromProbeArray($data['networks'][Protocol::DIASPORA]); - } catch (NotFoundException $e) { - DI::logger()->notice($e->getMessage(), ['id' => $id, 'network' => $network, 'contact' => $contact, 'data' => $data]); - } catch (\InvalidArgumentException $e) { + } catch (NotFoundException|\InvalidArgumentException $e) { DI::logger()->notice($e->getMessage(), ['id' => $id, 'network' => $network, 'contact' => $contact, 'data' => $data]); } } diff --git a/src/Model/GServer.php b/src/Model/GServer.php index c74b0e86ba..6eb6773dc6 100644 --- a/src/Model/GServer.php +++ b/src/Model/GServer.php @@ -822,7 +822,7 @@ class GServer $serverdata = self::fetchWeeklyUsage($url, $serverdata); } - $serverdata['registered-users'] = $serverdata['registered-users'] ?? 0; + $serverdata['registered-users'] ??= 0; // On an active server there has to be at least a single user if (!in_array($serverdata['network'], [Protocol::PHANTOM, Protocol::FEED]) && ($serverdata['registered-users'] <= 0)) { diff --git a/src/Model/Post/Media.php b/src/Model/Post/Media.php index f75d8adfff..9f4e122c17 100644 --- a/src/Model/Post/Media.php +++ b/src/Model/Post/Media.php @@ -184,7 +184,7 @@ class Media } $media['modified'] = DateTimeFormat::utc($lastModified); - $media['published'] = $media['published'] ?? $media['modified']; + $media['published'] ??= $media['modified']; return $media; } @@ -1375,7 +1375,7 @@ class Media return $body; } - if (strpos($body, $links[0]['url'])) { + if (strpos($body, (string) $links[0]['url'])) { return $body; } diff --git a/src/Model/Profile.php b/src/Model/Profile.php index f1071ee4a8..5da575f981 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -855,7 +855,7 @@ class Profile } $parent = User::getOwnerDataById($parent_uid); - if (strpos($about, $parent['addr']) || strpos($about, $parent['url'])) { + if (strpos($about, (string) $parent['addr']) || strpos($about, (string) $parent['url'])) { return $about; } diff --git a/src/Model/User.php b/src/Model/User.php index 7923690ca6..22e25503ae 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -503,7 +503,7 @@ class User // Check if the avatar field is filled and the photo directs to the correct path $avatar = Photo::selectFirst(['resource-id'], ['uid' => $uid, 'profile' => true]); if (DBA::isResult($avatar)) { - $repair = empty($owner['avatar']) || !strpos($owner['photo'], $avatar['resource-id']); + $repair = empty($owner['avatar']) || !strpos($owner['photo'], (string) $avatar['resource-id']); } } diff --git a/src/Model/User/Cookie.php b/src/Model/User/Cookie.php index 69270478f8..86a29666d3 100644 --- a/src/Model/User/Cookie.php +++ b/src/Model/User/Cookie.php @@ -163,7 +163,7 @@ class Cookie protected function setCookie(string $value = null, int $expire = null, bool $secure = null): bool { - return setcookie(self::NAME, $value, $expire, self::PATH, self::DOMAIN, $secure, self::HTTPONLY); + return setcookie(self::NAME, $value, ['expires' => $expire, 'path' => self::PATH, 'domain' => self::DOMAIN, 'secure' => $secure, 'httponly' => self::HTTPONLY]); } /** diff --git a/src/Module/Api/ApiResponse.php b/src/Module/Api/ApiResponse.php index a29b2c651c..14f2031e58 100644 --- a/src/Module/Api/ApiResponse.php +++ b/src/Module/Api/ApiResponse.php @@ -213,7 +213,7 @@ class ApiResponse extends Response */ public function addFormattedContent(string $root_element, array $data, string $format = null, int $cid = 0) { - $format = $format ?? 'json'; + $format ??= 'json'; $return = $this->formatData($root_element, $format, $data, $cid); diff --git a/src/Module/Conversation/Network.php b/src/Module/Conversation/Network.php index aa832bd8b3..3d90371245 100644 --- a/src/Module/Conversation/Network.php +++ b/src/Module/Conversation/Network.php @@ -427,7 +427,7 @@ class Network extends Timeline $this->order = 'commented'; } - $this->selectedTab = $this->selectedTab ?? $this->order; + $this->selectedTab ??= $this->order; // Upon updates in the background and order by last comment we order by received date, // since otherwise the feed will optically jump, when some already visible thread has been updated. diff --git a/src/Module/Debug/Babel.php b/src/Module/Debug/Babel.php index 706a317c42..65c1f18d52 100644 --- a/src/Module/Debug/Babel.php +++ b/src/Module/Debug/Babel.php @@ -138,7 +138,7 @@ class Babel extends BaseModule $markdown = XML::unescape($diaspora); // no break case 'markdown': - $markdown = $markdown ?? trim($request['text']); + $markdown ??= trim($request['text']); $results[] = [ 'title' => 'Source input (Markdown)', diff --git a/src/Module/Response.php b/src/Module/Response.php index 87f2af3b66..c696699c3f 100644 --- a/src/Module/Response.php +++ b/src/Module/Response.php @@ -83,19 +83,19 @@ class Response implements ICanCreateResponses switch ($type) { case static::TYPE_HTML: - $content_type = $content_type ?? 'text/html; charset=utf-8'; + $content_type ??= 'text/html; charset=utf-8'; break; case static::TYPE_JSON: - $content_type = $content_type ?? 'application/json'; + $content_type ??= 'application/json'; break; case static::TYPE_XML: - $content_type = $content_type ?? 'text/xml'; + $content_type ??= 'text/xml'; break; case static::TYPE_RSS: - $content_type = $content_type ?? 'application/rss+xml'; + $content_type ??= 'application/rss+xml'; break; case static::TYPE_ATOM: - $content_type = $content_type ?? 'application/atom+xml'; + $content_type ??= 'application/atom+xml'; break; } diff --git a/src/Module/User/Import.php b/src/Module/User/Import.php index 03b3938645..370f7d446a 100644 --- a/src/Module/User/Import.php +++ b/src/Module/User/Import.php @@ -233,8 +233,8 @@ class Import extends \Friendica\BaseModule } // Backward compatibility - $account['circle'] = $account['circle'] ?? $account['group']; - $account['circle_member'] = $account['circle_member'] ?? $account['group_member']; + $account['circle'] ??= $account['group']; + $account['circle_member'] ??= $account['group_member']; $oldBaseUrl = $account['baseurl']; $newBaseUrl = (string)$this->baseUrl; diff --git a/src/Network/HTTPClient/Client/HttpClient.php b/src/Network/HTTPClient/Client/HttpClient.php index 113facc04b..be0ec704c6 100644 --- a/src/Network/HTTPClient/Client/HttpClient.php +++ b/src/Network/HTTPClient/Client/HttpClient.php @@ -198,7 +198,7 @@ class HttpClient implements ICanSendHttpRequests public function get(string $url, string $accept_content = HttpClientAccept::DEFAULT, array $opts = []): ICanHandleHttpResponses { // In case there is no - $opts[HttpClientOptions::ACCEPT_CONTENT] = $opts[HttpClientOptions::ACCEPT_CONTENT] ?? $accept_content; + $opts[HttpClientOptions::ACCEPT_CONTENT] ??= $accept_content; return $this->request('get', $url, $opts); } diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 20f11a1e4d..3beeb53203 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -227,8 +227,8 @@ class Probe unset($data['networks']); if (!empty($data['network'])) { $networks[$data['network']] = $data; - $ap_profile['guid'] = $ap_profile['guid'] ?? $data['guid'] ?? null; - $ap_profile['about'] = $ap_profile['about'] ?? $data['about'] ?? null; + $ap_profile['guid'] ??= $data['guid'] ?? null; + $ap_profile['about'] ??= $data['about'] ?? null; $ap_profile['keywords'] = $data['keywords'] ?? null; $ap_profile['location'] = $data['location'] ?? null; $ap_profile['poco'] = $data['poco'] ?? null; diff --git a/src/Object/Api/Mastodon/Status.php b/src/Object/Api/Mastodon/Status.php index 652e6dde4d..c5b42d4b1e 100644 --- a/src/Object/Api/Mastodon/Status.php +++ b/src/Object/Api/Mastodon/Status.php @@ -116,8 +116,7 @@ class Status extends BaseDataTransferObject $languages = json_decode($item['language'] ?? '', true); if (is_array($languages)) { - reset($languages); - $this->language = key($languages); + $this->language = array_key_first($languages); } else { $this->language = null; } diff --git a/src/Object/Post.php b/src/Object/Post.php index 956421213a..f462c58fd0 100644 --- a/src/Object/Post.php +++ b/src/Object/Post.php @@ -1100,7 +1100,7 @@ class Post $profile = Contact::getByURL($term['url'], false, ['addr', 'contact-type']); if ( !empty($profile['addr']) && (($profile['contact-type'] ?? Contact::TYPE_UNKNOWN) != Contact::TYPE_COMMUNITY) - && ($profile['addr'] != $owner['addr']) && !strstr($text, $profile['addr']) + && ($profile['addr'] != $owner['addr']) && !strstr($text, (string) $profile['addr']) ) { $text .= '@' . $profile['addr'] . ' '; } diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index c78ea3de78..d8dbe66a76 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -2607,8 +2607,8 @@ class Transmitter if ( !empty($profile['addr']) && $profile['contact-type'] != Contact::TYPE_COMMUNITY - && !strstr($body, $profile['addr']) - && !strstr($body, $tag['url']) + && !strstr($body, (string) $profile['addr']) + && !strstr($body, (string) $tag['url']) && $tag['url'] !== $authorLink ) { $mentions[] = '@[url=' . $tag['url'] . ']' . $profile['nick'] . '[/url]'; diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index bd88587e64..0a1bfc71c1 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -117,7 +117,7 @@ class DFRN // These values aren't sent when sending from the queue. /// @todo Check if we can set these values from the queue or if they are needed at all. $item['entry:comment-allow'] = ($item['entry:comment-allow'] ?? '') ?: true; - $item['entry:cid'] = $item['entry:cid'] ?? 0; + $item['entry:cid'] ??= 0; $entry = self::entry($doc, 'text', $item, $owner, $item['entry:comment-allow'], $item['entry:cid']); if (isset($entry)) { diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index 63017960fb..142ee18331 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -3472,7 +3472,7 @@ class Diaspora $profile = Contact::getByURL($profile_url, false, ['addr', 'name']); if ( !empty($profile['addr']) - && !strstr($body, $profile['addr']) + && !strstr($body, (string) $profile['addr']) && !strstr($body, $profile_url) ) { $body = '@[url=' . $profile_url . ']' . $profile['name'] . '[/url] ' . $body; diff --git a/src/Protocol/Feed.php b/src/Protocol/Feed.php index e691c408de..9e3fb8d4b5 100644 --- a/src/Protocol/Feed.php +++ b/src/Protocol/Feed.php @@ -1411,7 +1411,7 @@ class Feed $entry->setAttribute('xmlns:activity', ActivityNamespace::ACTIVITY); $contact = Contact::getByURL($item['author-link']) ?: $owner; - $contact['nickname'] = $contact['nickname'] ?? $contact['nick']; + $contact['nickname'] ??= $contact['nick']; $author = self::addAuthor($doc, $contact); $entry->appendChild($author); } diff --git a/src/Security/OAuth1/OAuthRequest.php b/src/Security/OAuth1/OAuthRequest.php index 283a1abace..1502604e43 100644 --- a/src/Security/OAuth1/OAuthRequest.php +++ b/src/Security/OAuth1/OAuthRequest.php @@ -87,7 +87,7 @@ class OAuthRequest } // fix for friendica redirect system - $http_url = substr($http_url, 0, strpos($http_url, $parameters['pagename']) + strlen($parameters['pagename'])); + $http_url = substr($http_url, 0, strpos($http_url, (string) $parameters['pagename']) + strlen($parameters['pagename'])); unset($parameters['pagename']); return new OAuthRequest($http_method, $http_url, $parameters); diff --git a/src/Util/EMailer/MailBuilder.php b/src/Util/EMailer/MailBuilder.php index 55f5d1ca67..2979de3035 100644 --- a/src/Util/EMailer/MailBuilder.php +++ b/src/Util/EMailer/MailBuilder.php @@ -235,7 +235,7 @@ abstract class MailBuilder throw new UnprocessableEntityException('Sender address or name is missing.'); } - $this->senderNoReply = $this->senderNoReply ?? $this->senderAddress; + $this->senderNoReply ??= $this->senderAddress; $msgHtml = $this->getHtmlMessage() ?? ''; diff --git a/src/Util/ParseUrl.php b/src/Util/ParseUrl.php index 1d6d70293d..1a53d08c97 100644 --- a/src/Util/ParseUrl.php +++ b/src/Util/ParseUrl.php @@ -546,7 +546,7 @@ class ParseUrl } if (!empty($siteinfo['image'])) { - $siteinfo['images'] = $siteinfo['images'] ?? []; + $siteinfo['images'] ??= []; array_unshift($siteinfo['images'], ['url' => $siteinfo['image']]); unset($siteinfo['image']); } diff --git a/src/Util/Strings.php b/src/Util/Strings.php index e971d4651b..c44b342ff2 100644 --- a/src/Util/Strings.php +++ b/src/Util/Strings.php @@ -444,7 +444,7 @@ class Strings { $string_length = mb_strlen($string); - $length = $length ?? $string_length; + $length ??= $string_length; if ($start < 0) { $start = max(0, $string_length + $start); diff --git a/src/Util/Temporal.php b/src/Util/Temporal.php index df6b12f6b9..ccf708522a 100644 --- a/src/Util/Temporal.php +++ b/src/Util/Temporal.php @@ -310,7 +310,7 @@ class Temporal return DI::l10n()->t('never'); } - $clock = $clock ?? new SystemClock(); + $clock ??= new SystemClock(); $localtime = $posted_date . ' UTC'; $abs = strtotime($localtime); diff --git a/static/routes.config.php b/static/routes.config.php index 9cf450338f..6284c3dd4f 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -657,7 +657,7 @@ return [ '/network' => [ '[/{content}]' => [Module\Conversation\Network::class, [R::GET]], - '/archive/{from:\d\d\d\d-\d\d-\d\d}[/{to:\d\d\d\d-\d\d-\d\d}]' => [Module\Conversation\Network::class, [R::GET]], + '/archive/{from:\d\d\d\d-\d\d-\d\d}[/{to:\d\d\d\d\-\d\d-\d\d}]' => [Module\Conversation\Network::class, [R::GET]], '/circle/{circle_id:\d+}' => [Module\Conversation\Network::class, [R::GET]], ], @@ -672,7 +672,7 @@ return [ '/ping_network' => [ '[/]' => [Module\Ping\Network::class, [R::GET]], - '/archive/{from:\d\d\d\d-\d\d-\d\d}[/{to:\d\d\d\d-\d\d-\d\d}]' => [Module\Ping\Network::class, [R::GET]], + '/archive/{from:\d\d\d\d-\d\d-\d\d}[/{to:\d\d\d\d\-\d\d-\d\d}]' => [Module\Ping\Network::class, [R::GET]], '/group/{contact_id:\d+}' => [Module\Ping\Network::class, [R::GET]], '/circle/{circle_id:\d+}' => [Module\Ping\Network::class, [R::GET]], ], @@ -686,7 +686,7 @@ return [ '/update_network' => [ '[/]' => [Module\Update\Network::class, [R::GET]], - '/archive/{from:\d\d\d\d-\d\d-\d\d}[/{to:\d\d\d\d-\d\d-\d\d}]' => [Module\Update\Network::class, [R::GET]], + '/archive/{from:\d\d\d\d-\d\d-\d\d}[/{to:\d\d\d\d\-\d\d-\d\d}]' => [Module\Update\Network::class, [R::GET]], '/group/{contact_id:\d+}' => [Module\Update\Network::class, [R::GET]], '/circle/{circle_id:\d+}' => [Module\Update\Network::class, [R::GET]], ], diff --git a/view/theme/frio/php/default.php b/view/theme/frio/php/default.php index d569b190ed..725a6d0748 100644 --- a/view/theme/frio/php/default.php +++ b/view/theme/frio/php/default.php @@ -61,7 +61,7 @@ if ($scheme != FRIO_CUSTOM_SCHEME) { } } -$nav_bg = $nav_bg ?? DI::pConfig()->get($uid, 'frio', 'nav_bg', DI::config()->get('frio', 'nav_bg', '#708fa0')); +$nav_bg ??= DI::pConfig()->get($uid, 'frio', 'nav_bg', DI::config()->get('frio', 'nav_bg', '#708fa0')); echo ''; ?> diff --git a/view/theme/frio/php/frio_boot.php b/view/theme/frio/php/frio_boot.php index 2ba04b4615..ea9a88c454 100644 --- a/view/theme/frio/php/frio_boot.php +++ b/view/theme/frio/php/frio_boot.php @@ -49,7 +49,7 @@ function is_modal() $modalpages = get_modalpage_list(); foreach ($modalpages as $r => $value) { - if (strpos($_REQUEST['pagename'], $value) !== false) { + if (strpos($_REQUEST['pagename'], (string) $value) !== false) { $is_modal = true; } } @@ -111,7 +111,7 @@ function is_standard_page($pagetitle) $standardpages = get_standard_page_list(); foreach ($standardpages as $r => $value) { - if (strpos($pagetitle, $value) !== false) { + if (strpos($pagetitle, (string) $value) !== false) { $is_standard_page = true; } } From ea3c576b22a7115b15e9be916c7a40105d55426a Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 4 Mar 2026 21:53:29 +0000 Subject: [PATCH 169/197] chore: fix code style --- mod/photos.php | 22 ++-- src/App.php | 2 +- src/Contact/Avatar.php | 2 +- src/Content/Conversation.php | 2 +- src/Content/Item.php | 42 +++---- src/Content/PageInfo.php | 6 +- src/Content/Text/BBCode.php | 2 +- src/Content/Text/HTML.php | 34 +++--- src/Content/Text/Plaintext.php | 30 ++--- src/Content/Widget/TagCloud.php | 27 +++-- src/Core/Cache/Type/ArrayCache.php | 2 +- src/Core/Lock/Type/CacheLock.php | 4 +- src/Core/Lock/Type/DatabaseLock.php | 4 +- src/Core/Logger/Handler/ErrorHandler.php | 10 +- src/Core/PConfig/Type/JitPConfig.php | 6 +- src/Core/PConfig/Type/PreloadPConfig.php | 2 +- src/Core/Protocol.php | 60 ++++----- .../Storage/Repository/StorageManager.php | 8 +- src/Database/DBA.php | 24 ++-- src/Database/PostUpdate.php | 28 ++--- src/Model/GServer.php | 114 +++++++++--------- src/Model/Post/Media.php | 74 ++++++------ src/Model/User.php | 74 ++++++------ src/Model/User/Cookie.php | 35 +++--- src/Module/Conversation/Network.php | 18 +-- src/Module/Debug/Babel.php | 40 +++--- src/Module/Notifications/Ping.php | 19 +-- src/Module/Photo.php | 8 +- src/Module/User/Import.php | 8 +- .../Notifications/Repository/Notify.php | 38 +++--- src/Network/HTTPClient/Client/HttpClient.php | 16 +-- .../HTTPClient/Response/CurlResult.php | 2 +- src/Network/Probe.php | 12 +- src/Object/Api/Mastodon/Status.php | 6 +- src/Protocol/ActivityPub/Transmitter.php | 56 ++++----- src/Protocol/Feed.php | 24 ++-- src/Security/OAuth1/OAuthRequest.php | 61 +++++----- src/Util/EMailer/MailBuilder.php | 18 +-- src/Util/Emailer.php | 38 +++--- src/Util/ParseUrl.php | 16 +-- src/Util/Strings.php | 10 +- src/Util/XML.php | 18 +-- static/routes.config.php | 16 +-- view/theme/frio/php/default.php | 10 +- 44 files changed, 533 insertions(+), 515 deletions(-) diff --git a/mod/photos.php b/mod/photos.php index 288aeda535..6937e70874 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -61,7 +61,7 @@ function photos_init() 'total' => $album['total'], 'url' => 'photos/' . $owner['nickname'] . '/album/' . bin2hex($album['album']), 'urlencode' => urlencode($album['album']), - 'bin2hex' => bin2hex($album['album']) + 'bin2hex' => bin2hex($album['album']), ]; $ret['albums'][] = $entry; } @@ -74,7 +74,7 @@ function photos_init() '$recent' => DI::l10n()->t('Recent Photos'), '$albums' => $ret['albums'], '$upload' => [DI::l10n()->t('Upload photo'), 'photos/' . $owner['nickname'] . '/upload'], - '$can_post' => (DI::userSession()->getLocalUserId() && $owner['uid'] === DI::userSession()->getLocalUserId()) + '$can_post' => (DI::userSession()->getLocalUserId() && $owner['uid'] === DI::userSession()->getLocalUserId()), ]); } @@ -85,7 +85,7 @@ function photos_init() $tpl = Renderer::getMarkupTemplate("photos_head.tpl"); DI::page()['htmlhead'] .= Renderer::replaceMacros($tpl, [ - '$ispublic' => DI::l10n()->t('everybody') + '$ispublic' => DI::l10n()->t('everybody'), ]); } @@ -183,13 +183,13 @@ function photos_post() "SELECT distinct(`resource-id`) AS `rid` FROM `photo` WHERE `contact-id` = ? AND `uid` = ? AND `album` = ?", $visitor, $page_owner_uid, - $album + $album, )); } else { $r = DBA::toArray(DBA::p( "SELECT distinct(`resource-id`) AS `rid` FROM `photo` WHERE `uid` = ? AND `album` = ?", DI::userSession()->getLocalUserId(), - $album + $album, )); } @@ -297,7 +297,7 @@ function photos_post() $photo = $photos[0]; Photo::update( ['desc' => $desc, 'album' => $albname, 'allow_cid' => $str_contact_allow, 'allow_gid' => $str_circle_allow, 'deny_cid' => $str_contact_deny, 'deny_gid' => $str_circle_deny], - ['resource-id' => $resource_id, 'uid' => $page_owner_uid] + ['resource-id' => $resource_id, 'uid' => $page_owner_uid], ); // Update the photo albums cache if album name was changed @@ -439,13 +439,13 @@ function photos_content() $ret = [ 'post_url' => 'profile/' . $user['nickname'] . '/photos', 'addon_text' => $uploader, - 'default_upload' => true + 'default_upload' => true, ]; $eventDispatcher = DI::eventDispatcher(); $eventDispatcher->dispatch( - new ArrayFilterEvent(ArrayFilterEvent::PHOTO_UPLOAD_FORM, $ret) + new ArrayFilterEvent(ArrayFilterEvent::PHOTO_UPLOAD_FORM, $ret), ); // Determine if we're in album context (uploading to a specific album) @@ -518,7 +518,7 @@ function photos_content() "SELECT `resource-id`, MAX(`scale`) AS `scale` FROM `photo` WHERE `uid` = ? AND `album` = ? AND `scale` <= 4 $sql_extra GROUP BY `resource-id`", $owner_uid, - $album + $album, )); if (DBA::isResult($r)) { $total = count($r); @@ -543,7 +543,7 @@ function photos_content() intval($owner_uid), DBA::escape($album), $pager->getStart(), - $pager->getItemsPerPage() + $pager->getItemsPerPage(), )); if ($cmd === 'drop') { @@ -715,7 +715,7 @@ function photos_content() $tpl = Renderer::getMarkupTemplate('photo_edit_head.tpl'); DI::page()['htmlhead'] .= Renderer::replaceMacros($tpl, [ '$prevlink' => $prevlink, - '$nextlink' => $nextlink + '$nextlink' => $nextlink, ]); if ($prevlink) { diff --git a/src/App.php b/src/App.php index 0212bbe909..2c3d587a68 100644 --- a/src/App.php +++ b/src/App.php @@ -617,7 +617,7 @@ class App $router = $this->container->create(Router::class); $moduleClass ??= $router->getModuleClass(); - $parameters = $router->getParameters(); + $parameters = $router->getParameters(); $dice_profiler_threshold = $this->config->get('system', 'dice_profiler_threshold', 0); diff --git a/src/Contact/Avatar.php b/src/Contact/Avatar.php index 0a1f6b40ee..caba042906 100644 --- a/src/Contact/Avatar.php +++ b/src/Contact/Avatar.php @@ -20,7 +20,7 @@ use Friendica\Util\Proxy; */ class Avatar { - const BASE_PATH = '/avatar/'; + public const BASE_PATH = '/avatar/'; /** * Returns a field array with locally cached avatar pictures diff --git a/src/Content/Conversation.php b/src/Content/Conversation.php index 3b659a5e7a..f3370fc41b 100644 --- a/src/Content/Conversation.php +++ b/src/Content/Conversation.php @@ -318,7 +318,7 @@ class Conversation $x['allow_location'] ??= $user['allow_location']; $x['default_location'] ??= $user['default-location']; $x['nickname'] ??= $user['nickname']; - $x['lockstate'] = $x['lockstate'] ?? ACL::getLockstateForUserId($user['uid']) ? 'lock' : 'unlock'; + $x['lockstate'] = $x['lockstate'] ?? ACL::getLockstateForUserId($user['uid']) ? 'lock' : 'unlock'; $x['acl'] ??= ACL::getFullSelectorHTML($this->page, $user['uid'], true); $x['bang'] ??= ''; $x['visitor'] ??= 'block'; diff --git a/src/Content/Item.php b/src/Content/Item.php index 5c6fabd342..72dcbfc0bc 100644 --- a/src/Content/Item.php +++ b/src/Content/Item.php @@ -151,7 +151,7 @@ class Item 'url' => $url, 'removeurl' => $this->userSession->getLocalUserId() == $uid ? 'filerm/' . $item['id'] . '?cat=' . rawurlencode($savedFolderName) : '', 'first' => $first, - 'last' => false + 'last' => false, ]; $first = false; } @@ -167,7 +167,7 @@ class Item 'url' => "#", 'removeurl' => $this->userSession->getLocalUserId() == $uid ? 'filerm/' . $item['id'] . '?term=' . rawurlencode($savedFolderName) : '', 'first' => $first, - 'last' => false + 'last' => false, ]; $first = false; } @@ -303,7 +303,7 @@ class Item if ($this->activity->match($item['verb'], Activity::TAG)) { $fields = [ 'author-id', 'author-link', 'author-name', 'author-network', 'author-link', 'author-alias', - 'verb', 'object-type', 'resource-id', 'body', 'plink' + 'verb', 'object-type', 'resource-id', 'body', 'plink', ]; $obj = Post::selectFirst($fields, ['uri' => $item['parent-uri']]); if (!DBA::isResult($obj)) { @@ -452,8 +452,8 @@ class Item $menu[$this->l10n->t('Raw content')] = 'javascript:displaySearchText(' . $item['uri-id'] . ');'; - if ((($cid == 0) || ($rel == Contact::FOLLOWER)) && - in_array($item['network'], Protocol::FEDERATED) + if ((($cid == 0) || ($rel == Contact::FOLLOWER)) + && in_array($item['network'], Protocol::FEDERATED) ) { $menu[$this->l10n->t('Connect/Follow')] = 'contact/follow?url=' . urlencode($item['author-link']) . '&auto=1'; } @@ -496,10 +496,10 @@ class Item } // Check conditions - return (!($this->activity->match($item['verb'], Activity::FOLLOW) && - $item['object-type'] === Activity\ObjectType::NOTE && - empty($item['self']) && - $item['uid'] == $this->userSession->getLocalUserId()) + return (!($this->activity->match($item['verb'], Activity::FOLLOW) + && $item['object-type'] === Activity\ObjectType::NOTE + && empty($item['self']) + && $item['uid'] == $this->userSession->getLocalUserId()) ); } @@ -741,7 +741,7 @@ class Item if (is_array($shared)) { return [ 'comment' => BBCode::removeSharedData($item['body'] ?? ''), - 'post' => $shared + 'post' => $shared, ]; } } @@ -752,7 +752,7 @@ class Item if (is_array($shared)) { return [ 'comment' => $attributes['comment'], - 'post' => $shared + 'post' => $shared, ]; } } @@ -845,8 +845,8 @@ class Item 0 => [ 'src' => $attachment_img_src, 'width' => $attachment_img_width, - 'height' => $attachment_img_height - ] + 'height' => $attachment_img_height, + ], ]; } else { unset($attachment['images']); @@ -940,11 +940,11 @@ class Item public function initializePost(array $post): array { - $post['network'] = Protocol::DFRN; - $post['protocol'] = Conversation::PARCEL_DIRECT; - $post['direction'] = Conversation::PUSH; - $post['received'] = DateTimeFormat::utcNow(); - $post['origin'] = true; + $post['network'] = Protocol::DFRN; + $post['protocol'] = Conversation::PARCEL_DIRECT; + $post['direction'] = Conversation::PUSH; + $post['received'] = DateTimeFormat::utcNow(); + $post['origin'] = true; $post['wall'] ??= true; $post['guid'] ??= System::createUUID(); $post['verb'] ??= Activity::POST; @@ -1031,7 +1031,7 @@ class Item ]; $hook_data = $this->eventDispatcher->dispatch( - new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL_END, $hook_data) + new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL_END, $hook_data), )->getArray(); $post = $hook_data['item'] ?? $post; @@ -1050,7 +1050,7 @@ class Item $this->baseURL, $post, $address, - $author['thumb'] ?? '' + $author['thumb'] ?? '', )); } } @@ -1335,7 +1335,7 @@ class Item \IntlChar::BLOCK_CODE_BASIC_LATIN, \IntlChar::BLOCK_CODE_LATIN_1_SUPPLEMENT, \IntlChar::BLOCK_CODE_LATIN_EXTENDED_A, \IntlChar::BLOCK_CODE_LATIN_EXTENDED_B, \IntlChar::BLOCK_CODE_LATIN_EXTENDED_C, \IntlChar::BLOCK_CODE_LATIN_EXTENDED_D, - \IntlChar::BLOCK_CODE_LATIN_EXTENDED_E, \IntlChar::BLOCK_CODE_LATIN_EXTENDED_ADDITIONAL + \IntlChar::BLOCK_CODE_LATIN_EXTENDED_E, \IntlChar::BLOCK_CODE_LATIN_EXTENDED_ADDITIONAL, ]); } diff --git a/src/Content/PageInfo.php b/src/Content/PageInfo.php index dfa672024a..90f32c2fc2 100644 --- a/src/Content/PageInfo.php +++ b/src/Content/PageInfo.php @@ -103,8 +103,8 @@ class PageInfo // It maybe is a rich content, but if it does have everything that a link has, // then treat it that way - if (($data['type'] == 'rich') && is_string($data['title']) && - is_string($data['text']) && !empty($data['images'])) { + if (($data['type'] == 'rich') && is_string($data['title']) + && is_string($data['text']) && !empty($data['images'])) { $data['type'] = 'link'; } @@ -223,7 +223,7 @@ class PageInfo $hashtag = str_replace( [' ', '+', '/', '.', '#', "'"], ['', '', '', '', '', ''], - $keyword + $keyword, ); $taglist[] = $hashtag; diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index e31e215974..1ef2220104 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -811,7 +811,7 @@ class BBCode function ($match) use ($callback, $uriid) { $attributes = self::extractShareAttributes($match[2]); - $author_contact = Contact::getByURL($attributes['profile'], false, ['id', 'url', 'addr', 'name', 'micro']); + $author_contact = Contact::getByURL($attributes['profile'], false, ['id', 'url', 'addr', 'name', 'micro']); $author_contact['url'] ??= $attributes['profile']; $author_contact['addr'] ??= ''; diff --git a/src/Content/Text/HTML.php b/src/Content/Text/HTML.php index 085613c3a2..304525a470 100644 --- a/src/Content/Text/HTML.php +++ b/src/Content/Text/HTML.php @@ -153,7 +153,7 @@ class HTML "
  • ", "
  • ", ], - $message + $message, ); // remove namespaces @@ -209,7 +209,7 @@ class HTML 'div', ['style' => 'border:none;border-left:solid blue 1.5pt;padding:0cm 0cm 0cm 4.0pt'], '[quote]', - '[/quote]' + '[/quote]', ); // MyBB-Stuff @@ -244,7 +244,7 @@ class HTML $elements = [ 'b', 'del', 'em', 'i', 'ins', 'kbd', 'mark', - 's', 'samp', 'strong', 'sub', 'sup', 'u', 'var' + 's', 'samp', 'strong', 'sub', 'sup', 'u', 'var', ]; foreach ($elements as $element) { self::tagToBBCode($doc, $element, [], '[' . $element . ']', '[/' . $element . ']'); @@ -348,7 +348,7 @@ class HTML $message = str_replace( ['[b][b]', '[/b][/b]', '[i][i]', '[/i][/i]'], ['[b]', '[/b]', '[i]', '[/i]'], - $message + $message, ); // Handling Yahoo style of mails @@ -367,7 +367,7 @@ class HTML return $prefix . "\n" . html_entity_decode($matches[2]) . "\n" . '[/code]'; }, - $message + $message, ); $message = trim($message); @@ -402,7 +402,7 @@ class HTML } $parts = array_merge($base, parse_url($url)); - $url2 = (string)Uri::fromParts((array)$parts); + $url2 = (string) Uri::fromParts((array) $parts); return str_replace($url, $url2, $link); } @@ -436,7 +436,7 @@ class HTML function ($match) use ($basepath) { return self::qualifyURLsSub($match, $basepath); }, - $body + $body, ); } return $body; @@ -531,7 +531,7 @@ class HTML // A list of some links that should be ignored $list = [ "/user/", "/tag/", "/group/", "/circle/", "/profile/", "/search?search=", "/search?tag=", "mailto:", "/u/", "/node/", - "//plus.google.com/", "//twitter.com/" + "//plus.google.com/", "//twitter.com/", ]; foreach ($list as $listitem) { if (strpos($treffer[1], $listitem) !== false) { @@ -708,19 +708,19 @@ class HTML $s = preg_replace( '#]+>(.*?)https?://www.youtube.com/((?:v|cp)/[A-Za-z0-9\-_=]+)(.*?)#ism', '[youtube]$2[/youtube]', - $s + $s, ); $s = preg_replace( '#](.*?)https?://www.youtube.com/embed/([A-Za-z0-9\-_=]+)(.*?)#ism', '[youtube]$2[/youtube]', - $s + $s, ); $s = preg_replace( '#](.*?)https?://player.vimeo.com/video/([0-9]+)(.*?)#ism', '[vimeo]$2[/vimeo]', - $s + $s, ); return $s; @@ -777,7 +777,7 @@ class HTML $tpl = Renderer::getMarkupTemplate("scroll_loader.tpl"); return Renderer::replaceMacros($tpl, [ 'wait' => DI::l10n()->t('Loading more entries...'), - 'end' => DI::l10n()->t('The end') + 'end' => DI::l10n()->t('The end'), ]); } @@ -832,7 +832,7 @@ class HTML '$name' => $contact['name'], 'title' => $contact['name'] . ' [' . $contact['addr'] . ']', '$parkle' => $sparkle, - '$redir' => $redir + '$redir' => $redir, ]); } @@ -870,7 +870,7 @@ class HTML $values['$search_options'] = [ 'fulltext' => DI::l10n()->t('Full Text'), 'tags' => DI::l10n()->t('Tags'), - 'contacts' => DI::l10n()->t('Contacts') + 'contacts' => DI::l10n()->t('Contacts'), ]; if (DI::config()->get('system', 'poco_local_search')) { @@ -899,7 +899,7 @@ class HTML '$reasons' => $reasons, '$rnd' => Strings::getRandomHex(8), '$openclose' => DI::l10n()->t('Click to open/close'), - '$html' => $html + '$html' => $html, ]); } @@ -947,7 +947,7 @@ class HTML ' . implode('|', $allowedIframeDomains) . ' ) (?:/|$) # Prevents bogus domains like youtube.com.fake.tld - %xi' + %xi', ); $config->set('Attr.AllowedRel', [ @@ -1073,7 +1073,7 @@ class HTML * * @param string $html * @param string $className - * @return string the HTML without the removed HTML element + * @return string the HTML without the removed HTML element */ public static function removeElementByClass(string $html, string $className): string { diff --git a/src/Content/Text/Plaintext.php b/src/Content/Text/Plaintext.php index 96b2e5c159..7bbd1dbfb3 100644 --- a/src/Content/Text/Plaintext.php +++ b/src/Content/Text/Plaintext.php @@ -17,7 +17,7 @@ use IntlChar; class Plaintext { // Assumed length of an URL when shortened via the network's own url shortener (e.g. Twitter) - const URL_LENGTH = 23; + public const URL_LENGTH = 23; /** * Shortens message @@ -37,8 +37,8 @@ class Plaintext return mb_substr(mb_substr(trim($msg), 0, $limit), 0, -3) . $ellipsis; } - $lines = explode("\n", $msg); - $msg = ""; + $lines = explode("\n", $msg); + $msg = ""; $recycle = html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8'); foreach ($lines as $row => $line) { if (mb_strlen(trim($msg . "\n" . $line)) <= $limit) { @@ -138,13 +138,13 @@ class Plaintext if ($post['type'] == 'text') { $post['type'] = 'link'; - $post['url'] = $item['plink']; + $post['url'] = $item['plink']; } } $html = BBCode::convertForUriId($item['uri-id'], $post['text'] . ($post['after'] ?? ''), $htmlmode); - $msg = HTML::toPlaintext($html, 0, true); - $msg = trim(html_entity_decode($msg, ENT_QUOTES, 'UTF-8')); + $msg = HTML::toPlaintext($html, 0, true); + $msg = trim(html_entity_decode($msg, ENT_QUOTES, 'UTF-8')); $complete_msg = $msg; @@ -215,7 +215,7 @@ class Plaintext if (($post['type'] == 'text') && isset($post['url'])) { $post['url'] = $item['plink']; } elseif (!isset($post['url'])) { - $limit = $limit - self::URL_LENGTH; + $limit = $limit - self::URL_LENGTH; $post['url'] = $item['plink']; } elseif (strpos($item['body'], '[share') !== false) { $post['url'] = $item['plink']; @@ -250,7 +250,7 @@ class Plaintext $limit = $baselimit; while ($message) { - $pos_word = mb_strpos($message, ' '); + $pos_word = mb_strpos($message, ' '); $pos_paragraph = mb_strpos($message, "\n"); if (($pos_word !== false) && ($pos_paragraph !== false)) { @@ -260,8 +260,8 @@ class Plaintext } elseif ($pos_paragraph !== false) { $pos = $pos_paragraph + 1; } else { - $word = $message; - $message = ''; + $word = $message; + $message = ''; } if (trim($message)) { @@ -324,7 +324,7 @@ class Plaintext // Remove mentions and hashtag links $URLSearchString = '^\[\]'; - $post['text'] = preg_replace("/([#!@])\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '$1$3', $item['body']); + $post['text'] = preg_replace("/([#!@])\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '$1$3', $item['body']); // Remove abstract $post['text'] = BBCode::stripAbstract($post['text']); @@ -382,10 +382,10 @@ class Plaintext $page = Post\Media::getByURIId($item['quote-uri-id'], [Post\Media::HTML]); } if (!empty($page)) { - $post['type'] = 'link'; - $post['url'] = $page[0]['url']; - $post['description'] = $page[0]['description']; - $post['title'] = $page[0]['name']; + $post['type'] = 'link'; + $post['url'] = $page[0]['url']; + $post['description'] = $page[0]['description']; + $post['title'] = $page[0]['name']; if (empty($post['image']) && !empty($page[0]['preview'])) { $post['image'] = $page[0]['preview']; diff --git a/src/Content/Widget/TagCloud.php b/src/Content/Widget/TagCloud.php index c2ba1fd1ed..5c6972ba93 100644 --- a/src/Content/Widget/TagCloud.php +++ b/src/Content/Widget/TagCloud.php @@ -38,7 +38,7 @@ class TagCloud $r = self::tagadelic($uid, $count, $owner_id, $flags, $type); if (count($r)) { $contact = DBA::selectFirst('contact', ['url'], ['uid' => $uid, 'self' => true]); - $url = DI::baseUrl()->remove($contact['url']); + $url = DI::baseUrl()->remove($contact['url']); $tags = []; foreach ($r as $rr) { @@ -50,9 +50,9 @@ class TagCloud } $tpl = Renderer::getMarkupTemplate('widget/tagcloud.tpl'); - $o = Renderer::replaceMacros($tpl, [ + $o = Renderer::replaceMacros($tpl, [ '$title' => DI::l10n()->t('Tags'), - '$tags' => $tags + '$tags' => $tags, ]); } return $o; @@ -74,7 +74,7 @@ class TagCloud private static function tagadelic($uid, $count = 0, $owner_id = 0, $flags = '', $type = Tag::HASHTAG) { $sql_options = Item::getPermissionsSQLByUserId($uid, 'post-user-view'); - $limit = $count ? sprintf('LIMIT %d', intval($count)) : ''; + $limit = $count ? sprintf('LIMIT %d', intval($count)) : ''; if ($flags) { if ($flags === 'wall') { @@ -87,13 +87,14 @@ class TagCloud } // Fetch tags - $tag_stmt = DBA::p("SELECT `name`, COUNT(`name`) AS `total` FROM `tag-search-view` + $tag_stmt = DBA::p( + "SELECT `name`, COUNT(`name`) AS `total` FROM `tag-search-view` LEFT JOIN `post-user-view` ON `tag-search-view`.`uri-id` = `post-user-view`.`uri-id` AND `tag-search-view`.`uid` = `post-user-view`.`uid` WHERE `tag-search-view`.`uid` = ? AND `post-user-view`.`visible` AND NOT `post-user-view`.`deleted` $sql_options GROUP BY `name` ORDER BY `total` DESC $limit", - $uid + $uid, ); if (!DBA::isResult($tag_stmt)) { return []; @@ -113,9 +114,9 @@ class TagCloud private static function tagCalc(array $arr) { $tags = []; - $min = 1000000000.0; - $max = -1000000000.0; - $x = 0; + $min = 1000000000.0; + $max = -1000000000.0; + $x = 0; if (!$arr) { return []; @@ -125,15 +126,15 @@ class TagCloud $tags[$x][0] = $rr['name']; $tags[$x][1] = log($rr['total']); $tags[$x][2] = 0; - $min = min($min, $tags[$x][1]); - $max = max($max, $tags[$x][1]); - $x ++; + $min = min($min, $tags[$x][1]); + $max = max($max, $tags[$x][1]); + $x++; } usort($tags, [self::class, 'tagsSort']); $range = max(0.01, $max - $min) * 1.0001; - for ($x = 0; $x < count($tags); $x ++) { + for ($x = 0; $x < count($tags); $x++) { $tags[$x][2] = 1 + floor(9 * ($tags[$x][1] - $min) / $range); } diff --git a/src/Core/Cache/Type/ArrayCache.php b/src/Core/Cache/Type/ArrayCache.php index 74368b29c4..9391825b10 100644 --- a/src/Core/Cache/Type/ArrayCache.php +++ b/src/Core/Cache/Type/ArrayCache.php @@ -16,7 +16,7 @@ use Friendica\Core\Cache\Enum; class ArrayCache extends AbstractCache implements ICanCacheInMemory { use CompareDeleteTrait; - const NAME = 'array'; + public const NAME = 'array'; /** @var array Array with the cached data */ protected $cachedData = []; diff --git a/src/Core/Lock/Type/CacheLock.php b/src/Core/Lock/Type/CacheLock.php index cb61a55b39..df40aec765 100644 --- a/src/Core/Lock/Type/CacheLock.php +++ b/src/Core/Lock/Type/CacheLock.php @@ -19,7 +19,7 @@ class CacheLock extends AbstractLock * * @var string */ - const CACHE_PREFIX = 'lock:'; + public const CACHE_PREFIX = 'lock:'; /** * @var ICanCacheInMemory @@ -50,7 +50,7 @@ class CacheLock extends AbstractLock do { $lock = $this->cache->get($lockKey); // When we do want to lock something that was already locked by us. - if ((int)$lock == getmypid()) { + if ((int) $lock == getmypid()) { $got_lock = true; } diff --git a/src/Core/Lock/Type/DatabaseLock.php b/src/Core/Lock/Type/DatabaseLock.php index 0bc13c9420..39e33d2d4f 100644 --- a/src/Core/Lock/Type/DatabaseLock.php +++ b/src/Core/Lock/Type/DatabaseLock.php @@ -51,7 +51,7 @@ class DatabaseLock extends AbstractLock do { $this->dba->lock('locks'); $lock = $this->dba->selectFirst('locks', ['locked', 'pid'], [ - '`name` = ? AND `expires` >= ?', $key,DateTimeFormat::utcNow() + '`name` = ? AND `expires` >= ?', $key,DateTimeFormat::utcNow(), ]); if ($this->dba->isResult($lock)) { @@ -65,7 +65,7 @@ class DatabaseLock extends AbstractLock $this->dba->update('locks', [ 'locked' => true, 'pid' => $this->pid, - 'expires' => DateTimeFormat::utc('now + ' . $ttl . 'seconds') + 'expires' => DateTimeFormat::utc('now + ' . $ttl . 'seconds'), ], ['name' => $key]); $got_lock = true; } diff --git a/src/Core/Logger/Handler/ErrorHandler.php b/src/Core/Logger/Handler/ErrorHandler.php index 15cff99e24..b62a5a4502 100644 --- a/src/Core/Logger/Handler/ErrorHandler.php +++ b/src/Core/Logger/Handler/ErrorHandler.php @@ -219,7 +219,7 @@ class ErrorHandler $this->logger->log( $level, sprintf('Uncaught Exception %s: "%s" at %s line %s', self::getClass($e), $e->getMessage(), $e->getFile(), $e->getLine()), - ['exception' => $e] + ['exception' => $e], ); if ($this->previousExceptionHandler) { @@ -262,14 +262,14 @@ class ErrorHandler $message .= sprintf( ' It was called in `%s`%s.', $calledPlace['file'], - isset($calledPlace['line']) ? ' in line ' . $calledPlace['line'] : '' + isset($calledPlace['line']) ? ' in line ' . $calledPlace['line'] : '', ); } // fatal error codes are ignored if a fatal error handler is present as well to avoid duplicate log entries if (!$this->hasFatalErrorHandler || !in_array($code, self::$fatalErrors, true)) { $level = $this->errorLevelMap[$code] ?? LogLevel::CRITICAL; - $this->logger->log($level, self::codeToString($code).': '.$message, ['code' => $code, 'message' => $message, 'file' => $file, 'line' => $line]); + $this->logger->log($level, self::codeToString($code) . ': ' . $message, ['code' => $code, 'message' => $message, 'file' => $file, 'line' => $line]); } else { $this->lastFatalTrace = $trace; } @@ -294,8 +294,8 @@ class ErrorHandler if ($lastError && in_array($lastError['type'], self::$fatalErrors, true)) { $this->logger->log( $this->fatalLevel, - 'Fatal Error ('.self::codeToString($lastError['type']).'): '.$lastError['message'], - ['code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'], 'trace' => $this->lastFatalTrace] + 'Fatal Error (' . self::codeToString($lastError['type']) . '): ' . $lastError['message'], + ['code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'], 'trace' => $this->lastFatalTrace], ); } } diff --git a/src/Core/PConfig/Type/JitPConfig.php b/src/Core/PConfig/Type/JitPConfig.php index c11ab2b73e..a0b9e605f2 100644 --- a/src/Core/PConfig/Type/JitPConfig.php +++ b/src/Core/PConfig/Type/JitPConfig.php @@ -19,7 +19,7 @@ use Friendica\Core\PConfig\ValueObject; */ class JitPConfig extends AbstractPConfigValues { - const NAME = 'jit'; + public const NAME = 'jit'; /** * @var array Array of already loaded db values (even if there was no value) @@ -71,8 +71,8 @@ class JitPConfig extends AbstractPConfigValues } // if the value isn't loaded or refresh is needed, load it to the cache - if ($this->configModel->isConnected() && - (empty($this->db_loaded[$uid][$cat][$key]) || $refresh)) { + if ($this->configModel->isConnected() + && (empty($this->db_loaded[$uid][$cat][$key]) || $refresh)) { $dbValue = $this->configModel->get($uid, $cat, $key); if (isset($dbValue)) { diff --git a/src/Core/PConfig/Type/PreloadPConfig.php b/src/Core/PConfig/Type/PreloadPConfig.php index e21d52927b..930235977d 100644 --- a/src/Core/PConfig/Type/PreloadPConfig.php +++ b/src/Core/PConfig/Type/PreloadPConfig.php @@ -18,7 +18,7 @@ use Friendica\Core\PConfig\ValueObject; */ class PreloadPConfig extends AbstractPConfigValues { - const NAME = 'preload'; + public const NAME = 'preload'; /** @var array */ private $config_loaded; diff --git a/src/Core/Protocol.php b/src/Core/Protocol.php index c41f696232..6f7579da39 100644 --- a/src/Core/Protocol.php +++ b/src/Core/Protocol.php @@ -22,43 +22,43 @@ use Friendica\Protocol\Diaspora; class Protocol { // Native support - const ACTIVITYPUB = 'apub'; // ActivityPub (Pleroma, Mastodon, Osada, ...) - const DFRN = 'dfrn'; // Friendica, Mistpark, other DFRN implementations - const DIASPORA = 'dspr'; // Diaspora, Hubzilla, Socialhome, Ganggo - const FEED = 'feed'; // RSS/Atom feeds with no known "post/notify" protocol - const MAIL = 'mail'; // IMAP/POP + public const ACTIVITYPUB = 'apub'; // ActivityPub (Pleroma, Mastodon, Osada, ...) + public const DFRN = 'dfrn'; // Friendica, Mistpark, other DFRN implementations + public const DIASPORA = 'dspr'; // Diaspora, Hubzilla, Socialhome, Ganggo + public const FEED = 'feed'; // RSS/Atom feeds with no known "post/notify" protocol + public const MAIL = 'mail'; // IMAP/POP - const NATIVE_SUPPORT = [self::DFRN, self::DIASPORA, self::FEED, self::MAIL, self::ACTIVITYPUB]; + public const NATIVE_SUPPORT = [self::DFRN, self::DIASPORA, self::FEED, self::MAIL, self::ACTIVITYPUB]; - const FEDERATED = [self::DFRN, self::DIASPORA, self::ACTIVITYPUB]; + public const FEDERATED = [self::DFRN, self::DIASPORA, self::ACTIVITYPUB]; - const SUPPORT_PRIVATE = [self::DFRN, self::DIASPORA, self::MAIL, self::ACTIVITYPUB, self::PUMPIO]; + public const SUPPORT_PRIVATE = [self::DFRN, self::DIASPORA, self::MAIL, self::ACTIVITYPUB, self::PUMPIO]; // Supported through a connector - const BLUESKY = 'bsky'; // Bluesky - const DIASPORA2 = 'dspc'; // Diaspora connector - const DISCOURSE = 'dscs'; // Discourse - const PNUT = 'pnut'; // pnut.io - const PUMPIO = 'pump'; // pump.io - const TUMBLR = 'tmbl'; // Tumblr - const TWITTER = 'twit'; // Twitter + public const BLUESKY = 'bsky'; // Bluesky + public const DIASPORA2 = 'dspc'; // Diaspora connector + public const DISCOURSE = 'dscs'; // Discourse + public const PNUT = 'pnut'; // pnut.io + public const PUMPIO = 'pump'; // pump.io + public const TUMBLR = 'tmbl'; // Tumblr + public const TWITTER = 'twit'; // Twitter // Dead protocols - const APPNET = 'apdn'; // app.net - Dead protocol - const FACEBOOK = 'face'; // Facebook API - Not working anymore, API is closed - const GPLUS = 'goog'; // Google+ - Dead in 2019 - const OSTATUS = 'stat'; // GNU Social and other OStatus implementations - const STATUSNET = 'stac'; // Statusnet connector + public const APPNET = 'apdn'; // app.net - Dead protocol + public const FACEBOOK = 'face'; // Facebook API - Not working anymore, API is closed + public const GPLUS = 'goog'; // Google+ - Dead in 2019 + public const OSTATUS = 'stat'; // GNU Social and other OStatus implementations + public const STATUSNET = 'stac'; // Statusnet connector // Currently unsupported - const ICALENDAR = 'ical'; // iCalendar - const LINKEDIN = 'lnkd'; // LinkedIn - const MYSPACE = 'mysp'; // MySpace - const NEWS = 'nntp'; // Network News Transfer Protocol - const XMPP = 'xmpp'; // XMPP - const ZOT = 'zot!'; // Zot! + public const ICALENDAR = 'ical'; // iCalendar + public const LINKEDIN = 'lnkd'; // LinkedIn + public const MYSPACE = 'mysp'; // MySpace + public const NEWS = 'nntp'; // Network News Transfer Protocol + public const XMPP = 'xmpp'; // XMPP + public const ZOT = 'zot!'; // Zot! - const PHANTOM = 'unkn'; // Place holder + public const PHANTOM = 'unkn'; // Place holder /** * Returns whether the provided protocol supports following @@ -75,7 +75,7 @@ class Protocol $hook_data = [ 'protocol' => $protocol, - 'result' => null + 'result' => null, ]; $eventDispatcher = DI::eventDispatcher(); @@ -102,7 +102,7 @@ class Protocol $hook_data = [ 'protocol' => $protocol, - 'result' => null + 'result' => null, ]; $eventDispatcher = DI::eventDispatcher(); @@ -340,7 +340,7 @@ class Protocol $hook_data = [ 'protocol' => $protocol, - 'result' => null + 'result' => null, ]; $eventDispatcher = DI::eventDispatcher(); diff --git a/src/Core/Storage/Repository/StorageManager.php b/src/Core/Storage/Repository/StorageManager.php index 63d21d16db..681318a63c 100644 --- a/src/Core/Storage/Repository/StorageManager.php +++ b/src/Core/Storage/Repository/StorageManager.php @@ -34,11 +34,11 @@ use Psr\Log\LoggerInterface; class StorageManager { // Default tables to look for data - const TABLES = ['photo', 'attach']; + public const TABLES = ['photo', 'attach']; // Default storage backends /** @var string[] */ - const DEFAULT_BACKENDS = [ + public const DEFAULT_BACKENDS = [ Type\Filesystem::NAME, Type\Database::NAME, ]; @@ -245,7 +245,7 @@ class StorageManager [ Type\SystemResource::getName(), Type\ExternalResource::getName(), - ] + ], ); return in_array($name, $validBackends); } @@ -373,7 +373,7 @@ class StorageManager $table, ['id', 'data', 'backend-class', 'backend-ref'], ['`backend-class` IS NULL or `backend-class` != ?', $destination::getName()], - ['limit' => $limit] + ['limit' => $limit], ); while ($resource = $this->dba->fetch($resources)) { diff --git a/src/Database/DBA.php b/src/Database/DBA.php index 6566181570..ae65370463 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -23,16 +23,16 @@ class DBA /** * Lowest possible date value */ - const NULL_DATE = '0001-01-01'; + public const NULL_DATE = '0001-01-01'; /** * Lowest possible datetime value */ - const NULL_DATETIME = '0001-01-01 00:00:00'; + public const NULL_DATETIME = '0001-01-01 00:00:00'; /** * Lowest possible datetime(6) value */ - const NULL_DATETIME6 = '0001-01-01 00:00:00.000000'; + public const NULL_DATETIME6 = '0001-01-01 00:00:00.000000'; public static function connect(): bool { @@ -130,11 +130,11 @@ class DBA */ public static function cleanQuery(string $sql): string { - $search = ["\t", "\n", "\r", " "]; + $search = ["\t", "\n", "\r", " "]; $replace = [' ', ' ', ' ', ' ']; do { $oldsql = $sql; - $sql = str_replace($search, $replace, $sql); + $sql = str_replace($search, $replace, $sql); } while ($oldsql != $sql); return $sql; @@ -518,8 +518,8 @@ class DBA '.', array_map( function (string $identifier) { return '`' . str_replace('`', '``', $identifier) . '`'; }, - explode('.', $identifier) - ) + explode('.', $identifier), + ), ); } @@ -578,7 +578,7 @@ class DBA return $condition; } - $values = []; + $values = []; $condition_string = ""; foreach ($condition as $field => $value) { if ($condition_string != "") { @@ -592,7 +592,7 @@ class DBA * In case of mixed types, cast all as string. * Logic needs to be consistent with DBA::p() data types. */ - $is_int = false; + $is_int = false; $is_alpha = false; foreach ($value as $single_value) { if (is_int($single_value)) { @@ -605,13 +605,13 @@ class DBA if ($is_int && $is_alpha) { foreach ($value as &$ref) { if (is_int($ref)) { - $ref = (string)$ref; + $ref = (string) $ref; } } unset($ref); //Prevent accidental re-use. } - $values = array_merge($values, array_values($value)); + $values = array_merge($values, array_values($value)); $placeholders = substr(str_repeat("?, ", count($value)), 0, -2); $condition_string .= self::quoteIdentifier($field) . " IN (" . $placeholders . ")"; } else { @@ -645,7 +645,7 @@ class DBA } $conditionStrings = []; - $result = []; + $result = []; foreach ($conditions as $key => $condition) { if (!$condition) { diff --git a/src/Database/PostUpdate.php b/src/Database/PostUpdate.php index 52c3387253..d14ce32343 100644 --- a/src/Database/PostUpdate.php +++ b/src/Database/PostUpdate.php @@ -35,9 +35,9 @@ use GuzzleHttp\Psr7\Uri; class PostUpdate { // Needed for the helper function to read from the legacy term table - const OBJECT_TYPE_POST = 1; + public const OBJECT_TYPE_POST = 1; - const VERSION = 1550; + public const VERSION = 1550; /** * Calls the post update functions @@ -185,7 +185,7 @@ class PostUpdate Protocol::DIASPORA, Protocol::OSTATUS, Protocol::ACTIVITYPUB, - 0 + 0, ); while ($contact = DBA::fetch($contacts)) { @@ -348,7 +348,7 @@ class PostUpdate Tag::MENTION, Tag::EXCLUSIVE_MENTION, Tag::IMPLICIT_MENTION, - $id + $id, ); if (DBA::errorNo() != 0) { @@ -507,7 +507,7 @@ class PostUpdate 'term', ['oid'], ["`type` IN (?, ?) AND `oid` >= ?", Category::CATEGORY, Category::FILE, $id], - ['order' => ['oid'], 'limit' => 1000, 'group_by' => ['oid']] + ['order' => ['oid'], 'limit' => 1000, 'group_by' => ['oid']], ); if (DBA::errorNo() != 0) { @@ -651,7 +651,7 @@ class PostUpdate DBA::update( 'contact', ['gsid' => GServer::getRealID($contact['baseurl'], true), 'baseurl' => GServer::cleanURL($contact['baseurl'])], - ['id' => $contact['id']] + ['id' => $contact['id']], ); ++$rows; @@ -706,7 +706,7 @@ class PostUpdate DBA::update( 'apcontact', ['gsid' => GServer::getRealID($apcontact['baseurl'], true), 'baseurl' => GServer::cleanURL($apcontact['baseurl'])], - ['url' => $apcontact['url']] + ['url' => $apcontact['url']], ); ++$rows; @@ -1079,7 +1079,7 @@ class PostUpdate WHERE NOT `source` IS NULL AND `conversation`.`protocol` = ? AND `uri-id` > ? LIMIT ?", Conversation::PARCEL_ACTIVITYPUB, $id, - 1000 + 1000, ); if (DBA::errorNo() != 0) { @@ -1239,12 +1239,12 @@ class PostUpdate $parts = parse_url($contact['url']); unset($parts['path']); - $server = (string)Uri::fromParts($parts); + $server = (string) Uri::fromParts($parts); DBA::update( 'contact', ['gsid' => GServer::getRealID($server, true), 'baseurl' => GServer::cleanURL($server)], - ['id' => $contact['id']] + ['id' => $contact['id']], ); ++$rows; @@ -1333,10 +1333,10 @@ class PostUpdate return true; } - $id = (int)(DI::keyValue()->get('post_update_version_1544_id') ?? 0); + $id = (int) (DI::keyValue()->get('post_update_version_1544_id') ?? 0); if ($id == 0) { $post = Post::selectFirstPost(['uri-id'], [], ['order' => ['uri-id' => true]]); - $id = (int)($post['uri-id'] ?? 0); + $id = (int) ($post['uri-id'] ?? 0); } DI::logger()->info('Start', ['uri-id' => $id]); @@ -1398,10 +1398,10 @@ class PostUpdate } DBA::close($engagements); - $id = (int)(DI::keyValue()->get('post_update_version_1550_id') ?? 0); + $id = (int) (DI::keyValue()->get('post_update_version_1550_id') ?? 0); if ($id == 0) { $post = Post::selectFirstPost(['uri-id'], [], ['order' => ['uri-id' => true]]); - $id = (int)($post['uri-id'] ?? 0); + $id = (int) ($post['uri-id'] ?? 0); } DI::logger()->info('Start', ['uri-id' => $id]); diff --git a/src/Model/GServer.php b/src/Model/GServer.php index 6eb6773dc6..cf018c7981 100644 --- a/src/Model/GServer.php +++ b/src/Model/GServer.php @@ -40,44 +40,44 @@ use Psr\Http\Message\UriInterface; class GServer { // Directory types - const DT_NONE = 0; - const DT_POCO = 1; - const DT_MASTODON = 2; + public const DT_NONE = 0; + public const DT_POCO = 1; + public const DT_MASTODON = 2; // Methods to detect server types // Non endpoint specific methods - const DETECT_MANUAL = 0; - const DETECT_HEADER = 1; - const DETECT_BODY = 2; - const DETECT_HOST_META = 3; - const DETECT_CONTACTS = 4; - const DETECT_AP_ACTOR = 5; - const DETECT_AP_COLLECTION = 6; + public const DETECT_MANUAL = 0; + public const DETECT_HEADER = 1; + public const DETECT_BODY = 2; + public const DETECT_HOST_META = 3; + public const DETECT_CONTACTS = 4; + public const DETECT_AP_ACTOR = 5; + public const DETECT_AP_COLLECTION = 6; - const DETECT_UNSPECIFIC = [self::DETECT_MANUAL, self::DETECT_HEADER, self::DETECT_BODY, self::DETECT_HOST_META, self::DETECT_CONTACTS, self::DETECT_AP_ACTOR]; + public const DETECT_UNSPECIFIC = [self::DETECT_MANUAL, self::DETECT_HEADER, self::DETECT_BODY, self::DETECT_HOST_META, self::DETECT_CONTACTS, self::DETECT_AP_ACTOR]; // Implementation specific endpoints // @todo Possibly add Lemmy detection via the endpoint /api/v3/site - const DETECT_FRIENDIKA = 10; - const DETECT_FRIENDICA = 11; - const DETECT_STATUSNET = 12; - const DETECT_GNUSOCIAL = 13; - const DETECT_CONFIG_JSON = 14; // Statusnet, GNU Social, Older Hubzilla/Redmatrix - const DETECT_SITEINFO_JSON = 15; // Newer Hubzilla - const DETECT_MASTODON_API = 16; - const DETECT_STATUS_PHP = 17; // Nextcloud - const DETECT_V1_CONFIG = 18; - const DETECT_SYSTEM_ACTOR = 20; // Mistpark, Osada, Roadhouse, Zap - const DETECT_THREADS = 21; + public const DETECT_FRIENDIKA = 10; + public const DETECT_FRIENDICA = 11; + public const DETECT_STATUSNET = 12; + public const DETECT_GNUSOCIAL = 13; + public const DETECT_CONFIG_JSON = 14; // Statusnet, GNU Social, Older Hubzilla/Redmatrix + public const DETECT_SITEINFO_JSON = 15; // Newer Hubzilla + public const DETECT_MASTODON_API = 16; + public const DETECT_STATUS_PHP = 17; // Nextcloud + public const DETECT_V1_CONFIG = 18; + public const DETECT_SYSTEM_ACTOR = 20; // Mistpark, Osada, Roadhouse, Zap + public const DETECT_THREADS = 21; // Standardized endpoints - const DETECT_STATISTICS_JSON = 100; - const DETECT_NODEINFO_10 = 101; // Nodeinfo Version 1.0 - const DETECT_NODEINFO_20 = 102; // Nodeinfo Version 2.0 - const DETECT_NODEINFO2_10 = 103; // Nodeinfo2 Version 1.0 - const DETECT_NODEINFO_21 = 104; // Nodeinfo Version 2.1 - const DETECT_NODEINFO_22 = 105; // Nodeinfo Version 2.2 + public const DETECT_STATISTICS_JSON = 100; + public const DETECT_NODEINFO_10 = 101; // Nodeinfo Version 1.0 + public const DETECT_NODEINFO_20 = 102; // Nodeinfo Version 2.0 + public const DETECT_NODEINFO2_10 = 103; // Nodeinfo2 Version 1.0 + public const DETECT_NODEINFO_21 = 104; // Nodeinfo Version 2.1 + public const DETECT_NODEINFO_22 = 105; // Nodeinfo Version 2.2 private static RobotsTxt $robotsTxt; @@ -194,10 +194,10 @@ class GServer */ private static function isDefunct(array $gserver): bool { - return ($gserver['failed'] || in_array($gserver['network'], Protocol::FEDERATED)) && - ($gserver['last_contact'] >= $gserver['created']) && - ($gserver['last_contact'] < $gserver['last_failure']) && - ($gserver['last_contact'] < DateTimeFormat::utc('now - 90 days')); + return ($gserver['failed'] || in_array($gserver['network'], Protocol::FEDERATED)) + && ($gserver['last_contact'] >= $gserver['created']) + && ($gserver['last_contact'] < $gserver['last_failure']) + && ($gserver['last_contact'] < DateTimeFormat::utc('now - 90 days')); } /** @@ -256,9 +256,9 @@ class GServer } elseif (!empty($contact['baseurl'])) { $server = $contact['baseurl']; } elseif ($contact['network'] == Protocol::DIASPORA) { - $parts = (array)parse_url($contact['url']); + $parts = (array) parse_url($contact['url']); unset($parts['path']); - $server = (string)Uri::fromParts($parts); + $server = (string) Uri::fromParts($parts); } else { return true; } @@ -482,7 +482,7 @@ class GServer self::update( ['url' => $url, 'failed' => true, 'blocked' => Network::isUrlBlocked($url), 'last_failure' => DateTimeFormat::utcNow(), 'next_contact' => $next_update, 'network' => Protocol::PHANTOM, 'detection-method' => null], - ['nurl' => $nurl] + ['nurl' => $nurl], ); DI::logger()->info('Set failed status for existing server', ['url' => $url]); if (self::isDefunct($gserver)) { @@ -521,7 +521,7 @@ class GServer public static function cleanURL(string $dirtyUrl): string { try { - return (string)self::cleanUri(new Uri($dirtyUrl)); + return (string) self::cleanUri(new Uri($dirtyUrl)); } catch (\Throwable $e) { DI::logger()->warning('Invalid URL', ['dirtyUrl' => $dirtyUrl]); return ''; @@ -546,8 +546,8 @@ class GServer preg_replace( '#(?:^|/)index\.php#', '', - rtrim($dirtyUri->getPath(), '/') - ) + rtrim($dirtyUri->getPath(), '/'), + ), ); } @@ -594,8 +594,8 @@ class GServer if (!Strings::compareLink($url, $valid_url)) { // We only follow redirects when the path stays the same or the target url has no path. // Some systems have got redirects on their landing page to a single account page. This check handles it. - if (((parse_url($url, PHP_URL_HOST) != parse_url($valid_url, PHP_URL_HOST)) && (parse_url($url, PHP_URL_PATH) == parse_url($valid_url, PHP_URL_PATH))) || - (((parse_url($url, PHP_URL_HOST) != parse_url($valid_url, PHP_URL_HOST)) || (parse_url($url, PHP_URL_PATH) != parse_url($valid_url, PHP_URL_PATH))) && empty(parse_url($valid_url, PHP_URL_PATH)))) { + if (((parse_url($url, PHP_URL_HOST) != parse_url($valid_url, PHP_URL_HOST)) && (parse_url($url, PHP_URL_PATH) == parse_url($valid_url, PHP_URL_PATH))) + || (((parse_url($url, PHP_URL_HOST) != parse_url($valid_url, PHP_URL_HOST)) || (parse_url($url, PHP_URL_PATH) != parse_url($valid_url, PHP_URL_PATH))) && empty(parse_url($valid_url, PHP_URL_PATH)))) { DI::logger()->debug('Found redirect. Mark old entry as failure', ['old' => $url, 'new' => $valid_url]); self::setFailureByUrl($url); $target_id = self::getID($valid_url, true); @@ -609,12 +609,12 @@ class GServer return false; } - if ((parse_url($url, PHP_URL_HOST) != parse_url($valid_url, PHP_URL_HOST)) && (parse_url($url, PHP_URL_PATH) != parse_url($valid_url, PHP_URL_PATH)) && - (parse_url($url, PHP_URL_PATH) == '')) { + if ((parse_url($url, PHP_URL_HOST) != parse_url($valid_url, PHP_URL_HOST)) && (parse_url($url, PHP_URL_PATH) != parse_url($valid_url, PHP_URL_PATH)) + && (parse_url($url, PHP_URL_PATH) == '')) { DI::logger()->debug('Found redirect. Mark old entry as failure and redirect to the basepath.', ['old' => $url, 'new' => $valid_url]); - $parts = (array)parse_url($valid_url); + $parts = (array) parse_url($valid_url); unset($parts['path']); - $valid_url = (string)Uri::fromParts($parts); + $valid_url = (string) Uri::fromParts($parts); self::setFailureByUrl($url); if (!self::getID($valid_url, true) && !Network::isUrlBlocked($valid_url)) { @@ -625,9 +625,9 @@ class GServer DI::logger()->debug('Found redirect, but ignore it.', ['old' => $url, 'new' => $valid_url]); } - if ((parse_url($url, PHP_URL_HOST) == parse_url($valid_url, PHP_URL_HOST)) && - (parse_url($url, PHP_URL_PATH) == parse_url($valid_url, PHP_URL_PATH)) && - (parse_url($url, PHP_URL_SCHEME) != parse_url($valid_url, PHP_URL_SCHEME))) { + if ((parse_url($url, PHP_URL_HOST) == parse_url($valid_url, PHP_URL_HOST)) + && (parse_url($url, PHP_URL_PATH) == parse_url($valid_url, PHP_URL_PATH)) + && (parse_url($url, PHP_URL_SCHEME) != parse_url($valid_url, PHP_URL_SCHEME))) { $url = $valid_url; } @@ -789,8 +789,8 @@ class GServer // When a server is new, then there is no gserver entry yet. // But in "detectNetworkViaContacts" it could happen that a contact is updated, // and this can call this function here as well. - if (self::getID($url, true) && (in_array($serverdata['network'], [Protocol::PHANTOM, Protocol::FEED]) || - in_array($serverdata['detection-method'], [self::DETECT_MANUAL, self::DETECT_HEADER, self::DETECT_BODY, self::DETECT_HOST_META]))) { + if (self::getID($url, true) && (in_array($serverdata['network'], [Protocol::PHANTOM, Protocol::FEED]) + || in_array($serverdata['detection-method'], [self::DETECT_MANUAL, self::DETECT_HEADER, self::DETECT_BODY, self::DETECT_HOST_META]))) { $serverdata = self::detectNetworkViaContacts($url, $serverdata); } @@ -974,7 +974,7 @@ class GServer } // Sanitize incoming data, see https://github.com/friendica/friendica/issues/8565 - $data['subscribe'] = (bool)($data['subscribe'] ?? false); + $data['subscribe'] = (bool) ($data['subscribe'] ?? false); if (!$data['subscribe'] || empty($data['scope']) || !in_array(strtolower($data['scope']), ['all', 'tags'])) { $data['scope'] = ''; @@ -1241,7 +1241,7 @@ class GServer $server = [ 'detection-method' => self::DETECT_NODEINFO_10, - 'register_policy' => Register::CLOSED + 'register_policy' => Register::CLOSED, ]; if (!empty($nodeinfo['openRegistrations'])) { @@ -1472,7 +1472,7 @@ class GServer $server = [ 'detection-method' => self::DETECT_NODEINFO2_10, - 'register_policy' => Register::CLOSED + 'register_policy' => Register::CLOSED, ]; if (!empty($nodeinfo['openRegistrations'])) { @@ -2325,8 +2325,8 @@ class GServer // Test for GNU Social if (self::$robotsTxt->isAllowed('/api/gnusocial/version.json')) { $curlResult = DI::httpClient()->get($url . '/api/gnusocial/version.json', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); - if ($curlResult->isSuccess() && ($curlResult->getBodyString() != '{"error":"not implemented"}') && - ($curlResult->getBodyString() != '') && (strlen($curlResult->getBodyString()) < 30)) { + if ($curlResult->isSuccess() && ($curlResult->getBodyString() != '{"error":"not implemented"}') + && ($curlResult->getBodyString() != '') && (strlen($curlResult->getBodyString()) < 30)) { $serverdata['platform'] = 'gnusocial'; // Remove junk that some GNU Social servers return $serverdata['version'] = str_replace(chr(239) . chr(187) . chr(191), '', $curlResult->getBodyString()); @@ -2345,8 +2345,8 @@ class GServer // Test for Statusnet if (self::$robotsTxt->isAllowed('/api/statusnet/version.json')) { $curlResult = DI::httpClient()->get($url . '/api/statusnet/version.json', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); - if ($curlResult->isSuccess() && ($curlResult->getBodyString() != '{"error":"not implemented"}') && - ($curlResult->getBodyString() != '') && (strlen($curlResult->getBodyString()) < 30)) { + if ($curlResult->isSuccess() && ($curlResult->getBodyString() != '{"error":"not implemented"}') + && ($curlResult->getBodyString() != '') && (strlen($curlResult->getBodyString()) < 30)) { // Remove junk that some GNU Social servers return $serverdata['version'] = str_replace(chr(239) . chr(187) . chr(191), '', $curlResult->getBodyString()); @@ -2673,7 +2673,7 @@ class GServer 'gserver', ['id', 'url', 'nurl', 'network', 'poco', 'directory-type'], ["NOT `blocked` AND NOT `failed` AND `directory-type` != ? AND `last_poco_query` < ?", GServer::DT_NONE, $last_update], - ['order' => ['RAND()']] + ['order' => ['RAND()']], ); while ($gserver = DBA::fetch($gservers)) { diff --git a/src/Model/Post/Media.php b/src/Model/Post/Media.php index 9f4e122c17..5763516a7f 100644 --- a/src/Model/Post/Media.php +++ b/src/Model/Post/Media.php @@ -44,22 +44,22 @@ use GuzzleHttp\Psr7\Uri; */ class Media { - const UNKNOWN = 0; - const IMAGE = 1; - const VIDEO = 2; - const AUDIO = 3; - const TEXT = 4; - const APPLICATION = 5; - const TORRENT = 16; - const HTML = 17; - const XML = 18; - const PLAIN = 19; - const ACTIVITY = 20; - const ACCOUNT = 21; - const HLS = 22; - const JSON = 23; - const LD = 24; - const DOCUMENT = 128; + public const UNKNOWN = 0; + public const IMAGE = 1; + public const VIDEO = 2; + public const AUDIO = 3; + public const TEXT = 4; + public const APPLICATION = 5; + public const TORRENT = 16; + public const HTML = 17; + public const XML = 18; + public const PLAIN = 19; + public const ACTIVITY = 20; + public const ACCOUNT = 21; + public const HLS = 22; + public const JSON = 23; + public const LD = 24; + public const DOCUMENT = 128; /** * Insert a post-media record @@ -166,11 +166,11 @@ class Media 'url' => $href, 'size' => $length, 'mimetype' => $type, - 'description' => $title + 'description' => $title, ]); - return '[attach]href="' . $media['url'] . '" length="' . $media['size'] . - '" type="' . $media['mimetype'] . '" title="' . $media['description'] . '"[/attach]'; + return '[attach]href="' . $media['url'] . '" length="' . $media['size'] + . '" type="' . $media['mimetype'] . '" title="' . $media['description'] . '"[/attach]'; } private static function setModified(array $media, string $lastModified): array @@ -183,7 +183,7 @@ class Media return $media; } - $media['modified'] = DateTimeFormat::utc($lastModified); + $media['modified'] = DateTimeFormat::utc($lastModified); $media['published'] ??= $media['modified']; return $media; @@ -228,7 +228,7 @@ class Media $media['mimetype'] = $curlResult->getContentType(); } if (empty($media['size']) && $is_head) { - $media['size'] = (int)($curlResult->getHeader('Content-Length')[0] ?? strlen($curlResult->getBodyString() ?? '')); + $media['size'] = (int) ($curlResult->getHeader('Content-Length')[0] ?? strlen($curlResult->getBodyString() ?? '')); } $media = self::setModified($media, $curlResult->getHeader('Last-Modified')[0] ?? ''); } else { @@ -365,8 +365,8 @@ class Media } if ( - !empty($item['plink']) && Strings::compareLink($item['plink'], $media['url']) && - parse_url($item['plink'], PHP_URL_HOST) != parse_url($item['uri'], PHP_URL_HOST) + !empty($item['plink']) && Strings::compareLink($item['plink'], $media['url']) + && parse_url($item['plink'], PHP_URL_HOST) != parse_url($item['uri'], PHP_URL_HOST) ) { DI::logger()->debug('Not a link to an activity', ['uri-id' => $media['uri-id'], 'url' => $media['url'], 'plink' => $item['plink'], 'uri' => $item['uri']]); $media['type'] = $media['type'] == self::ACTIVITY ? self::JSON : $media['type']; @@ -786,7 +786,7 @@ class Media foreach (explode("\n", $curlResult->getBodyString() ?? '') as $line) { if (strpos(trim($line), '#EXT-X-STREAM-INF') === 0) { if (preg_match('/RESOLUTION=([\d]+)x([\d]+)/', $line, $matches)) { - $resolutions[$matches[1]] = [(int)$matches[1], (int)$matches[2]]; + $resolutions[$matches[1]] = [(int) $matches[1], (int) $matches[2]]; } } } @@ -885,7 +885,7 @@ class Media 'type' => self::IMAGE, 'url' => $image, 'preview' => $picture[2], - 'description' => $picture[3] + 'description' => $picture[3], ]; } elseif (self::isLinkToPhoto($picture[1], $picture[2])) { $body = str_replace($picture[0], '', $body); @@ -895,7 +895,7 @@ class Media 'type' => self::IMAGE, 'url' => $picture[1], 'preview' => $picture[2], - 'description' => $picture[3] + 'description' => $picture[3], ]; } elseif ($removepicturelinks) { $body = str_replace($picture[0], '', $body); @@ -905,7 +905,7 @@ class Media 'type' => self::UNKNOWN, 'url' => $picture[1], 'preview' => $picture[2], - 'description' => $picture[3] + 'description' => $picture[3], ]; } } @@ -930,7 +930,7 @@ class Media 'type' => self::IMAGE, 'url' => $image, 'preview' => $picture[2], - 'description' => null + 'description' => null, ]; } elseif (self::isLinkToPhoto($picture[1], $picture[2])) { $body = str_replace($picture[0], '', $body); @@ -940,7 +940,7 @@ class Media 'type' => self::IMAGE, 'url' => $picture[1], 'preview' => $picture[2], - 'description' => null + 'description' => null, ]; } elseif ($removepicturelinks) { $body = str_replace($picture[0], '', $body); @@ -950,7 +950,7 @@ class Media 'type' => self::UNKNOWN, 'url' => $picture[1], 'preview' => $picture[2], - 'description' => null + 'description' => null, ]; } } @@ -1354,7 +1354,7 @@ class Media 'src' => $links[0]['preview'], 'height' => $links[0]['preview-height'], 'width' => $links[0]['preview-width'], - ]] + ]], ]; $body .= "\n" . PageInfo::getFooterFromData($data); @@ -1416,9 +1416,9 @@ class Media */ public static function getPreviewUrlForId(int $id, string $size = ''): string { - return DI::baseUrl() . '/photo/preview/' . - (Proxy::getPixelsFromSize($size) ? Proxy::getPixelsFromSize($size) . '/' : '') . - $id; + return DI::baseUrl() . '/photo/preview/' + . (Proxy::getPixelsFromSize($size) ? Proxy::getPixelsFromSize($size) . '/' : '') + . $id; } /** @@ -1430,9 +1430,9 @@ class Media */ public static function getUrlForId(int $id, string $size = ''): string { - return DI::baseUrl() . '/photo/media/' . - (Proxy::getPixelsFromSize($size) ? Proxy::getPixelsFromSize($size) . '/' : '') . - $id; + return DI::baseUrl() . '/photo/media/' + . (Proxy::getPixelsFromSize($size) ? Proxy::getPixelsFromSize($size) . '/' : '') + . $id; } /** diff --git a/src/Model/User.php b/src/Model/User.php index 22e25503ae..4e3d51d4ad 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -54,13 +54,13 @@ class User * * @{ */ - const PAGE_FLAGS_NORMAL = 0; - const PAGE_FLAGS_SOAPBOX = 1; - const PAGE_FLAGS_COMMUNITY = 2; - const PAGE_FLAGS_FREELOVE = 3; - const PAGE_FLAGS_BLOG = 4; - const PAGE_FLAGS_PRVGROUP = 5; - const PAGE_FLAGS_COMM_MAN = 6; + public const PAGE_FLAGS_NORMAL = 0; + public const PAGE_FLAGS_SOAPBOX = 1; + public const PAGE_FLAGS_COMMUNITY = 2; + public const PAGE_FLAGS_FREELOVE = 3; + public const PAGE_FLAGS_BLOG = 4; + public const PAGE_FLAGS_PRVGROUP = 5; + public const PAGE_FLAGS_COMM_MAN = 6; /** * @} */ @@ -84,12 +84,12 @@ class User * This will only be assigned to contacts, not to user accounts * @{ */ - const ACCOUNT_TYPE_PERSON = 0; - const ACCOUNT_TYPE_ORGANISATION = 1; - const ACCOUNT_TYPE_NEWS = 2; - const ACCOUNT_TYPE_COMMUNITY = 3; - const ACCOUNT_TYPE_RELAY = 4; - const ACCOUNT_TYPE_DELETED = 127; + public const ACCOUNT_TYPE_PERSON = 0; + public const ACCOUNT_TYPE_ORGANISATION = 1; + public const ACCOUNT_TYPE_NEWS = 2; + public const ACCOUNT_TYPE_COMMUNITY = 3; + public const ACCOUNT_TYPE_RELAY = 4; + public const ACCOUNT_TYPE_DELETED = 127; /** * @} */ @@ -170,7 +170,7 @@ class User $system['region'] = ''; $system['postal-code'] = ''; $system['country-name'] = ''; - $system['homepage'] = (string)DI::baseUrl(); + $system['homepage'] = (string) DI::baseUrl(); $system['dob'] = '0000-00-00'; // Ensure that the user contains data @@ -755,7 +755,7 @@ class User 'username' => $username, 'password' => $password, 'authenticated' => 0, - 'user_record' => null + 'user_record' => null, ]; $eventDispatcher = DI::eventDispatcher(); @@ -815,7 +815,7 @@ class User 'uid' => $user_info, 'account_expired' => false, 'account_removed' => false, - 'verified' => true + 'verified' => true, ]; if (!$with_blocked) { $condition = DBA::mergeConditions($condition, ['blocked' => false]); @@ -825,7 +825,7 @@ class User $condition = [ "(`email` = ? OR `username` = ? OR `nickname` = ?) AND `verified` AND NOT `account_removed` AND NOT `account_expired`", - $user_info, $user_info, $user_info + $user_info, $user_info, $user_info, ]; if (!$with_blocked) { $condition = DBA::mergeConditions($condition, ['blocked' => false]); @@ -905,7 +905,7 @@ class User 'code' => $e->getCode(), 'file' => $e->getFile(), 'line' => $e->getLine(), - 'trace' => $e->getTraceAsString() + 'trace' => $e->getTraceAsString(), ]); return false; @@ -1008,7 +1008,7 @@ class User 'password' => $password_hashed, 'pwdreset' => null, 'pwdreset_time' => null, - 'legacy_password' => false + 'legacy_password' => false, ]; return DBA::update('user', $fields, ['uid' => $uid]); } @@ -1025,7 +1025,7 @@ class User { return DBA::exists('user', [ 'uid' => $uid, - 'email' => self::getAdminEmailList() + 'email' => self::getAdminEmailList(), ]); } @@ -1337,7 +1337,7 @@ class User 'language' => $language, 'timezone' => 'UTC', 'register_date' => DateTimeFormat::utcNow(), - 'default-location' => '' + 'default-location' => '', ]); if ($insert_result) { @@ -1566,7 +1566,7 @@ class User $user, DI::config()->get('config', 'sitename'), DI::baseUrl(), - ($register['password'] ?? '') ?: 'Sent in a previous email' + ($register['password'] ?? '') ?: 'Sent in a previous email', ); } @@ -1597,8 +1597,8 @@ class User // Delete the avatar Photo::delete(['uid' => $register['uid']]); - return DBA::delete('user', ['uid' => $register['uid']]) && - Register::deleteByHash($register['hash']); + return DBA::delete('user', ['uid' => $register['uid']]) + && Register::deleteByHash($register['hash']); } /** @@ -1616,9 +1616,9 @@ class User */ public static function createMinimal(string $name, string $email, string $nick, string $lang = L10n::DEFAULT, string $avatar = ''): bool { - if (empty($name) || - empty($email) || - empty($nick)) { + if (empty($name) + || empty($email) + || empty($nick)) { throw new HTTPException\InternalServerErrorException('Invalid arguments.'); } @@ -1629,7 +1629,7 @@ class User 'nickname' => $nick, 'verified' => 1, 'language' => $lang, - 'photo' => $avatar + 'photo' => $avatar, ]); $user = $result['user']; @@ -1702,7 +1702,7 @@ class User $sitename, $siteurl, $user['nickname'], - $password + $password, )); $email = DI::emailer() @@ -1736,7 +1736,7 @@ class User Thank you for registering at %2$s. Your account has been created. ', $user['username'], - $sitename + $sitename, )); $body = Strings::deindent($l10n->t( ' @@ -1769,7 +1769,7 @@ class User $sitename, $siteurl, $user['username'], - $password + $password, )); $email = DI::emailer() @@ -1877,14 +1877,14 @@ class User $identities = [[ 'uid' => $user['uid'], 'username' => $user['username'], - 'nickname' => $user['nickname'] + 'nickname' => $user['nickname'], ]]; // Then add all the children $r = DBA::select( 'user', ['uid', 'username', 'nickname'], - ['parent-uid' => $user['uid'], 'verified' => true, 'blocked' => false, 'account_removed' => false, 'account_expired' => false] + ['parent-uid' => $user['uid'], 'verified' => true, 'blocked' => false, 'account_removed' => false, 'account_expired' => false], ); if (DBA::isResult($r)) { $identities = array_merge($identities, DBA::toArray($r)); @@ -1894,7 +1894,7 @@ class User $r = DBA::select( 'user', ['uid', 'username', 'nickname'], - ['uid' => $user['parent-uid'], 'verified' => true, 'blocked' => false, 'account_removed' => false, 'account_expired' => false] + ['uid' => $user['parent-uid'], 'verified' => true, 'blocked' => false, 'account_removed' => false, 'account_expired' => false], ); if (DBA::isResult($r)) { $identities = DBA::toArray($r); @@ -1904,7 +1904,7 @@ class User $r = DBA::select( 'user', ['uid', 'username', 'nickname'], - ['parent-uid' => $user['parent-uid'], 'verified' => true, 'blocked' => false, 'account_removed' => false, 'account_expired' => false] + ['parent-uid' => $user['parent-uid'], 'verified' => true, 'blocked' => false, 'account_removed' => false, 'account_expired' => false], ); if (DBA::isResult($r)) { $identities = array_merge($identities, DBA::toArray($r)); @@ -1916,7 +1916,7 @@ class User FROM `manage` INNER JOIN `user` ON `manage`.`mid` = `user`.`uid` WHERE NOT `user`.`account_removed` AND `manage`.`uid` = ?", - $user['uid'] + $user['uid'], ); if (DBA::isResult($r)) { $identities = array_merge($identities, DBA::toArray($r)); @@ -1978,7 +1978,7 @@ class User ['uid', 'last-activity', 'last-item'], ["`verified` AND `last-activity` > ? AND NOT `blocked` AND NOT `account_removed` AND NOT `account_expired`", - DBA::NULL_DATETIME] + DBA::NULL_DATETIME], ); if (!DBA::isResult($userStmt)) { return $statistics; diff --git a/src/Model/User/Cookie.php b/src/Model/User/Cookie.php index 86a29666d3..33a78bb170 100644 --- a/src/Model/User/Cookie.php +++ b/src/Model/User/Cookie.php @@ -17,15 +17,15 @@ use Friendica\Core\Config\Capability\IManageConfigValues; class Cookie { /** @var int Default expire duration in days */ - const DEFAULT_EXPIRE = 7; + public const DEFAULT_EXPIRE = 7; /** @var string The name of the Friendica cookie */ - const NAME = 'Friendica'; + public const NAME = 'Friendica'; /** @var string The path of the Friendica cookie */ - const PATH = '/'; + public const PATH = '/'; /** @var string The domain name of the Friendica cookie */ - const DOMAIN = ''; + public const DOMAIN = ''; /** @var bool True, if the cookie should only be accessible through HTTP */ - const HTTPONLY = true; + public const HTTPONLY = true; /** @var string The remote address of this node */ private $remoteAddr; @@ -49,8 +49,11 @@ class Cookie $this->sslEnabled = $baseURL->getScheme() === 'https'; $this->sitePrivateKey = $config->get('system', 'site_prvkey'); - $authCookieDays = $config->get('system', 'auth_cookie_lifetime', - self::DEFAULT_EXPIRE); + $authCookieDays = $config->get( + 'system', + 'auth_cookie_lifetime', + self::DEFAULT_EXPIRE, + ); $this->lifetime = $authCookieDays * 24 * 60 * 60; $this->remoteAddr = $request->getRemoteAddress(); @@ -120,8 +123,8 @@ class Cookie */ public function reset(array $data): bool { - return $this->clear() && - $this->setMultiple($data); + return $this->clear() + && $this->setMultiple($data); } /** @@ -144,7 +147,7 @@ class Cookie return $this->setCookie( json_encode(['ip' => $this->remoteAddr] + $this->data), $this->lifetime + time(), - $this->sslEnabled + $this->sslEnabled, ); } @@ -160,9 +163,11 @@ class Cookie * @return bool If output exists prior to calling this function, * */ - protected function setCookie(string $value = null, int $expire = null, - bool $secure = null): bool - { + protected function setCookie( + string $value = null, + int $expire = null, + bool $secure = null + ): bool { return setcookie(self::NAME, $value, ['expires' => $expire, 'path' => self::PATH, 'domain' => self::DOMAIN, 'secure' => $secure, 'httponly' => self::HTTPONLY]); } @@ -180,7 +185,7 @@ class Cookie return hash_hmac( 'sha256', hash_hmac('sha256', $privateData, $privateKey), - $this->sitePrivateKey + $this->sitePrivateKey, ); } @@ -196,7 +201,7 @@ class Cookie { return hash_equals( $this->hashPrivateData($privateData, $privateKey), - $hash + $hash, ); } } diff --git a/src/Module/Conversation/Network.php b/src/Module/Conversation/Network.php index 3d90371245..58d4893258 100644 --- a/src/Module/Conversation/Network.php +++ b/src/Module/Conversation/Network.php @@ -163,7 +163,7 @@ class Network extends Timeline ]; $this->eventDispatcher->dispatch( - new ArrayFilterEvent(ArrayFilterEvent::NETWORK_CONTENT_START, $hook_data) + new ArrayFilterEvent(ArrayFilterEvent::NETWORK_CONTENT_START, $hook_data), ); $o = ''; @@ -180,7 +180,7 @@ class Network extends Timeline Feature::SEARCHES, Feature::FOLDERS, Feature::NOSHARER, - Feature::TRENDING_TAGS + Feature::TRENDING_TAGS, ]; } @@ -215,8 +215,8 @@ class Network extends Timeline $this->page['aside'] .= TrendingTags::getHTML($this->selectedTab); break; case Feature::NOSHARER: - if (($this->channel->isTimeline($this->selectedTab) || $this->userDefinedChannel->isTimeline($this->selectedTab, $this->session->getLocalUserId())) && - !in_array($this->selectedTab, [Channel::FOLLOWERS, Channel::FORYOU, Channel::DISCOVER])) { + if (($this->channel->isTimeline($this->selectedTab) || $this->userDefinedChannel->isTimeline($this->selectedTab, $this->session->getLocalUserId())) + && !in_array($this->selectedTab, [Channel::FOLLOWERS, Channel::FORYOU, Channel::DISCOVER])) { $this->page['aside'] .= $this->getNoSharerWidget('network'); } break; @@ -277,7 +277,7 @@ class Network extends Timeline } $o = Renderer::replaceMacros(Renderer::getMarkupTemplate('section_title.tpl'), [ - '$title' => $this->l10n->t('Circle: %s', $circle['name']) + '$title' => $this->l10n->t('Circle: %s', $circle['name']), ]) . $o; } elseif (Profile::shouldDisplayEventList($this->session->getLocalUserId(), $this->mode)) { $o .= Profile::getBirthdays($this->session->getLocalUserId()); @@ -309,7 +309,7 @@ class Network extends Timeline $this->args->getQueryString(), $items[array_key_first($items)][$this->order] ?? null, $items[array_key_last($items)][$this->order] ?? null, - $this->itemsPerPage + $this->itemsPerPage, ); $o .= $pager->renderMinimal(count($items)); @@ -364,7 +364,7 @@ class Network extends Timeline ]; $hook_data = $this->eventDispatcher->dispatch( - new ArrayFilterEvent(ArrayFilterEvent::NETWORK_CONTENT_TABS, $hook_data) + new ArrayFilterEvent(ArrayFilterEvent::NETWORK_CONTENT_TABS, $hook_data), )->getArray(); if (!empty($network_timelines)) { @@ -388,7 +388,7 @@ class Network extends Timeline { parent::parseRequest($request); - $this->circleId = (int)($this->parameters['circle_id'] ?? 0); + $this->circleId = (int) ($this->parameters['circle_id'] ?? 0); if (!$this->selectedTab) { $this->selectedTab = $this->getTimelineOrderBySession(); @@ -565,7 +565,7 @@ class Network extends Timeline if (!$this->mention && !$this->star) { foreach ($this->pConfig->get($this->session->getLocalUserId(), 'channel', 'timeline_channels') ?? [] as $channel) { if (is_numeric($channel)) { - $userchannels[] = (int)$channel; + $userchannels[] = (int) $channel; } else { $systemchannels[] = $channel; } diff --git a/src/Module/Debug/Babel.php b/src/Module/Debug/Babel.php index 65c1f18d52..7565d16113 100644 --- a/src/Module/Debug/Babel.php +++ b/src/Module/Debug/Babel.php @@ -42,19 +42,19 @@ class Babel extends BaseModule $bbcode = $request['text']; $results[] = [ 'title' => 'Source input', - 'content' => $visible_whitespace($bbcode) + 'content' => $visible_whitespace($bbcode), ]; $plain = Text\BBCode::toPlaintext($bbcode, false); $results[] = [ 'title' => 'BBCode::toPlaintext', - 'content' => $visible_whitespace($plain) + 'content' => $visible_whitespace($plain), ]; $html = Text\BBCode::convertForUriId(0, $bbcode); $results[] = [ 'title' => 'BBCode::convert (raw HTML)', - 'content' => $visible_whitespace($html) + 'content' => $visible_whitespace($html), ]; $results[] = [ @@ -64,41 +64,41 @@ class Babel extends BaseModule $results[] = [ 'title' => 'BBCode::convert', - 'content' => $html + 'content' => $html, ]; $bbcode2 = Text\HTML::toBBCode($html); $results[] = [ 'title' => 'BBCode::convert => HTML::toBBCode', - 'content' => $visible_whitespace($bbcode2) + 'content' => $visible_whitespace($bbcode2), ]; $markdown = Text\BBCode::toMarkdown($bbcode); $results[] = [ 'title' => 'BBCode::toMarkdown', - 'content' => $visible_whitespace($markdown) + 'content' => $visible_whitespace($markdown), ]; $html2 = Text\Markdown::convert($markdown); $results[] = [ 'title' => 'BBCode::toMarkdown => Markdown::convert (raw HTML)', - 'content' => $visible_whitespace($html2) + 'content' => $visible_whitespace($html2), ]; $results[] = [ 'title' => 'BBCode::toMarkdown => Markdown::convert', - 'content' => $html2 + 'content' => $html2, ]; $bbcode3 = Text\Markdown::toBBCode($markdown); $results[] = [ 'title' => 'BBCode::toMarkdown => Markdown::toBBCode', - 'content' => $visible_whitespace($bbcode3) + 'content' => $visible_whitespace($bbcode3), ]; $bbcode4 = Text\HTML::toBBCode($html2); $results[] = [ 'title' => 'BBCode::toMarkdown => Markdown::convert => HTML::toBBCode', - 'content' => $visible_whitespace($bbcode4) + 'content' => $visible_whitespace($bbcode4), ]; $tags = Text\BBCode::getTags($bbcode); @@ -106,7 +106,7 @@ class Babel extends BaseModule $body = Item::setHashtags($bbcode); $results[] = [ 'title' => 'Item Body', - 'content' => $visible_whitespace($body) + 'content' => $visible_whitespace($body), ]; $results[] = [ 'title' => 'Item Tags', @@ -116,16 +116,16 @@ class Babel extends BaseModule $body2 = PageInfo::searchAndAppendToBody($bbcode, true); $results[] = [ 'title' => 'PageInfo::appendToBody', - 'content' => $visible_whitespace($body2) + 'content' => $visible_whitespace($body2), ]; $html3 = Text\BBCode::convertForUriId(0, $body2); $results[] = [ 'title' => 'PageInfo::appendToBody => BBCode::convert (raw HTML)', - 'content' => $visible_whitespace($html3) + 'content' => $visible_whitespace($html3), ]; $results[] = [ 'title' => 'PageInfo::appendToBody => BBCode::convert', - 'content' => $html3 + 'content' => $html3, ]; break; case 'diaspora': @@ -153,7 +153,7 @@ class Babel extends BaseModule $results[] = [ 'title' => 'Markdown::convert', - 'content' => $html + 'content' => $html, ]; $bbcode = Text\Markdown::toBBCode($markdown); @@ -171,7 +171,7 @@ class Babel extends BaseModule $results[] = [ 'title' => 'HTML Input', - 'content' => $html + 'content' => $html, ]; $purified = Text\HTML::purify($html); @@ -194,18 +194,18 @@ class Babel extends BaseModule $bbcode = Text\HTML::toBBCode($html); $results[] = [ 'title' => 'HTML::toBBCode', - 'content' => $visible_whitespace($bbcode) + 'content' => $visible_whitespace($bbcode), ]; $html2 = Text\BBCode::convertForUriId(0, $bbcode); $results[] = [ 'title' => 'HTML::toBBCode => BBCode::convert', - 'content' => $html2 + 'content' => $html2, ]; $results[] = [ 'title' => 'HTML::toBBCode => BBCode::convert (raw HTML)', - 'content' => htmlspecialchars($html2) + 'content' => htmlspecialchars($html2), ]; $bbcode2plain = Text\BBCode::toPlaintext($bbcode); @@ -217,7 +217,7 @@ class Babel extends BaseModule $markdown = Text\HTML::toMarkdown($html); $results[] = [ 'title' => 'HTML::toMarkdown', - 'content' => $visible_whitespace($markdown) + 'content' => $visible_whitespace($markdown), ]; $text = Text\HTML::toPlaintext($html, 0); diff --git a/src/Module/Notifications/Ping.php b/src/Module/Notifications/Ping.php index 5885b41a2e..d9bc92897d 100644 --- a/src/Module/Notifications/Ping.php +++ b/src/Module/Notifications/Ping.php @@ -92,7 +92,7 @@ class Ping extends BaseModule $home_count = 0; $register_count = 0; $sysnotify_count = 0; - $circles_unseen = []; + $circles_unseen = []; $groups_unseen = []; $event_count = 0; @@ -110,12 +110,12 @@ class Ping extends BaseModule $condition = [ "`unseen` AND `uid` = ? AND NOT `origin` AND `wall` AND (`vid` != ? OR `vid` IS NULL)", - $this->session->getLocalUserId(), Verb::getID(Activity::FOLLOW) + $this->session->getLocalUserId(), Verb::getID(Activity::FOLLOW), ]; $home_count = Post::count($condition); - if ($this->config->get('system','compute_circle_counts')) { + if ($this->config->get('system', 'compute_circle_counts')) { // Find out how unseen network posts are spread across circles foreach (Circle::countUnseen($this->session->getLocalUserId()) as $circle_count) { if ($circle_count['count'] > 0) { @@ -138,16 +138,19 @@ class Ping extends BaseModule $mail_count = $this->database->count('mail', ["`uid` = ? AND NOT `seen` AND `from-url` != ?", $this->session->getLocalUserId(), $myurl]); if (Register::getPolicy() === Register::APPROVE && $this->session->isSiteAdmin()) { - $registrations = \Friendica\Model\Register::getPending(); + $registrations = \Friendica\Model\Register::getPending(); $register_count = count($registrations); } $cachekey = 'ping:events:' . $this->session->getLocalUserId(); $events = $this->cache->get($cachekey); if (is_null($events)) { - $events = $this->database->selectToArray('event', ['type', 'start'], + $events = $this->database->selectToArray( + 'event', + ['type', 'start'], ["`uid` = ? AND `start` < ? AND `finish` > ? AND NOT `ignore`", - $this->session->getLocalUserId(), DateTimeFormat::utc('now + 7 days'), DateTimeFormat::utcNow()]); + $this->session->getLocalUserId(), DateTimeFormat::utc('now + 7 days'), DateTimeFormat::utcNow()], + ); $this->cache->set($cachekey, $events, Duration::HOUR); } @@ -207,7 +210,7 @@ class Ping extends BaseModule $registration['url'], $this->l10n->t('{0} requested registration'), new \DateTime($registration['created'], new \DateTimeZone('UTC')), - new Uri($this->baseUrl . '/moderation/users/pending') + new Uri($this->baseUrl . '/moderation/users/pending'), ); } } else { @@ -216,7 +219,7 @@ class Ping extends BaseModule $registrations[0]['url'], $this->l10n->t('{0} and %d others requested registration', count($registrations) - 1), new \DateTime($registrations[0]['created'], new \DateTimeZone('UTC')), - new Uri($this->baseUrl . '/moderation/users/pending') + new Uri($this->baseUrl . '/moderation/users/pending'), ); } diff --git a/src/Module/Photo.php b/src/Module/Photo.php index d1ada02573..3acb154b8c 100644 --- a/src/Module/Photo.php +++ b/src/Module/Photo.php @@ -239,7 +239,7 @@ class Photo extends BaseApi 'scale' => $scale, 'resource' => $photo['resource-id'], 'total' => number_format($total, 3), 'fetch' => number_format($fetch, 3), 'data' => number_format($data, 3), 'checksum' => number_format($checksum, 3), - 'output' => number_format($output, 3), 'rest' => number_format($rest, 3) + 'output' => number_format($output, 3), 'rest' => number_format($rest, 3), ]); } @@ -294,7 +294,7 @@ class Photo extends BaseApi return MPhoto::getPhoto($matches[1], $matches[2], self::getCurrentUserID()); } - return MPhoto::createPhotoForExternalResource($url, (int)DI::userSession()->getLocalUserId(), $media['mimetype'] ?? '', $media['blurhash'], $width, $height); + return MPhoto::createPhotoForExternalResource($url, (int) DI::userSession()->getLocalUserId(), $media['mimetype'] ?? '', $media['blurhash'], $width, $height); case 'media': $media = DBA::selectFirst('post-media', ['url', 'height', 'width', 'mimetype', 'uri-id', 'blurhash'], ['id' => $id, 'type' => Post\Media::IMAGE]); if (empty($media)) { @@ -305,14 +305,14 @@ class Photo extends BaseApi return MPhoto::getPhoto($matches[1], $matches[2], self::getCurrentUserID()); } - return MPhoto::createPhotoForExternalResource($media['url'], (int)DI::userSession()->getLocalUserId(), $media['mimetype'], $media['blurhash'], $media['width'], $media['height']); + return MPhoto::createPhotoForExternalResource($media['url'], (int) DI::userSession()->getLocalUserId(), $media['mimetype'], $media['blurhash'], $media['width'], $media['height']); case 'link': $link = DBA::selectFirst('post-link', ['url', 'mimetype', 'blurhash', 'width', 'height'], ['id' => $id]); if (empty($link)) { return false; } - return MPhoto::createPhotoForExternalResource($link['url'], (int)DI::userSession()->getLocalUserId(), $link['mimetype'] ?? '', $link['blurhash'] ?? '', $link['width'] ?? 0, $link['height'] ?? 0); + return MPhoto::createPhotoForExternalResource($link['url'], (int) DI::userSession()->getLocalUserId(), $link['mimetype'] ?? '', $link['blurhash'] ?? '', $link['width'] ?? 0, $link['height'] ?? 0); case 'contact': $fields = ['uid', 'uri-id', 'url', 'nurl', 'avatar', 'photo', 'blurhash', 'xmpp', 'addr', 'network', 'failed', 'updated', 'next-update']; $contact = Contact::getById($id, $fields); diff --git a/src/Module/User/Import.php b/src/Module/User/Import.php index 370f7d446a..895b98f1d7 100644 --- a/src/Module/User/Import.php +++ b/src/Module/User/Import.php @@ -34,8 +34,8 @@ use Psr\Log\LoggerInterface; class Import extends \Friendica\BaseModule { - const IMPORT_DEBUG = false; - const MEMORY_LIMIT = 67108864; // 64MB + public const IMPORT_DEBUG = false; + public const MEMORY_LIMIT = 67108864; // 64MB /** @var IManageConfigValues */ private $config; @@ -237,7 +237,7 @@ class Import extends \Friendica\BaseModule $account['circle_member'] ??= $account['group_member']; $oldBaseUrl = $account['baseurl']; - $newBaseUrl = (string)$this->baseUrl; + $newBaseUrl = (string) $this->baseUrl; $oldAddr = str_replace('http://', '@', Strings::normaliseLink($oldBaseUrl)); $newAddr = str_replace('http://', '@', Strings::normaliseLink($newBaseUrl)); @@ -404,7 +404,7 @@ class Import extends \Friendica\BaseModule $photo['allow_cid'], $photo['allow_gid'], $photo['deny_cid'], - $photo['deny_gid'] + $photo['deny_gid'], ); if ($r === false) { diff --git a/src/Navigation/Notifications/Repository/Notify.php b/src/Navigation/Notifications/Repository/Notify.php index 2a97573e8a..9c085f09f3 100644 --- a/src/Navigation/Notifications/Repository/Notify.php +++ b/src/Navigation/Notifications/Repository/Notify.php @@ -200,7 +200,7 @@ class Notify extends BaseRepository $Notify->link, $Notify->parent, $Notify->otype, - $Notify->uid + $Notify->uid, ]; return $this->db->update(self::$table_name, ['seen' => true], $condition); } @@ -261,7 +261,7 @@ class Notify extends BaseRepository } } - $siteurl = (string)$this->baseUrl; + $siteurl = (string) $this->baseUrl; $sitename = $this->config->get('config', 'sitename'); // with $params['show_in_notification_page'] == false, the notification isn't inserted into @@ -354,7 +354,7 @@ class Notify extends BaseRepository $epreamble = $l10n->t( '%1$s posted to [url=%2$s]your wall[/url]', '[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]', - $params['link'] + $params['link'], ); $sitelink = $l10n->t('Please visit %s to view and/or reply to the conversation.'); @@ -371,7 +371,7 @@ class Notify extends BaseRepository $epreamble = $l10n->t( 'You\'ve received [url=%1$s]an introduction[/url] from %2$s.', $itemlink, - '[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]' + '[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]', ); $body = $l10n->t('You may visit their profile at %s', $params['source_link']); @@ -389,7 +389,7 @@ class Notify extends BaseRepository $epreamble = $l10n->t( '%1$s is your friend at %2$s', '[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]', - $sitename + $sitename, ); break; case Activity::FOLLOW: @@ -400,7 +400,7 @@ class Notify extends BaseRepository $epreamble = $l10n->t( 'You have a new follower at %2$s : %1$s', '[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]', - $sitename + $sitename, ); break; default: @@ -418,7 +418,7 @@ class Notify extends BaseRepository 'You\'ve received [url=%1$s]a friend suggestion[/url] for %2$s from %3$s.', $itemlink, '[url=' . $params['item']['url'] . ']' . $params['item']['name'] . '[/url]', - '[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]' + '[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]', ); $body = $l10n->t('Name:') . ' ' . $params['item']['name'] . "\n"; @@ -439,7 +439,7 @@ class Notify extends BaseRepository $epreamble = $l10n->t( '%2$s has accepted your [url=%1$s]connection request[/url].', $itemlink, - '[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]' + '[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]', ); $body = $l10n->t('You are now friends and may exchange status updates, photos, and messages without restriction.'); @@ -455,7 +455,7 @@ class Notify extends BaseRepository $epreamble = $l10n->t( '%2$s has accepted your [url=%1$s]connection request[/url].', $itemlink, - '[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]' + '[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]', ); $body = $l10n->t('\'%1$s\' has chosen to accept you a fan, which restricts some forms of communication - such as private messaging and some profile interactions. If this is a celebrity or community page, these settings were applied automatically.', $params['source_name']); @@ -478,7 +478,7 @@ class Notify extends BaseRepository $epreamble = $l10n->t( 'You\'ve received a [url=%1$s]registration request[/url] from %2$s.', $itemlink, - '[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]' + '[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]', ); $body = $l10n->t( @@ -486,7 +486,7 @@ class Notify extends BaseRepository $params['source_name'], $siteurl, $params['source_mail'], - $params['source_nick'] + $params['source_nick'], ); $sitelink = $l10n->t('Please visit %s to approve or reject the request.'); @@ -502,7 +502,7 @@ class Notify extends BaseRepository $epreamble = $l10n->t( 'You\'ve received a [url=%1$s]new registration[/url] from %2$s.', $itemlink, - '[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]' + '[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]', ); $body = $l10n->t( @@ -510,7 +510,7 @@ class Notify extends BaseRepository $params['source_name'], $siteurl, $params['source_mail'], - $params['source_nick'] + $params['source_nick'], ); $sitelink = $l10n->t('Please visit %s to have a look at the new registration.'); @@ -570,7 +570,7 @@ class Notify extends BaseRepository 'sitelink' => $sitelink, 'tsitelink' => $tsitelink, 'hsitelink' => $hsitelink, - 'itemlink' => $itemlink + 'itemlink' => $itemlink, ]; $hook_data = $this->eventDispatcher->dispatch( @@ -625,7 +625,7 @@ class Notify extends BaseRepository 'notify-id' => $notify_id, 'master-parent-uri-id' => $parent_uri_id, 'receiver-uid' => $params['uid'], - 'parent-item' => 0 + 'parent-item' => 0, ]; DBA::insert('notify-threads', $fields); @@ -676,7 +676,7 @@ class Notify extends BaseRepository $emailBuilder->withPhoto( $hook_data['source_photo'], $hook_data['source_link'] ?? $sitelink, - $hook_data['source_name'] ?? $sitename + $hook_data['source_name'] ?? $sitename, ); } @@ -766,7 +766,7 @@ class Notify extends BaseRepository $Notification->uid, Model\Item::ITEM_FIELDLIST, ['uid' => [0, $Notification->uid], 'uri-id' => $Notification->targetUriId, 'deleted' => false], - ['order' => ['uid' => true]] + ['order' => ['uid' => true]], ); if (empty($item)) { $this->logger->info('Item not found', ['uri-id' => $Notification->targetUriId, 'type' => $Notification->type]); @@ -789,7 +789,7 @@ class Notify extends BaseRepository $condition = [ 'type' => [Model\Notification\Type::TAG_SELF, Model\Notification\Type::COMMENT, Model\Notification\Type::SHARE], 'link' => $params['link'], - 'verb' => Activity::POST + 'verb' => Activity::POST, ]; if ($this->existsForUser($Notification->uid, $condition)) { $this->logger->info('Duplicate found, quitting', $condition + ['uid' => $Notification->uid]); @@ -838,7 +838,7 @@ class Notify extends BaseRepository $epreamble = $msg['rich']; $sitename = $this->config->get('config', 'sitename'); - $siteurl = (string)$this->baseUrl; + $siteurl = (string) $this->baseUrl; $sitelink = $l10n->t('Please visit %s to view and/or reply to the conversation.'); $tsitelink = sprintf($sitelink, $siteurl); diff --git a/src/Network/HTTPClient/Client/HttpClient.php b/src/Network/HTTPClient/Client/HttpClient.php index be0ec704c6..a1dc8bba69 100644 --- a/src/Network/HTTPClient/Client/HttpClient.php +++ b/src/Network/HTTPClient/Client/HttpClient.php @@ -93,7 +93,7 @@ class HttpClient implements ICanSendHttpRequests } } $parts['path'] = implode('/', $parts2); - $url = (string)Uri::fromParts((array)$parts); + $url = (string) Uri::fromParts((array) $parts); if (Network::isUrlBlocked($url)) { $this->logger->info('Domain is blocked.', ['url' => $url]); @@ -147,8 +147,8 @@ class HttpClient implements ICanSendHttpRequests $conf[RequestOptions::ON_HEADERS] = function (ResponseInterface $response) use ($opts) { if ( - !empty($opts[HttpClientOptions::CONTENT_LENGTH]) && - (int)$response->getHeaderLine('Content-Length') > $opts[HttpClientOptions::CONTENT_LENGTH] + !empty($opts[HttpClientOptions::CONTENT_LENGTH]) + && (int) $response->getHeaderLine('Content-Length') > $opts[HttpClientOptions::CONTENT_LENGTH] ) { throw new TransferException('The file is too big!'); } @@ -168,14 +168,14 @@ class HttpClient implements ICanSendHttpRequests return new GuzzleResponse($response, $url); } catch (TransferException $exception) { if ( - $exception instanceof RequestException && - $exception->hasResponse() + $exception instanceof RequestException + && $exception->hasResponse() ) { return new GuzzleResponse($exception->getResponse(), $url, $exception->getCode(), ''); } else { return new CurlResult($this->logger, $url, '', ['http_code' => 500], $exception->getCode(), ''); } - } catch (InvalidArgumentException | \InvalidArgumentException $argumentException) { + } catch (InvalidArgumentException|\InvalidArgumentException $argumentException) { $this->logger->info('Invalid Argument for HTTP call.', ['url' => $url, 'method' => $method, 'exception' => $argumentException]); return new CurlResult($this->logger, $url, '', ['http_code' => 500], $argumentException->getCode(), $argumentException->getMessage()); } finally { @@ -279,7 +279,7 @@ class HttpClient implements ICanSendHttpRequests HttpClientOptions::TIMEOUT => $timeout, HttpClientOptions::COOKIEJAR => $cookiejar, HttpClientOptions::REQUEST => $request, - ] + ], ); return $ret->getBodyString(); } catch (\Throwable $th) { @@ -291,7 +291,7 @@ class HttpClient implements ICanSendHttpRequests private function getUserAgent(string $type = ''): string { // @see https://developers.whatismybrowser.com/learn/browser-detection/user-agents/user-agent-best-practices - $userAgent = App::PLATFORM . '/' . App::VERSION . ' DatabaseVersion/' . DB_UPDATE_VERSION; + $userAgent = App::PLATFORM . '/' . App::VERSION . ' DatabaseVersion/' . DB_UPDATE_VERSION; if ($type != '') { $userAgent .= ' Request/' . $type; } diff --git a/src/Network/HTTPClient/Response/CurlResult.php b/src/Network/HTTPClient/Response/CurlResult.php index 039f7d5619..f50b0fa637 100644 --- a/src/Network/HTTPClient/Response/CurlResult.php +++ b/src/Network/HTTPClient/Response/CurlResult.php @@ -225,7 +225,7 @@ class CurlResult implements ICanHandleHttpResponses } } - $this->redirectUrl = (string)Uri::fromParts((array)$redirect_parts); + $this->redirectUrl = (string) Uri::fromParts((array) $redirect_parts); $this->isRedirectUrl = true; $this->redirectIsPermanent = $this->returnCode == 301 || $this->returnCode == 308; } else { diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 3beeb53203..90a130e7ad 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -227,12 +227,12 @@ class Probe unset($data['networks']); if (!empty($data['network'])) { $networks[$data['network']] = $data; - $ap_profile['guid'] ??= $data['guid'] ?? null; - $ap_profile['about'] ??= $data['about'] ?? null; - $ap_profile['keywords'] = $data['keywords'] ?? null; - $ap_profile['location'] = $data['location'] ?? null; - $ap_profile['poco'] = $data['poco'] ?? null; - $ap_profile['openwebauth'] = $data['openwebauth'] ?? null; + $ap_profile['guid'] ??= $data['guid'] ?? null; + $ap_profile['about'] ??= $data['about'] ?? null; + $ap_profile['keywords'] = $data['keywords'] ?? null; + $ap_profile['location'] = $data['location'] ?? null; + $ap_profile['poco'] = $data['poco'] ?? null; + $ap_profile['openwebauth'] = $data['openwebauth'] ?? null; } $data = $ap_profile; $data['networks'] = $networks; diff --git a/src/Object/Api/Mastodon/Status.php b/src/Object/Api/Mastodon/Status.php index c5b42d4b1e..742f43ab84 100644 --- a/src/Object/Api/Mastodon/Status.php +++ b/src/Object/Api/Mastodon/Status.php @@ -98,14 +98,14 @@ class Status extends BaseDataTransferObject public function __construct(array $item, Account $account, Counts $counts, UserAttributes $userAttributes, bool $sensitive, Application $application, array $mentions, array $tags, Card $card, array $attachments, array $in_reply, array $reblog, FriendicaExtension $friendica, array $quote = null, array $poll = null, array $emojis = null) { $reblogged = !empty($reblog); - $this->id = (string)$item['uri-id']; + $this->id = (string) $item['uri-id']; $this->created_at = DateTimeFormat::utc($item['created'], DateTimeFormat::JSON); $this->edited_at = DateTimeFormat::utc($item['edited'], DateTimeFormat::JSON); if ($item['gravity'] == Item::GRAVITY_COMMENT) { - $this->in_reply_to_id = (string)$item['thr-parent-id']; + $this->in_reply_to_id = (string) $item['thr-parent-id']; $this->in_reply_to_status = $in_reply; - $this->in_reply_to_account_id = (string)$item['parent-author-id']; + $this->in_reply_to_account_id = (string) $item['parent-author-id']; } $this->sensitive = $sensitive; diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index d8dbe66a76..3f0aabe93e 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -43,8 +43,8 @@ use Friendica\Util\XML; */ class Transmitter { - const CACHEKEY_FEATURED = 'transmitter:getFeatured:'; - const CACHEKEY_CONTACTS = 'transmitter:getContacts:'; + public const CACHEKEY_FEATURED = 'transmitter:getFeatured:'; + public const CACHEKEY_CONTACTS = 'transmitter:getContacts:'; /** * Add relay servers to the list of inboxes @@ -248,7 +248,7 @@ class Transmitter $condition = [ "`uri-id` IN (SELECT `uri-id` FROM `collection-view` WHERE `cid` = ? AND `type` = ?)", - $owner_cid, Post\Collection::FEATURED + $owner_cid, Post\Collection::FEATURED, ]; $condition = DBA::mergeConditions($condition, [ @@ -260,7 +260,7 @@ class Transmitter 'parent-network' => Protocol::FEDERATED, 'origin' => true, 'deleted' => false, - 'visible' => true + 'visible' => true, ]); $count = Post::count($condition); @@ -315,10 +315,10 @@ class Transmitter public static function getService(): array { return [ - 'id' => (string)DI::baseUrl() . '/friendica', + 'id' => (string) DI::baseUrl() . '/friendica', 'type' => 'Application', 'name' => App::PLATFORM . " '" . App::CODENAME . "' " . App::VERSION . '-' . DB_UPDATE_VERSION, - 'url' => (string)DI::baseUrl(), + 'url' => (string) DI::baseUrl(), ]; } @@ -365,7 +365,7 @@ class Transmitter if ($full && !empty($owner['country-name'] . $owner['region'] . $owner['locality'])) { $data['vcard:hasAddress'] = [ '@type' => 'vcard:Home', 'vcard:country-name' => $owner['country-name'], - 'vcard:region' => $owner['region'], 'vcard:locality' => $owner['locality'] + 'vcard:region' => $owner['region'], 'vcard:locality' => $owner['locality'], ]; } @@ -386,11 +386,11 @@ class Transmitter $data['url'] = $owner['url']; $data['manuallyApprovesFollowers'] = in_array($owner['page-flags'], [User::PAGE_FLAGS_NORMAL, User::PAGE_FLAGS_PRVGROUP]); - $data['discoverable'] = (bool)$owner['net-publish'] && $full; + $data['discoverable'] = (bool) $owner['net-publish'] && $full; $data['publicKey'] = [ 'id' => $owner['url'] . '#main-key', 'owner' => $owner['url'], - 'publicKeyPem' => $owner['pubkey'] + 'publicKeyPem' => $owner['pubkey'], ]; $data['endpoints'] = ['sharedInbox' => DI::baseUrl() . '/inbox']; if ($full && $uid != 0) { @@ -422,7 +422,7 @@ class Transmitter $custom_fields[] = [ 'type' => 'PropertyValue', 'name' => $profile_field->label, - 'value' => BBCode::convertForUriId($owner['uri-id'], $profile_field->value) + 'value' => BBCode::convertForUriId($owner['uri-id'], $profile_field->value), ]; }; @@ -454,7 +454,7 @@ class Transmitter 'name' => $contact['name'], 'icon' => ['type' => 'Image', 'url' => Contact::getAvatarUrlForId($cid, '', $contact['updated'])], 'image' => ['type' => 'Image', 'url' => Contact::getHeaderUrlForId($cid, '', $contact['updated'])], - 'manuallyApprovesFollowers' => (bool)$contact['manually-approve'], + 'manuallyApprovesFollowers' => (bool) $contact['manually-approve'], 'discoverable' => !$contact['unsearchable'], ]; @@ -1311,7 +1311,7 @@ class Transmitter */ public static function createCachedActivityFromItem(int $item_id, bool $force = false, bool $object_mode = false, $announce_activity = false) { - $cachekey = 'APDelivery:createActivity:' . $item_id . ':' . (int)$object_mode . ':' . (int)$announce_activity; + $cachekey = 'APDelivery:createActivity:' . $item_id . ':' . (int) $object_mode . ':' . (int) $announce_activity; if (!$force) { $data = DI::cache()->get($cachekey); @@ -1701,7 +1701,7 @@ class Transmitter // otherwise we just return the link return '[url]' . $match[1] . '[/url]'; }, - $text + $text, ); // Remove all pictures @@ -1834,7 +1834,7 @@ class Transmitter } else { $data['attributedTo'] = $item['author-link']; } - $data['sensitive'] = (bool)$item['sensitive']; + $data['sensitive'] = (bool) $item['sensitive']; if (!empty($item['context']) && ($item['context'] != './')) { $data['context'] = $item['context']; @@ -1955,8 +1955,8 @@ class Transmitter if ($item['private'] != Item::PRIVATE) { $data['interactionPolicy'] = [ 'canQuote' => [ - 'automaticApproval' => [ActivityPub::PUBLIC_COLLECTION] - ] + 'automaticApproval' => [ActivityPub::PUBLIC_COLLECTION], + ], ]; } @@ -1966,7 +1966,7 @@ class Transmitter $data['replies'] = [ 'id' => $item['uri'] . '/replies', 'type' => 'Collection', - 'totalItems' => Post::countPosts(['thr-parent-id' => $item['uri-id'], 'gravity' => Item::GRAVITY_COMMENT, 'deleted' => false, 'private' => [Item::PUBLIC, Item::UNLISTED]]) + 'totalItems' => Post::countPosts(['thr-parent-id' => $item['uri-id'], 'gravity' => Item::GRAVITY_COMMENT, 'deleted' => false, 'private' => [Item::PUBLIC, Item::UNLISTED]]), ]; if (empty($data['location']) && (!empty($item['coord']) || !empty($item['location']))) { @@ -2026,9 +2026,9 @@ class Transmitter $activity['diaspora:guid'] = $item['guid']; $activity['actor'] = $item['author-link']; - $activity['target'] = (string)$target->id; + $activity['target'] = (string) $target->id; $activity['summary'] = BBCode::toPlaintext($item['body']); - $activity['object'] = ['id' => (string)$object->id, 'type' => 'tag', 'name' => (string)$object->title, 'content' => (string)$object->content]; + $activity['object'] = ['id' => (string) $object->id, 'type' => 'tag', 'name' => (string) $object->title, 'content' => (string) $object->content]; return $activity; } @@ -2159,7 +2159,7 @@ class Transmitter 'content' => $suggestion->note, 'instrument' => self::getService(), 'to' => [ActivityPub::PUBLIC_COLLECTION], - 'cc' => [] + 'cc' => [], ]; $signed = LDSignature::sign($data, $owner); @@ -2187,7 +2187,7 @@ class Transmitter 'published' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), 'instrument' => self::getService(), 'to' => [ActivityPub::PUBLIC_COLLECTION], - 'cc' => [] + 'cc' => [], ]; $signed = LDSignature::sign($data, $owner); @@ -2220,7 +2220,7 @@ class Transmitter 'published' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), 'instrument' => self::getService(), 'to' => [ActivityPub::PUBLIC_COLLECTION], - 'cc' => [] + 'cc' => [], ]; $signed = LDSignature::sign($data, $owner); @@ -2252,7 +2252,7 @@ class Transmitter 'published' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), 'instrument' => self::getService(), 'to' => [$profile['followers']], - 'cc' => [] + 'cc' => [], ]; $signed = LDSignature::sign($data, $owner); @@ -2340,7 +2340,7 @@ class Transmitter $condition = [ 'verb' => Activity::FOLLOW, 'uid' => 0, 'parent-uri' => $object, - 'author-id' => Contact::getPublicIdByUserId($uid) + 'author-id' => Contact::getPublicIdByUserId($uid), ]; if (Post::exists($condition)) { DI::logger()->info('Follow for ' . $object . ' for user ' . $uid . ' does already exist.'); @@ -2398,7 +2398,7 @@ class Transmitter 'id' => $id, 'type' => 'Follow', 'actor' => $profile['url'], - 'object' => $owner['url'] + 'object' => $owner['url'], ], 'instrument' => self::getService(), 'to' => [$profile['url']], @@ -2437,7 +2437,7 @@ class Transmitter 'id' => $objectId, 'type' => 'Follow', 'actor' => $profile['url'], - 'object' => $owner['url'] + 'object' => $owner['url'], ], 'instrument' => self::getService(), 'to' => [$profile['url']], @@ -2484,7 +2484,7 @@ class Transmitter 'id' => $object_id, 'type' => 'Follow', 'actor' => $owner['url'], - 'object' => $profile['url'] + 'object' => $profile['url'], ], 'instrument' => self::getService(), 'to' => [$profile['url']], @@ -2531,7 +2531,7 @@ class Transmitter 'id' => $object_id, 'type' => 'Block', 'actor' => $owner['url'], - 'object' => $profile['url'] + 'object' => $profile['url'], ], 'instrument' => self::getService(), 'to' => [$profile['url']], diff --git a/src/Protocol/Feed.php b/src/Protocol/Feed.php index 9e3fb8d4b5..140b38ec28 100644 --- a/src/Protocol/Feed.php +++ b/src/Protocol/Feed.php @@ -495,7 +495,7 @@ class Feed if (!$dryRun) { $condition = [ "`uid` = ? AND `uri` = ? AND `network` IN (?, ?)", - $importer['uid'], $item['uri'], Protocol::FEED, Protocol::DFRN + $importer['uid'], $item['uri'], Protocol::FEED, Protocol::DFRN, ]; $previous = Post::selectFirst(['id', 'created'], $condition); if (DBA::isResult($previous)) { @@ -544,7 +544,7 @@ class Feed if (in_array($attribute->name, ['url', 'href'])) { $href = $attribute->textContent; } elseif ($attribute->name == 'length') { - $length = (int)$attribute->textContent; + $length = (int) $attribute->textContent; } elseif ($attribute->name == 'type') { $type = $attribute->textContent; } @@ -665,7 +665,7 @@ class Feed $item['plink'], false, $fetch_further_information == LocalRelationship::FFI_BOTH, - $contact['ffi_keyword_denylist'] ?? '' + $contact['ffi_keyword_denylist'] ?? '', ); if (!empty($data)) { @@ -712,7 +712,7 @@ class Feed DI::logger()->info('Stored feed', ['item' => $item]); $notify = Item::isRemoteSelf($contact, $item); - $item['wall'] = (bool)$notify; + $item['wall'] = (bool) $notify; // Distributed items should have a well-formatted URI. // Additionally, we have to avoid conflicts with identical URI between imported feeds and these items. @@ -734,7 +734,7 @@ class Feed } else { $postings[] = [ 'item' => $item, 'notify' => $notify, - 'taglist' => $taglist, 'attachments' => $attachments + 'taglist' => $taglist, 'attachments' => $attachments, ]; } } else { @@ -1027,7 +1027,7 @@ class Feed $owner['uid'], $check_date, Item::GRAVITY_PARENT, Item::GRAVITY_COMMENT, Item::GRAVITY_ACTIVITY, Activity::ANNOUNCE, Item::PRIVATE, Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, - $authorid + $authorid, ]; if ($filter === 'comments') { @@ -1208,8 +1208,8 @@ class Feed '', [ 'rel' => 'alternate', 'type' => 'text/html', - 'href' => DI::baseUrl() . '/display/' . $item['guid'] - ] + 'href' => DI::baseUrl() . '/display/' . $item['guid'], + ], ); XML::addElement($doc, $entry, 'published', DateTimeFormat::utc($item['created'] . '+00:00', DateTimeFormat::ATOM)); @@ -1250,13 +1250,13 @@ class Feed if (isset($parent_plink)) { $attributes = [ 'ref' => $item['thr-parent'], - 'href' => $parent_plink + 'href' => $parent_plink, ]; XML::addElement($doc, $entry, 'thr:in-reply-to', '', $attributes); $attributes = [ 'rel' => 'related', - 'href' => $parent_plink + 'href' => $parent_plink, ]; XML::addElement($doc, $entry, 'link', '', $attributes); } @@ -1410,9 +1410,9 @@ class Feed if ($owner['contact-type'] == Contact::TYPE_COMMUNITY) { $entry->setAttribute('xmlns:activity', ActivityNamespace::ACTIVITY); - $contact = Contact::getByURL($item['author-link']) ?: $owner; + $contact = Contact::getByURL($item['author-link']) ?: $owner; $contact['nickname'] ??= $contact['nick']; - $author = self::addAuthor($doc, $contact); + $author = self::addAuthor($doc, $contact); $entry->appendChild($author); } } else { diff --git a/src/Security/OAuth1/OAuthRequest.php b/src/Security/OAuth1/OAuthRequest.php index 1502604e43..5318e12f1e 100644 --- a/src/Security/OAuth1/OAuthRequest.php +++ b/src/Security/OAuth1/OAuthRequest.php @@ -16,16 +16,16 @@ class OAuthRequest private $http_url; // for debug purposes public $base_string; - public static $version = '1.0'; + public static $version = '1.0'; public static $POST_INPUT = 'php://input'; - function __construct($http_method, $http_url, $parameters = null) + public function __construct($http_method, $http_url, $parameters = null) { @$parameters or $parameters = []; - $parameters = array_merge(OAuthUtil::parse_parameters(parse_url($http_url, PHP_URL_QUERY)), $parameters); - $this->parameters = $parameters; - $this->http_method = $http_method; - $this->http_url = $http_url; + $parameters = array_merge(OAuthUtil::parse_parameters(parse_url($http_url, PHP_URL_QUERY)), $parameters); + $this->parameters = $parameters; + $this->http_method = $http_method; + $this->http_url = $http_url; } @@ -43,11 +43,11 @@ class OAuthRequest $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") ? 'http' : 'https'; - @$http_url or $http_url = $scheme . - '://' . $_SERVER['HTTP_HOST'] . - ':' . - $_SERVER['SERVER_PORT'] . - $_SERVER['REQUEST_URI']; + @$http_url or $http_url = $scheme + . '://' . $_SERVER['HTTP_HOST'] + . ':' + . $_SERVER['SERVER_PORT'] + . $_SERVER['REQUEST_URI']; @$http_method or $http_method = $_SERVER['REQUEST_METHOD']; // We weren't handed any parameters, so let's find the ones relevant to @@ -67,11 +67,11 @@ class OAuthRequest $http_method == "POST" && @strstr( $request_headers["Content-Type"], - "application/x-www-form-urlencoded" + "application/x-www-form-urlencoded", ) ) { - $post_data = OAuthUtil::parse_parameters( - file_get_contents(self::$POST_INPUT) + $post_data = OAuthUtil::parse_parameters( + file_get_contents(self::$POST_INPUT), ); $parameters = array_merge($parameters, $post_data); } @@ -80,9 +80,9 @@ class OAuthRequest // and add those overriding any duplicates from GET or POST if (@substr($request_headers['Authorization'], 0, 6) == "OAuth ") { $header_parameters = OAuthUtil::split_header( - $request_headers['Authorization'] + $request_headers['Authorization'], ); - $parameters = array_merge($parameters, $header_parameters); + $parameters = array_merge($parameters, $header_parameters); } } // fix for friendica redirect system @@ -107,14 +107,15 @@ class OAuthRequest public static function from_consumer_and_token(OAuthConsumer $consumer, $http_method, $http_url, array $parameters = null, OAuthToken $token = null) { @$parameters or $parameters = []; - $defaults = [ + $defaults = [ "oauth_version" => OAuthRequest::$version, "oauth_nonce" => OAuthRequest::generate_nonce(), "oauth_timestamp" => OAuthRequest::generate_timestamp(), "oauth_consumer_key" => $consumer->key, ]; - if ($token) + if ($token) { $defaults['oauth_token'] = $token->key; + } $parameters = array_merge($defaults, $parameters); @@ -244,10 +245,11 @@ class OAuthRequest */ public function to_postdata(bool $raw = false) { - if ($raw) + if ($raw) { return $this->parameters; - else + } else { return OAuthUtil::build_http_query($this->parameters); + } } /** @@ -264,19 +266,22 @@ class OAuthRequest if ($realm) { $out = 'Authorization: OAuth realm="' . OAuthUtil::urlencode_rfc3986($realm) . '"'; $first = false; - } else + } else { $out = 'Authorization: OAuth'; + } foreach ($this->parameters as $k => $v) { - if (substr($k, 0, 5) != "oauth") continue; + if (substr($k, 0, 5) != "oauth") { + continue; + } if (is_array($v)) { throw new OAuthException('Arrays not supported in headers'); } - $out .= ($first) ? ' ' : ','; - $out .= OAuthUtil::urlencode_rfc3986($k) . - '="' . - OAuthUtil::urlencode_rfc3986($v) . - '"'; + $out .= ($first) ? ' ' : ','; + $out .= OAuthUtil::urlencode_rfc3986($k) + . '="' + . OAuthUtil::urlencode_rfc3986($v) + . '"'; $first = false; } return $out; @@ -293,7 +298,7 @@ class OAuthRequest $this->set_parameter( "oauth_signature_method", $signature_method->get_name(), - false + false, ); $signature = $this->build_signature($signature_method, $consumer, $token); $this->set_parameter("oauth_signature", $signature, false); diff --git a/src/Util/EMailer/MailBuilder.php b/src/Util/EMailer/MailBuilder.php index 2979de3035..a5e4497460 100644 --- a/src/Util/EMailer/MailBuilder.php +++ b/src/Util/EMailer/MailBuilder.php @@ -25,7 +25,7 @@ use Psr\Log\LoggerInterface; abstract class MailBuilder { /** @var string The default email banner in case nothing else is defined */ - const DEFAULT_EMAIL_BANNER = 'images/friendica-32.png'; + public const DEFAULT_EMAIL_BANNER = 'images/friendica-32.png'; /** @var L10n */ protected $l10n; @@ -199,7 +199,7 @@ abstract class MailBuilder * * @return static */ - public function setHeader(string $name, string $value) + public function setHeader(string $name, string $value) { $this->headers[$name] = [$value]; @@ -218,8 +218,8 @@ abstract class MailBuilder */ public function build(bool $raw = false) { - if ((empty($this->recipientAddress)) && - !empty($this->recipientUid)) { + if ((empty($this->recipientAddress)) + && !empty($this->recipientUid)) { $user = User::getById($this->recipientUid, ['email']); if (!empty($user['email'])) { @@ -247,8 +247,11 @@ abstract class MailBuilder '$product' => App::PLATFORM, '$htmlversion' => $msgHtml, '$sitename' => $this->config->get('config', 'sitename'), - '$banner' => $this->config->get('system', 'email_banner', - $this->baseUrl . DIRECTORY_SEPARATOR . self::DEFAULT_EMAIL_BANNER), + '$banner' => $this->config->get( + 'system', + 'email_banner', + $this->baseUrl . DIRECTORY_SEPARATOR . self::DEFAULT_EMAIL_BANNER, + ), ]); } @@ -261,6 +264,7 @@ abstract class MailBuilder $msgHtml, $this->getPlaintextMessage() ?? '', $this->headers, - $this->recipientUid ?? null); + $this->recipientUid ?? null, + ); } } diff --git a/src/Util/Emailer.php b/src/Util/Emailer.php index e7313db272..e8f8b05ba6 100644 --- a/src/Util/Emailer.php +++ b/src/Util/Emailer.php @@ -99,7 +99,7 @@ class Emailer $this->config, $this->logger, $this->getSiteEmailAddress(), - $this->getSiteEmailName() + $this->getSiteEmailName(), ); } @@ -116,7 +116,7 @@ class Emailer $this->config, $this->logger, $this->getSiteEmailAddress(), - $this->getSiteEmailName() + $this->getSiteEmailName(), ); } @@ -169,29 +169,29 @@ class Emailer } // generate a multipart/alternative message header - $messageHeader .= - "From: $fromName <{$fromAddress}>\r\n" . - "Reply-To: $fromName <{$replyTo}>\r\n" . - "MIME-Version: 1.0\r\n" . - "Content-Type: multipart/alternative; boundary=\"{$mimeBoundary}\""; + $messageHeader + .= "From: $fromName <{$fromAddress}>\r\n" + . "Reply-To: $fromName <{$replyTo}>\r\n" + . "MIME-Version: 1.0\r\n" + . "Content-Type: multipart/alternative; boundary=\"{$mimeBoundary}\""; // assemble the final multipart message body with the text and html types included $textBody = chunk_split(base64_encode($email->getMessage(true))); $htmlBody = chunk_split(base64_encode($email->getMessage())); - $multipartMessageBody = "--" . $mimeBoundary . "\n" . // plain text section - "Content-Type: text/plain; charset=UTF-8\n" . - "Content-Transfer-Encoding: base64\n\n" . - $textBody . "\n"; + $multipartMessageBody = "--" . $mimeBoundary . "\n" // plain text section + . "Content-Type: text/plain; charset=UTF-8\n" + . "Content-Transfer-Encoding: base64\n\n" + . $textBody . "\n"; if (!$email_textonly && !is_null($email->getMessage())) { - $multipartMessageBody .= - "--" . $mimeBoundary . "\n" . // text/html section - "Content-Type: text/html; charset=UTF-8\n" . - "Content-Transfer-Encoding: base64\n\n" . - $htmlBody . "\n"; + $multipartMessageBody + .= "--" . $mimeBoundary . "\n" // text/html section + . "Content-Type: text/html; charset=UTF-8\n" + . "Content-Transfer-Encoding: base64\n\n" + . $htmlBody . "\n"; } - $multipartMessageBody .= - "--" . $mimeBoundary . "--\n"; // message ending + $multipartMessageBody + .= "--" . $mimeBoundary . "--\n"; // message ending if ($this->config->get('system', 'sendmail_params', true)) { $sendmail_params = '-f ' . $fromAddress; @@ -220,7 +220,7 @@ class Emailer $hookdata['subject'], $hookdata['body'], $hookdata['headers'], - $hookdata['parameters'] + $hookdata['parameters'], ); $this->logger->debug('Email message header', ['To' => $email->getToAddress(), 'messageHeader' => $messageHeader, 'return' => ($res) ? 'true' : 'false']); diff --git a/src/Util/ParseUrl.php b/src/Util/ParseUrl.php index 1a53d08c97..d30e77490e 100644 --- a/src/Util/ParseUrl.php +++ b/src/Util/ParseUrl.php @@ -32,18 +32,18 @@ use Friendica\Model\Post; */ class ParseUrl { - const DEFAULT_EXPIRATION_FAILURE = 'now + 1 day'; - const DEFAULT_EXPIRATION_SUCCESS = 'now + 3 months'; + public const DEFAULT_EXPIRATION_FAILURE = 'now + 1 day'; + public const DEFAULT_EXPIRATION_SUCCESS = 'now + 3 months'; /** * Maximum number of characters for the description */ - const MAX_DESC_COUNT = 250; + public const MAX_DESC_COUNT = 250; /** * Minimum number of characters for the description */ - const MIN_DESC_COUNT = 100; + public const MIN_DESC_COUNT = 100; /** * Fetch the content type of the given url @@ -147,7 +147,7 @@ class ParseUrl 'created' => DateTimeFormat::utcNow(), 'expires' => $expires, ], - Database::INSERT_UPDATE + Database::INSERT_UPDATE, ); return $data; @@ -268,7 +268,7 @@ class ParseUrl if ($cacheControlHeader = $curlResult->getHeader('Cache-Control')[0] ?? '') { if (preg_match('/max-age=([0-9]+)/i', $cacheControlHeader, $matches)) { - $maxAge = max(86400, (int)array_pop($matches)); + $maxAge = max(86400, (int) array_pop($matches)); $siteinfo['expires'] = DateTimeFormat::utc("now + $maxAge seconds"); } @@ -285,7 +285,7 @@ class ParseUrl if (isset($mediaType->parameters['charset'])) { $charset = $mediaType->parameters['charset']; } - } catch(\InvalidArgumentException $e) { + } catch (\InvalidArgumentException $e) { } $siteinfo['charset'] = $charset; @@ -1394,7 +1394,7 @@ class ParseUrl DI::logger()->debug('Found oEmbed JSON from Embera', ['url' => $url]); } - if (!isset($data['type']) || !isset($data['provider_url'])) { + if (!isset($data['type']) || !isset($data['provider_url'])) { return []; } diff --git a/src/Util/Strings.php b/src/Util/Strings.php index c44b342ff2..a7998d4290 100644 --- a/src/Util/Strings.php +++ b/src/Util/Strings.php @@ -96,17 +96,17 @@ class Strings 'v', 'w', 'wh', 'x', - 'z', 'zh' + 'z', 'zh', ]; $midcons = [ 'ck', 'ct', 'gn', 'ld', 'lf', 'lm', 'lt', 'mb', 'mm', 'mn', 'mp', - 'nd', 'ng', 'nk', 'nt', 'rn', 'rp', 'rt' + 'nd', 'ng', 'nk', 'nt', 'rn', 'rp', 'rt', ]; $noend = [ 'bl', 'br', 'cl', 'cr', 'dr', 'fl', 'fr', 'gl', 'gr', - 'kh', 'kl', 'kr', 'mn', 'pl', 'pr', 'rh', 'tr', 'qu', 'wh', 'q' + 'kh', 'kl', 'kr', 'mn', 'pl', 'pr', 'rh', 'tr', 'qu', 'wh', 'q', ]; $start = mt_rand(0, 2); @@ -494,7 +494,7 @@ class Strings return $return; }, - $text + $text, ); if (is_null($return)) { @@ -513,7 +513,7 @@ class Strings } return $return; }, - $text + $text, ); return $text; diff --git a/src/Util/XML.php b/src/Util/XML.php index 8e4df82d89..7f37b06d42 100644 --- a/src/Util/XML.php +++ b/src/Util/XML.php @@ -304,7 +304,7 @@ class XML $type = $data['type']; $level = $data['level']; $attributes = $data['attributes'] ?? null; - $value = $data['value'] ?? null; + $value = $data['value'] ?? null; $result = []; $attributes_data = []; @@ -341,7 +341,7 @@ class XML if (!is_array($current) || (!in_array($tag, array_keys($current)))) { // Insert New tag $current[$tag] = $result; if ($attributes_data) { - $current[$tag. '_attr'] = $attributes_data; + $current[$tag . '_attr'] = $attributes_data; } $repeated_tag_index[$tag . '_' . $level] = 1; @@ -355,9 +355,9 @@ class XML $current[$tag] = [$current[$tag], $result]; // This will combine the existing item and the new item together to make an array $repeated_tag_index[$tag . '_' . $level] = 2; - if (isset($current[$tag.'_attr'])) { // The attribute of the last(0th) tag must be moved as well - $current[$tag]['0_attr'] = $current[$tag.'_attr']; - unset($current[$tag.'_attr']); + if (isset($current[$tag . '_attr'])) { // The attribute of the last(0th) tag must be moved as well + $current[$tag]['0_attr'] = $current[$tag . '_attr']; + unset($current[$tag . '_attr']); } } $last_item_index = $repeated_tag_index[$tag . '_' . $level] - 1; @@ -369,7 +369,7 @@ class XML $current[$tag] = $result; $repeated_tag_index[$tag . '_' . $level] = 1; if ($priority == 'tag' and $attributes_data) { - $current[$tag. '_attr'] = $attributes_data; + $current[$tag . '_attr'] = $attributes_data; } } else { // If taken, put all things inside a list(array) if (isset($current[$tag][0]) and is_array($current[$tag])) { // If it is already an array... @@ -385,10 +385,10 @@ class XML $current[$tag] = [$current[$tag], $result]; //...Make it an array using the existing value and the new value $repeated_tag_index[$tag . '_' . $level] = 1; if ($priority == 'tag' and $get_attributes) { - if (isset($current[$tag.'_attr'])) { // The attribute of the last(0th) tag must be moved as well + if (isset($current[$tag . '_attr'])) { // The attribute of the last(0th) tag must be moved as well - $current[$tag]['0_attr'] = $current[$tag.'_attr']; - unset($current[$tag.'_attr']); + $current[$tag]['0_attr'] = $current[$tag . '_attr']; + unset($current[$tag . '_attr']); } if ($attributes_data) { diff --git a/static/routes.config.php b/static/routes.config.php index 6284c3dd4f..98644abbb2 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -656,9 +656,9 @@ return [ '/stats/caching' => [Module\StatsCaching::class, [R::GET]], '/network' => [ - '[/{content}]' => [Module\Conversation\Network::class, [R::GET]], + '[/{content}]' => [Module\Conversation\Network::class, [R::GET]], '/archive/{from:\d\d\d\d-\d\d-\d\d}[/{to:\d\d\d\d\-\d\d-\d\d}]' => [Module\Conversation\Network::class, [R::GET]], - '/circle/{circle_id:\d+}' => [Module\Conversation\Network::class, [R::GET]], + '/circle/{circle_id:\d+}' => [Module\Conversation\Network::class, [R::GET]], ], '/randprof' => [Module\RandomProfile::class, [R::GET]], @@ -671,10 +671,10 @@ return [ '/tos' => [Module\Tos::class, [R::GET]], '/ping_network' => [ - '[/]' => [Module\Ping\Network::class, [R::GET]], + '[/]' => [Module\Ping\Network::class, [R::GET]], '/archive/{from:\d\d\d\d-\d\d-\d\d}[/{to:\d\d\d\d\-\d\d-\d\d}]' => [Module\Ping\Network::class, [R::GET]], - '/group/{contact_id:\d+}' => [Module\Ping\Network::class, [R::GET]], - '/circle/{circle_id:\d+}' => [Module\Ping\Network::class, [R::GET]], + '/group/{contact_id:\d+}' => [Module\Ping\Network::class, [R::GET]], + '/circle/{circle_id:\d+}' => [Module\Ping\Network::class, [R::GET]], ], '/update_channel[/{content}]' => [Module\Update\Channel::class, [R::GET]], @@ -685,10 +685,10 @@ return [ '/update_display' => [Module\Update\Display::class, [R::GET]], '/update_network' => [ - '[/]' => [Module\Update\Network::class, [R::GET]], + '[/]' => [Module\Update\Network::class, [R::GET]], '/archive/{from:\d\d\d\d-\d\d-\d\d}[/{to:\d\d\d\d\-\d\d-\d\d}]' => [Module\Update\Network::class, [R::GET]], - '/group/{contact_id:\d+}' => [Module\Update\Network::class, [R::GET]], - '/circle/{circle_id:\d+}' => [Module\Update\Network::class, [R::GET]], + '/group/{contact_id:\d+}' => [Module\Update\Network::class, [R::GET]], + '/circle/{circle_id:\d+}' => [Module\Update\Network::class, [R::GET]], ], '/update_notes' => [Module\Update\Notes::class, [R::GET]], diff --git a/view/theme/frio/php/default.php b/view/theme/frio/php/default.php index 725a6d0748..4fa80fbb59 100644 --- a/view/theme/frio/php/default.php +++ b/view/theme/frio/php/default.php @@ -36,7 +36,7 @@ $is_singleuser_class = $is_singleuser ? "is-singleuser" : "is-not-singleuser"; echo $page['title']; } ?> - + get($uid, 'frio', 'scheme_accent') ?: - DI::config()->get('frio', 'scheme_accent') ?: FRIO_SCHEME_ACCENT_BLUE; + $scheme_accent = DI::pConfig()->get($uid, 'frio', 'scheme_accent') + ?: DI::config()->get('frio', 'scheme_accent') ?: FRIO_SCHEME_ACCENT_BLUE; require_once $schemefile; } @@ -76,8 +76,8 @@ echo ''; str_replace( "~system.banner~", DI::config()->get('system', 'banner'), - $page['nav'] - ) + $page['nav'], + ), ); }; From d498dc890776d898aacb1c06e7953e247d76feb0 Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 4 Mar 2026 22:04:41 +0000 Subject: [PATCH 170/197] require php 7.4 to 8.5 --- composer.json | 2 +- composer.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 0798db78f4..24c44a35a8 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "issues": "https://github.com/friendica/friendica/issues" }, "require": { - "php": "^7.4 || ^8.0", + "php": "7.4.* || 8.0.* || 8.1.* || 8.2.* || 8.3.* || 8.4.* || 8.5.*", "ext-ctype": "*", "ext-curl": "*", "ext-dom": "*", diff --git a/composer.lock b/composer.lock index 4fba462ad5..0e5c0d2ad0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6d527ae9eae2fb9d84d097b0d543a152", + "content-hash": "2b4d6540f8af879e01ed418f2d5af7ab", "packages": [ { "name": "alchemy/binary-driver", @@ -10457,7 +10457,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^7.4 || ^8.0", + "php": "7.4.* || 8.0.* || 8.1.* || 8.2.* || 8.3.* || 8.4.* || 8.5.*", "ext-ctype": "*", "ext-curl": "*", "ext-dom": "*", From 074d352cb9a297f8ccc64fa1766640e6ea87180a Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 5 Mar 2026 05:22:52 +0000 Subject: [PATCH 171/197] Fix detection for threads.net --- src/Model/GServer.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Model/GServer.php b/src/Model/GServer.php index c74b0e86ba..1edcaa4779 100644 --- a/src/Model/GServer.php +++ b/src/Model/GServer.php @@ -703,17 +703,17 @@ class GServer return false; } - if (in_array($url, ['https://www.threads.net', 'https://threads.net'])) { - $serverdata['detection-method'] = self::DETECT_THREADS; - $serverdata['network'] = Protocol::ACTIVITYPUB; - $serverdata['platform'] = 'threads'; - } - if (($serverdata['network'] == Protocol::PHANTOM) || in_array($serverdata['detection-method'], self::DETECT_UNSPECIFIC)) { $serverdata = self::detectMastodonAlikes($url, $serverdata); } } + if (($serverdata['network'] == Protocol::PHANTOM) && in_array($url, ['https://www.threads.net', 'https://threads.net'])) { + $serverdata['detection-method'] = self::DETECT_THREADS; + $serverdata['network'] = Protocol::ACTIVITYPUB; + $serverdata['platform'] = 'threads'; + } + // All following checks are done for systems that always have got a "host-meta" endpoint. // With this check we don't have to waste time and resources for dead systems. // Also this hopefully prevents us from receiving abuse messages. From f749b099f5188ba48c172d750b8bc1bc8cf89f48 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 5 Mar 2026 05:25:18 +0000 Subject: [PATCH 172/197] Fix code style --- src/Model/GServer.php | 114 +++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/src/Model/GServer.php b/src/Model/GServer.php index 1edcaa4779..28fe7945f7 100644 --- a/src/Model/GServer.php +++ b/src/Model/GServer.php @@ -40,44 +40,44 @@ use Psr\Http\Message\UriInterface; class GServer { // Directory types - const DT_NONE = 0; - const DT_POCO = 1; - const DT_MASTODON = 2; + public const DT_NONE = 0; + public const DT_POCO = 1; + public const DT_MASTODON = 2; // Methods to detect server types // Non endpoint specific methods - const DETECT_MANUAL = 0; - const DETECT_HEADER = 1; - const DETECT_BODY = 2; - const DETECT_HOST_META = 3; - const DETECT_CONTACTS = 4; - const DETECT_AP_ACTOR = 5; - const DETECT_AP_COLLECTION = 6; + public const DETECT_MANUAL = 0; + public const DETECT_HEADER = 1; + public const DETECT_BODY = 2; + public const DETECT_HOST_META = 3; + public const DETECT_CONTACTS = 4; + public const DETECT_AP_ACTOR = 5; + public const DETECT_AP_COLLECTION = 6; - const DETECT_UNSPECIFIC = [self::DETECT_MANUAL, self::DETECT_HEADER, self::DETECT_BODY, self::DETECT_HOST_META, self::DETECT_CONTACTS, self::DETECT_AP_ACTOR]; + public const DETECT_UNSPECIFIC = [self::DETECT_MANUAL, self::DETECT_HEADER, self::DETECT_BODY, self::DETECT_HOST_META, self::DETECT_CONTACTS, self::DETECT_AP_ACTOR]; // Implementation specific endpoints // @todo Possibly add Lemmy detection via the endpoint /api/v3/site - const DETECT_FRIENDIKA = 10; - const DETECT_FRIENDICA = 11; - const DETECT_STATUSNET = 12; - const DETECT_GNUSOCIAL = 13; - const DETECT_CONFIG_JSON = 14; // Statusnet, GNU Social, Older Hubzilla/Redmatrix - const DETECT_SITEINFO_JSON = 15; // Newer Hubzilla - const DETECT_MASTODON_API = 16; - const DETECT_STATUS_PHP = 17; // Nextcloud - const DETECT_V1_CONFIG = 18; - const DETECT_SYSTEM_ACTOR = 20; // Mistpark, Osada, Roadhouse, Zap - const DETECT_THREADS = 21; + public const DETECT_FRIENDIKA = 10; + public const DETECT_FRIENDICA = 11; + public const DETECT_STATUSNET = 12; + public const DETECT_GNUSOCIAL = 13; + public const DETECT_CONFIG_JSON = 14; // Statusnet, GNU Social, Older Hubzilla/Redmatrix + public const DETECT_SITEINFO_JSON = 15; // Newer Hubzilla + public const DETECT_MASTODON_API = 16; + public const DETECT_STATUS_PHP = 17; // Nextcloud + public const DETECT_V1_CONFIG = 18; + public const DETECT_SYSTEM_ACTOR = 20; // Mistpark, Osada, Roadhouse, Zap + public const DETECT_THREADS = 21; // Standardized endpoints - const DETECT_STATISTICS_JSON = 100; - const DETECT_NODEINFO_10 = 101; // Nodeinfo Version 1.0 - const DETECT_NODEINFO_20 = 102; // Nodeinfo Version 2.0 - const DETECT_NODEINFO2_10 = 103; // Nodeinfo2 Version 1.0 - const DETECT_NODEINFO_21 = 104; // Nodeinfo Version 2.1 - const DETECT_NODEINFO_22 = 105; // Nodeinfo Version 2.2 + public const DETECT_STATISTICS_JSON = 100; + public const DETECT_NODEINFO_10 = 101; // Nodeinfo Version 1.0 + public const DETECT_NODEINFO_20 = 102; // Nodeinfo Version 2.0 + public const DETECT_NODEINFO2_10 = 103; // Nodeinfo2 Version 1.0 + public const DETECT_NODEINFO_21 = 104; // Nodeinfo Version 2.1 + public const DETECT_NODEINFO_22 = 105; // Nodeinfo Version 2.2 private static RobotsTxt $robotsTxt; @@ -194,10 +194,10 @@ class GServer */ private static function isDefunct(array $gserver): bool { - return ($gserver['failed'] || in_array($gserver['network'], Protocol::FEDERATED)) && - ($gserver['last_contact'] >= $gserver['created']) && - ($gserver['last_contact'] < $gserver['last_failure']) && - ($gserver['last_contact'] < DateTimeFormat::utc('now - 90 days')); + return ($gserver['failed'] || in_array($gserver['network'], Protocol::FEDERATED)) + && ($gserver['last_contact'] >= $gserver['created']) + && ($gserver['last_contact'] < $gserver['last_failure']) + && ($gserver['last_contact'] < DateTimeFormat::utc('now - 90 days')); } /** @@ -256,9 +256,9 @@ class GServer } elseif (!empty($contact['baseurl'])) { $server = $contact['baseurl']; } elseif ($contact['network'] == Protocol::DIASPORA) { - $parts = (array)parse_url($contact['url']); + $parts = (array) parse_url($contact['url']); unset($parts['path']); - $server = (string)Uri::fromParts($parts); + $server = (string) Uri::fromParts($parts); } else { return true; } @@ -482,7 +482,7 @@ class GServer self::update( ['url' => $url, 'failed' => true, 'blocked' => Network::isUrlBlocked($url), 'last_failure' => DateTimeFormat::utcNow(), 'next_contact' => $next_update, 'network' => Protocol::PHANTOM, 'detection-method' => null], - ['nurl' => $nurl] + ['nurl' => $nurl], ); DI::logger()->info('Set failed status for existing server', ['url' => $url]); if (self::isDefunct($gserver)) { @@ -521,7 +521,7 @@ class GServer public static function cleanURL(string $dirtyUrl): string { try { - return (string)self::cleanUri(new Uri($dirtyUrl)); + return (string) self::cleanUri(new Uri($dirtyUrl)); } catch (\Throwable $e) { DI::logger()->warning('Invalid URL', ['dirtyUrl' => $dirtyUrl]); return ''; @@ -546,8 +546,8 @@ class GServer preg_replace( '#(?:^|/)index\.php#', '', - rtrim($dirtyUri->getPath(), '/') - ) + rtrim($dirtyUri->getPath(), '/'), + ), ); } @@ -594,8 +594,8 @@ class GServer if (!Strings::compareLink($url, $valid_url)) { // We only follow redirects when the path stays the same or the target url has no path. // Some systems have got redirects on their landing page to a single account page. This check handles it. - if (((parse_url($url, PHP_URL_HOST) != parse_url($valid_url, PHP_URL_HOST)) && (parse_url($url, PHP_URL_PATH) == parse_url($valid_url, PHP_URL_PATH))) || - (((parse_url($url, PHP_URL_HOST) != parse_url($valid_url, PHP_URL_HOST)) || (parse_url($url, PHP_URL_PATH) != parse_url($valid_url, PHP_URL_PATH))) && empty(parse_url($valid_url, PHP_URL_PATH)))) { + if (((parse_url($url, PHP_URL_HOST) != parse_url($valid_url, PHP_URL_HOST)) && (parse_url($url, PHP_URL_PATH) == parse_url($valid_url, PHP_URL_PATH))) + || (((parse_url($url, PHP_URL_HOST) != parse_url($valid_url, PHP_URL_HOST)) || (parse_url($url, PHP_URL_PATH) != parse_url($valid_url, PHP_URL_PATH))) && empty(parse_url($valid_url, PHP_URL_PATH)))) { DI::logger()->debug('Found redirect. Mark old entry as failure', ['old' => $url, 'new' => $valid_url]); self::setFailureByUrl($url); $target_id = self::getID($valid_url, true); @@ -609,12 +609,12 @@ class GServer return false; } - if ((parse_url($url, PHP_URL_HOST) != parse_url($valid_url, PHP_URL_HOST)) && (parse_url($url, PHP_URL_PATH) != parse_url($valid_url, PHP_URL_PATH)) && - (parse_url($url, PHP_URL_PATH) == '')) { + if ((parse_url($url, PHP_URL_HOST) != parse_url($valid_url, PHP_URL_HOST)) && (parse_url($url, PHP_URL_PATH) != parse_url($valid_url, PHP_URL_PATH)) + && (parse_url($url, PHP_URL_PATH) == '')) { DI::logger()->debug('Found redirect. Mark old entry as failure and redirect to the basepath.', ['old' => $url, 'new' => $valid_url]); - $parts = (array)parse_url($valid_url); + $parts = (array) parse_url($valid_url); unset($parts['path']); - $valid_url = (string)Uri::fromParts($parts); + $valid_url = (string) Uri::fromParts($parts); self::setFailureByUrl($url); if (!self::getID($valid_url, true) && !Network::isUrlBlocked($valid_url)) { @@ -625,9 +625,9 @@ class GServer DI::logger()->debug('Found redirect, but ignore it.', ['old' => $url, 'new' => $valid_url]); } - if ((parse_url($url, PHP_URL_HOST) == parse_url($valid_url, PHP_URL_HOST)) && - (parse_url($url, PHP_URL_PATH) == parse_url($valid_url, PHP_URL_PATH)) && - (parse_url($url, PHP_URL_SCHEME) != parse_url($valid_url, PHP_URL_SCHEME))) { + if ((parse_url($url, PHP_URL_HOST) == parse_url($valid_url, PHP_URL_HOST)) + && (parse_url($url, PHP_URL_PATH) == parse_url($valid_url, PHP_URL_PATH)) + && (parse_url($url, PHP_URL_SCHEME) != parse_url($valid_url, PHP_URL_SCHEME))) { $url = $valid_url; } @@ -789,8 +789,8 @@ class GServer // When a server is new, then there is no gserver entry yet. // But in "detectNetworkViaContacts" it could happen that a contact is updated, // and this can call this function here as well. - if (self::getID($url, true) && (in_array($serverdata['network'], [Protocol::PHANTOM, Protocol::FEED]) || - in_array($serverdata['detection-method'], [self::DETECT_MANUAL, self::DETECT_HEADER, self::DETECT_BODY, self::DETECT_HOST_META]))) { + if (self::getID($url, true) && (in_array($serverdata['network'], [Protocol::PHANTOM, Protocol::FEED]) + || in_array($serverdata['detection-method'], [self::DETECT_MANUAL, self::DETECT_HEADER, self::DETECT_BODY, self::DETECT_HOST_META]))) { $serverdata = self::detectNetworkViaContacts($url, $serverdata); } @@ -974,7 +974,7 @@ class GServer } // Sanitize incoming data, see https://github.com/friendica/friendica/issues/8565 - $data['subscribe'] = (bool)($data['subscribe'] ?? false); + $data['subscribe'] = (bool) ($data['subscribe'] ?? false); if (!$data['subscribe'] || empty($data['scope']) || !in_array(strtolower($data['scope']), ['all', 'tags'])) { $data['scope'] = ''; @@ -1241,7 +1241,7 @@ class GServer $server = [ 'detection-method' => self::DETECT_NODEINFO_10, - 'register_policy' => Register::CLOSED + 'register_policy' => Register::CLOSED, ]; if (!empty($nodeinfo['openRegistrations'])) { @@ -1472,7 +1472,7 @@ class GServer $server = [ 'detection-method' => self::DETECT_NODEINFO2_10, - 'register_policy' => Register::CLOSED + 'register_policy' => Register::CLOSED, ]; if (!empty($nodeinfo['openRegistrations'])) { @@ -2325,8 +2325,8 @@ class GServer // Test for GNU Social if (self::$robotsTxt->isAllowed('/api/gnusocial/version.json')) { $curlResult = DI::httpClient()->get($url . '/api/gnusocial/version.json', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); - if ($curlResult->isSuccess() && ($curlResult->getBodyString() != '{"error":"not implemented"}') && - ($curlResult->getBodyString() != '') && (strlen($curlResult->getBodyString()) < 30)) { + if ($curlResult->isSuccess() && ($curlResult->getBodyString() != '{"error":"not implemented"}') + && ($curlResult->getBodyString() != '') && (strlen($curlResult->getBodyString()) < 30)) { $serverdata['platform'] = 'gnusocial'; // Remove junk that some GNU Social servers return $serverdata['version'] = str_replace(chr(239) . chr(187) . chr(191), '', $curlResult->getBodyString()); @@ -2345,8 +2345,8 @@ class GServer // Test for Statusnet if (self::$robotsTxt->isAllowed('/api/statusnet/version.json')) { $curlResult = DI::httpClient()->get($url . '/api/statusnet/version.json', HttpClientAccept::JSON, [HttpClientOptions::REQUEST => HttpClientRequest::SERVERINFO]); - if ($curlResult->isSuccess() && ($curlResult->getBodyString() != '{"error":"not implemented"}') && - ($curlResult->getBodyString() != '') && (strlen($curlResult->getBodyString()) < 30)) { + if ($curlResult->isSuccess() && ($curlResult->getBodyString() != '{"error":"not implemented"}') + && ($curlResult->getBodyString() != '') && (strlen($curlResult->getBodyString()) < 30)) { // Remove junk that some GNU Social servers return $serverdata['version'] = str_replace(chr(239) . chr(187) . chr(191), '', $curlResult->getBodyString()); @@ -2673,7 +2673,7 @@ class GServer 'gserver', ['id', 'url', 'nurl', 'network', 'poco', 'directory-type'], ["NOT `blocked` AND NOT `failed` AND `directory-type` != ? AND `last_poco_query` < ?", GServer::DT_NONE, $last_update], - ['order' => ['RAND()']] + ['order' => ['RAND()']], ); while ($gserver = DBA::fetch($gservers)) { From 8c869cdcf48a75da85a2f14c8c362dbe9017a436 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 5 Mar 2026 07:24:27 +0000 Subject: [PATCH 173/197] Change after review --- src/Model/GServer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Model/GServer.php b/src/Model/GServer.php index 28fe7945f7..631ace5674 100644 --- a/src/Model/GServer.php +++ b/src/Model/GServer.php @@ -708,7 +708,7 @@ class GServer } } - if (($serverdata['network'] == Protocol::PHANTOM) && in_array($url, ['https://www.threads.net', 'https://threads.net'])) { + if (($serverdata['network'] === Protocol::PHANTOM) && in_array($url, ['https://www.threads.net', 'https://threads.net'])) { $serverdata['detection-method'] = self::DETECT_THREADS; $serverdata['network'] = Protocol::ACTIVITYPUB; $serverdata['platform'] = 'threads'; From 07cf5b5d30796db9a2d752a6312ba4661f200e83 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 5 Mar 2026 07:25:49 +0000 Subject: [PATCH 174/197] Changes because of review --- src/Module/LostPass.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Module/LostPass.php b/src/Module/LostPass.php index 533e20dc1c..82157362ce 100644 --- a/src/Module/LostPass.php +++ b/src/Module/LostPass.php @@ -22,11 +22,11 @@ use Friendica\Util\Emailer; use Friendica\Util\Profiler; use Psr\Log\LoggerInterface; -class LostPass extends BaseModule +final class LostPass extends BaseModule { - protected SystemMessages $sysMessages; - protected IManageConfigValues $config; - protected Emailer $emailer; + private SystemMessages $sysMessages; + private IManageConfigValues $config; + private Emailer $emailer; public function __construct(L10n $l10n, BaseURL $baseUrl, Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, SystemMessages $sysMessages, IManageConfigValues $config, Emailer $emailer, array $server, array $parameters = []) { From 00979edfee4107d3fcbec1260fb6cccfa09d5ae1 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 5 Mar 2026 07:28:59 +0000 Subject: [PATCH 175/197] Added phpdoc --- src/Module/LostPass.php | 43 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/Module/LostPass.php b/src/Module/LostPass.php index 82157362ce..d14856c841 100644 --- a/src/Module/LostPass.php +++ b/src/Module/LostPass.php @@ -22,12 +22,32 @@ use Friendica\Util\Emailer; use Friendica\Util\Profiler; use Psr\Log\LoggerInterface; +/** + * Lost password module + * + * This module handles password reset functionality for users who have forgotten their passwords. + */ final class LostPass extends BaseModule { private SystemMessages $sysMessages; private IManageConfigValues $config; private Emailer $emailer; + /** + * Initialize the module + * + * @param L10n $l10n + * @param BaseURL $baseUrl + * @param Arguments $args + * @param LoggerInterface $logger + * @param Profiler $profiler + * @param Response $response + * @param SystemMessages $sysMessages + * @param IManageConfigValues $config + * @param Emailer $emailer + * @param array $server + * @param array $parameters + */ public function __construct(L10n $l10n, BaseURL $baseUrl, Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, SystemMessages $sysMessages, IManageConfigValues $config, Emailer $emailer, array $server, array $parameters = []) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); @@ -37,6 +57,12 @@ final class LostPass extends BaseModule $this->emailer = $emailer; } + /** + * Handle POST requests for password reset form submission + * + * @param array $request + * @return void + */ protected function post(array $request = []) { $loginame = trim($request['login-name'] ?? ''); @@ -99,6 +125,12 @@ final class LostPass extends BaseModule $this->baseUrl->redirect(); } + /** + * Render page content + * + * @param array $request + * @return string Rendered page content + */ protected function content(array $request = []): string { if (isset($this->parameters['token'])) { @@ -130,6 +162,11 @@ final class LostPass extends BaseModule } } + /** + * Render the password reset form + * + * @return string Rendered form HTML + */ private function form(): string { $tpl = Renderer::getMarkupTemplate('lostpass.tpl'); @@ -143,6 +180,12 @@ final class LostPass extends BaseModule return $o; } + /** + * Generate and send a new password to the user + * + * @param array $user User data array + * @return string Rendered success message HTML + */ private function generatePassword(array $user): string { $o = ''; From 49f7e1729202001026eb236a65083feaa52ab58c Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Thu, 5 Mar 2026 10:29:24 +0100 Subject: [PATCH 176/197] Fix installation documentation link in README Previous link was broken --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d4a49330e4..c608ccf331 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ You can control the privacy scope of your content. Being part of the Fediverse allows you to be free from data-harvesting corporations. Enjoy open social communication, independent of any specific provider. -[Join Friendica](https://dir.friendica.social/servers) today or set up [your own Friendica instance](doc/Install.md). +[Join Friendica](https://dir.friendica.social/servers) today or set up [your own Friendica instance](doc/en/admin/install.md). ### Friendica on desktop From c4b2ffa66cfa14cda6baeff35d593b9201cf002d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CRaroun=E2=80=9D?= Date: Thu, 5 Mar 2026 12:03:26 +0100 Subject: [PATCH 177/197] Modernize jot.js - Fix implicit global variables (reply, noAttachment) - Add feature detection for aStr, bin2hex, autosize - Add error handling for AJAX requests - Wrap in IIFE with strict mode - Add JSDoc documentation --- view/theme/frio/js/jot.js | 97 ++++++++++++++++++++++++++++----------- 1 file changed, 69 insertions(+), 28 deletions(-) diff --git a/view/theme/frio/js/jot.js b/view/theme/frio/js/jot.js index 275b23f53c..16f05664e1 100644 --- a/view/theme/frio/js/jot.js +++ b/view/theme/frio/js/jot.js @@ -3,43 +3,84 @@ // SPDX-License-Identifier: AGPL-3.0-or-later // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPLv3-or-later -// We append the linkPreview to a global Variable to make linkPreview -// accessable on other places. Note: search on other places before you -// delete or move the variable. -var linkPreview; /** - * Insert a link into friendica jot. + * @file view/theme/frio/js/jot.js + * JavaScript for link attachment in the jot (post composer). * - * @returns {void} + * Handles inserting links into posts with automatic preview generation. + * + * @requires jQuery + * @requires linkPreview.js + * @requires autosize + * + * Note: The linkPreview variable is intentionally global for cross-module access. */ -function jotGetLink() { - var currentText = $("#profile-jot-text").val(); - var noAttachment = ""; - reply = prompt(aStr.linkurl); - if (reply && reply.length) { - // There should be only one attachment per post. - // So we need to remove the old one. + +// Global linkPreview instance for cross-module access +// eslint-disable-next-line no-var +var linkPreview; + +(function ($, window) { + "use strict"; + + /** + * Prompt for a link URL and insert it into the jot with preview. + * + * @returns {void} + */ + window.jotGetLink = function () { + // Check for required global variables and functions + if (typeof window.aStr === "undefined" || !window.aStr.linkurl) { + return; + } + + const reply = prompt(window.aStr.linkurl); + + if (!reply || !reply.length) { + return; + } + + const $textarea = $("#profile-jot-text"); + + if (!$textarea.length) { + return; + } + + const currentText = $textarea.val(); + + // Clear previous attachment preview $("#jot-attachment-preview").empty(); $("#profile-rotator").show(); - if (currentText.includes("[attachment") && currentText.includes("[/attachment]")) { - noAttachment = "&noAttachment=1"; - } - // We use the linkPreview library to have a preview - // of the attachments. - if (typeof linkPreview === "object") { + // Check if post already has an attachment + const hasAttachment = currentText.includes("[attachment") && + currentText.includes("[/attachment]"); + const noAttachment = hasAttachment ? "&noAttachment=1" : ""; + + // Use linkPreview library if available + if (typeof linkPreview === "object" && linkPreview !== null) { linkPreview.crawlText(reply + noAttachment); - - // Fallback: insert the attachment bbcode directly into the textarea - // if the attachment live preview isn't available - } else { - $.get("parseurl?binurl=" + bin2hex(reply) + noAttachment, function (data) { - addeditortext(data); + } else if (typeof window.bin2hex === "function") { + // Fallback: directly fetch and insert BBCode + const hexReply = window.bin2hex(reply); + $.get("parseurl?binurl=" + hexReply + noAttachment, function (data) { + if (typeof window.addeditortext === "function") { + window.addeditortext(data); + } + $("#profile-rotator").hide(); + }).fail(function () { $("#profile-rotator").hide(); }); + } else { + $("#profile-rotator").hide(); } - autosize.update($("#profile-jot-text")); - } -} + + // Update textarea autosize if available + if (typeof window.autosize === "function") { + window.autosize.update($textarea); + } + }; + +})(jQuery, window); // @license-end From c78d5adb40ce92f694617547cabd2fe6689bda8c Mon Sep 17 00:00:00 2001 From: loma-one <44441246+loma-one@users.noreply.github.com> Date: Fri, 6 Mar 2026 21:20:54 +0100 Subject: [PATCH 178/197] Refactor image link generation in BBCode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, images embedded in continuous text were opened with the attribute `target=’_blank‘`. However, they should be loaded and displayed in the Fancybox. As a result of the change, images are now loaded in the Fancybox. Links and videos are identified in order to maintain the previous functionality. --- src/Content/Text/BBCode.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index 6634e2202c..15e7b0da9d 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -473,14 +473,19 @@ class BBCode if (!empty($data['title']) && !empty($data['url'])) { $preview_class = in_array($preview_mode, [self::PREVIEW_AUTO, self::PREVIEW_LARGE]) ? 'attachment-image' : 'attachment-preview'; - if (!empty($data['image']) && empty($data['text']) && ($data['type'] == 'photo')) { - $return .= sprintf('', $data['url'], self::proxyUrl($data['image'], $simplehtml, $uriid), $data['title']); + + $is_photo = ($data['type'] === 'photo'); + $link_attributes = $is_photo ? 'data-fancybox="gallery" rel="noopener noreferrer"' : 'target="_blank" rel="noopener noreferrer"'; + + if (!empty($data['image']) && empty($data['text']) && $is_photo) { + $return .= sprintf('', $data['url'], $link_attributes, self::proxyUrl($data['image'], $simplehtml, $uriid), $data['title'], $preview_class); } else { if (!empty($data['image'])) { - $return .= sprintf('
    ', $data['url'], self::proxyUrl($data['image'], $simplehtml, $uriid), $data['title']); + $return .= sprintf('
    ', $data['url'], $link_attributes, self::proxyUrl($data['image'], $simplehtml, $uriid), $data['title'], $preview_class); } elseif (!empty($data['preview'])) { - $return .= sprintf('
    ', $data['url'], self::proxyUrl($data['preview'], $simplehtml, $uriid), $data['title']); + $return .= sprintf('
    ', $data['url'], $link_attributes, self::proxyUrl($data['preview'], $simplehtml, $uriid), $data['title']); } + $return .= sprintf('

    %s

    ', $data['url'], $data['title']); } } From 263d452bbcf1aed9719debda1d889174a50bc85d Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 7 Mar 2026 13:20:37 +0000 Subject: [PATCH 179/197] Handle warnings because of missing handle information --- src/Protocol/ATProtocol/Processor.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Protocol/ATProtocol/Processor.php b/src/Protocol/ATProtocol/Processor.php index e073057358..4f5f4f05bc 100755 --- a/src/Protocol/ATProtocol/Processor.php +++ b/src/Protocol/ATProtocol/Processor.php @@ -61,7 +61,7 @@ class Processor $fields = [ 'archive' => !$data->account->active, 'failed' => !$data->account->active, - 'updated' => DateTimeFormat::utc($data->account->time, DateTimeFormat::MYSQL) + 'updated' => DateTimeFormat::utc($data->account->time, DateTimeFormat::MYSQL), ]; $this->logger->notice('Process account', ['did' => $data->identity->did, 'fields' => $fields]); @@ -71,6 +71,11 @@ class Processor public function processIdentity(stdClass $data) { + if (!isset($data->identity->handle)) { + $this->logger->warning('No handle provided', ['data' => $data]); + return; + } + $fields = [ 'alias' => ATProtocol::WEB . '/profile/' . $data->identity->did, 'nick' => $data->identity->handle, From 0d29f03bccb62d21d1781f2b7d6401795db27c94 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 8 Mar 2026 13:22:04 +0000 Subject: [PATCH 180/197] Improve performance on post counts --- src/Content/Conversation.php | 2 +- src/Model/Post/Counts.php | 20 ++++++++++---------- src/Module/Conversation/Timeline.php | 3 ++- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/Content/Conversation.php b/src/Content/Conversation.php index a72c572e91..ae952c6a00 100644 --- a/src/Content/Conversation.php +++ b/src/Content/Conversation.php @@ -1110,7 +1110,7 @@ class Conversation { $counts = []; - foreach (Post\Counts::get(['parent-uri-id' => $uriids, 'verb' => Activity::POST]) as $count) { + foreach (Post\Counts::get(['parent-uri-id' => $uriids, 'vid' => Verb::getID(Activity::POST)]) as $count) { $counts[$count['parent-uri-id']] = ($counts[$count['parent-uri-id']] ?? 0) + $count['count']; } diff --git a/src/Model/Post/Counts.php b/src/Model/Post/Counts.php index 3d971a5757..197395a6d6 100644 --- a/src/Model/Post/Counts.php +++ b/src/Model/Post/Counts.php @@ -83,19 +83,19 @@ class Counts $counts = []; $activity_verbs = [ - Activity::LIKE, - Activity::DISLIKE, - Activity::ATTEND, - Activity::ATTENDMAYBE, - Activity::ATTENDNO, - Activity::ANNOUNCE, - Activity::VIEW, - Activity::READ, + Verb::getID(Activity::LIKE), + Verb::getID(Activity::DISLIKE), + Verb::getID(Activity::ATTEND), + Verb::getID(Activity::ATTENDMAYBE), + Verb::getID(Activity::ATTENDNO), + Verb::getID(Activity::ANNOUNCE), + Verb::getID(Activity::VIEW), + Verb::getID(Activity::READ), ]; - $verbs = array_merge($activity_verbs, [Activity::EMOJIREACT, Activity::POST]); + $verbs = array_merge($activity_verbs, [Verb::getID(Activity::EMOJIREACT), Verb::getID(Activity::POST)]); - $condition = DBA::mergeConditions($condition, ['verb' => $verbs]); + $condition = DBA::mergeConditions($condition, ['vid' => $verbs]); $countquery = DBA::select('post-counts-view', [], $condition); while ($count = DBA::fetch($countquery)) { if (!empty($count['reaction'])) { diff --git a/src/Module/Conversation/Timeline.php b/src/Module/Conversation/Timeline.php index 42936ff1da..a948414611 100644 --- a/src/Module/Conversation/Timeline.php +++ b/src/Module/Conversation/Timeline.php @@ -30,6 +30,7 @@ use Friendica\Database\DBA; use Friendica\Model\Item; use Friendica\Model\Post; use Friendica\Model\Post\SearchIndex; +use Friendica\Model\Verb; use Friendica\Module\Response; use Friendica\Network\HTTPException\BadRequestException; use Friendica\Network\HTTPException\ForbiddenException; @@ -617,7 +618,7 @@ class Timeline extends BaseModule $uriids = array_keys($items); - foreach (Post\Counts::get(['parent-uri-id' => $uriids, 'verb' => Activity::POST]) as $count) { + foreach (Post\Counts::get(['parent-uri-id' => $uriids, 'vid' => Verb::getID(Activity::POST)]) as $count) { $items[$count['parent-uri-id']]['comments'] += $count['count']; } From 4958bf56e3d25ad80bb769af35a691cf4862beb8 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 8 Mar 2026 13:25:33 +0000 Subject: [PATCH 181/197] Fix code style --- src/Module/Conversation/Timeline.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Module/Conversation/Timeline.php b/src/Module/Conversation/Timeline.php index a948414611..6fb3d9336f 100644 --- a/src/Module/Conversation/Timeline.php +++ b/src/Module/Conversation/Timeline.php @@ -117,14 +117,14 @@ class Timeline extends BaseModule $this->session->getLocalUserId(), 'system', 'itemspage_mobile_network', - $this->config->get('system', 'itemspage_network_mobile') + $this->config->get('system', 'itemspage_network_mobile'), ); } else { $this->itemsPerPage = $this->pConfig->get( $this->session->getLocalUserId(), 'system', 'itemspage_network', - $this->config->get('system', 'itemspage_network') + $this->config->get('system', 'itemspage_network'), ); } @@ -335,7 +335,7 @@ class Timeline extends BaseModule ((`comments` >= ? OR `activities` >= ? OR `views` >= ?) AND `owner-id` IN (SELECT `cid` FROM `contact-relation` WHERE `follows` AND `relation-cid` = ?)) OR (`owner-id` IN (SELECT `cid` FROM `user-contact` WHERE `uid` = ? AND (`notify_new_posts` OR `channel-frequency` = ?))))", $cid, $this->channelRepository->getMedianRelationThreadScore($cid, 4), $this->channelRepository->getMedianComments($uid, 4), $this->channelRepository->getMedianActivities($uid, 4), $this->channelRepository->getMedianViews($uid, 4), $cid, - $uid, Contact\User::FREQUENCY_ALWAYS + $uid, Contact\User::FREQUENCY_ALWAYS, ]; } } elseif ($this->selectedTab == ChannelEntity::DISCOVER) { @@ -350,7 +350,7 @@ class Timeline extends BaseModule (`owner-id` IN (SELECT `cid` FROM `contact-relation` WHERE `cid` = ? AND `relation-thread-score` > ?)) OR (`owner-id` IN (SELECT `cid` FROM `contact-relation` WHERE `relation-cid` = ? AND `relation-thread-score` > ?))))", $cid, $cid, $this->channelRepository->getMedianRelationThreadScore($cid, 4), $cid, $this->channelRepository->getMedianRelationThreadScore($cid, 4), - $this->channelRepository->getMedianComments($uid, 4), $this->channelRepository->getMedianActivities($uid, 4), $this->channelRepository->getMedianViews($uid, 4), $cid, 0, $cid, 0 + $this->channelRepository->getMedianComments($uid, 4), $this->channelRepository->getMedianActivities($uid, 4), $this->channelRepository->getMedianViews($uid, 4), $cid, 0, $cid, 0, ]; } } elseif ($this->selectedTab == ChannelEntity::FOLLOWERS) { @@ -366,7 +366,7 @@ class Timeline extends BaseModule "`owner-id` IN (SELECT `cid` FROM `contact-relation` WHERE `follows` AND `last-interaction` > ? AND `relation-cid` IN (SELECT `cid` FROM `contact-relation` WHERE `follows` AND `relation-cid` = ? AND `relation-thread-score` >= ?) AND NOT `cid` IN (SELECT `cid` FROM `contact-relation` WHERE `follows` AND `relation-cid` = ?))", - DateTimeFormat::utc('now - ' . $this->config->get('channel', 'sharer_interaction_days') . ' day'), $cid, $this->channelRepository->getMedianRelationThreadScore($cid, 4), $cid + DateTimeFormat::utc('now - ' . $this->config->get('channel', 'sharer_interaction_days') . ' day'), $cid, $this->channelRepository->getMedianRelationThreadScore($cid, 4), $cid, ]; } } elseif ($this->selectedTab == ChannelEntity::QUIETSHARERS) { @@ -375,7 +375,7 @@ class Timeline extends BaseModule $condition = [ "`owner-id` IN (SELECT `cid` FROM `contact-relation` WHERE `follows` AND `relation-cid` = ? AND `post-score` <= ?)", - $cid, $this->channelRepository->getMedianPostScore($cid, 2) + $cid, $this->channelRepository->getMedianPostScore($cid, 2), ]; } } elseif ($this->selectedTab == ChannelEntity::IMAGE) { @@ -409,9 +409,9 @@ class Timeline extends BaseModule $orders = [ EntityUserDefinedChannel::CIRCLE_CREATION => 'created', EntityUserDefinedChannel::CIRCLE_POSTS => 'received', - EntityUserDefinedChannel::CIRCLE_ACTIVITY => 'commented' + EntityUserDefinedChannel::CIRCLE_ACTIVITY => 'commented', ]; - $this->order = $orders[(int)$channel->circle]; + $this->order = $orders[(int) $channel->circle]; } } @@ -499,10 +499,10 @@ class Timeline extends BaseModule $maxpostperauthor = 0; if ($this->selectedTab == Community::LOCAL) { - $maxpostperauthor = (int)$this->config->get('system', 'max_author_posts_community_page'); + $maxpostperauthor = (int) $this->config->get('system', 'max_author_posts_community_page'); $key = 'author-id'; } elseif ($this->selectedTab == Community::GLOBAL) { - $maxpostperauthor = (int)$this->config->get('system', 'max_server_posts_community_page'); + $maxpostperauthor = (int) $this->config->get('system', 'max_server_posts_community_page'); $key = 'author-gsid'; } From ba9943fe21a78de24b3914b16f275cec2ede9ee7 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 7 Mar 2026 13:17:38 +0000 Subject: [PATCH 182/197] Store EXIF data for media --- database.sql | 43 +++- doc/en/spec/database/db-post-media-exif.md | 55 +++++ doc/en/spec/database/index.md | 1 + src/Model/Post/Media.php | 10 +- src/Model/Post/MediaExif.php | 265 +++++++++++++++++++++ src/Util/Images.php | 33 ++- static/dbstructure.config.php | 42 +++- 7 files changed, 444 insertions(+), 5 deletions(-) create mode 100644 doc/en/spec/database/db-post-media-exif.md create mode 100644 src/Model/Post/MediaExif.php diff --git a/database.sql b/database.sql index e15d19ca7d..4aa9a008e5 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2026.04-dev (Blutwurz) --- DB_UPDATE_VERSION 1589 +-- DB_UPDATE_VERSION 1590 -- ------------------------------------------ @@ -1498,6 +1498,47 @@ CREATE TABLE IF NOT EXISTS `post-media` ( FOREIGN KEY (`attach-id`) REFERENCES `attach` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Attached media'; +-- +-- TABLE post-media-exif +-- +CREATE TABLE IF NOT EXISTS `post-media-exif` ( + `media-id` int unsigned NOT NULL COMMENT 'If of the post-media entry with EXIF data', + `uri-id` int unsigned NOT NULL COMMENT 'Id of the item-uri table entry that contains the item uri', + `raw-data` text COMMENT 'JSON array with the raw exif data', + `coord` varchar(255) COMMENT 'GPS coordinates (latitude and longitude) representing the location where the picture was taken.', + `FocalLength` varchar(16) COMMENT 'The focal length of the lens in mm.', + `ExposureTime` varchar(16) COMMENT 'The exposure time in fractions of 1/x or full seconds.', + `ApertureFNumber` varchar(16) COMMENT 'The lens aperture calculated as f number', + `ISOSpeedRatings` smallint unsigned COMMENT 'The ISO speed used to expose the image.', + `LensSpecification` varchar(32) COMMENT 'Lens specifications, for example 35mm f/2.8 or 70-200mm f/2.8-6.3', + `FocusDistance` varchar(16) COMMENT 'The distance to the subject, given in meters.', + `CCDWidth` varchar(16) COMMENT '', + `BodySerialNumber` varchar(255) COMMENT 'The serial number of the body of the camera.', + `Artist` varchar(255) COMMENT 'The name of the camera owner, photographer or image creator.', + `Copyright` varchar(255) COMMENT 'Copyright information. In this standard the tag is used to indicate both the photographer and editor copyrights.', + `DateTime` datetime COMMENT 'The date and time of image creation. In Exif standard, it is the time the file was changed.', + `DateTimeOriginal` datetime COMMENT 'The date and time when the original image data was generated.', + `DateTimeDigitized` datetime COMMENT 'The date and time when the image was stored as digital data.', + `ExpandFilm` varchar(255) COMMENT 'The type or brand of film used for the image, such as analog film types (e.g., Kodak E100SW).', + `ExpandLens` varchar(255) COMMENT 'The lens model or description used for the image (e.g., Nikkor 20-35mm f/2.8 zoom).', + `HostComputer` varchar(255) COMMENT 'Information about the host computer used to generate the image.', + `ImageDescription` text COMMENT 'A character string giving the title of the image.', + `ImageUniqueID` varchar(255) COMMENT 'A unique identifier for each image, typically in the form of a UUID or other unique string.', + `LensMake` varchar(255) COMMENT 'The name of the lens manufacturer.', + `LensModel` varchar(255) COMMENT 'The model name or model number of the lens used.', + `Make` varchar(255) COMMENT 'The manufacturer of the recording equipment.', + `MakerNote` varchar(255) COMMENT 'A tag for manufacturers of Exif writers to record any desired information. The contents are up to the manufacturer.', + `Model` varchar(255) COMMENT 'The model name or model number of the equipment.', + `OwnerName` varchar(255) COMMENT 'The owner of the camera.', + `Orientation` tinyint unsigned COMMENT 'The image orientation in terms of rows and columns.', + `Software` varchar(255) COMMENT 'The name and version of the software or firmware of the camera or image input device used to generate the image.', + `UserComment` text COMMENT 'A comment provided by the user about the image.', + PRIMARY KEY(`media-id`), + INDEX `uri-id` (`uri-id`), + FOREIGN KEY (`media-id`) REFERENCES `post-media` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE, + FOREIGN KEY (`uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE +) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Exif data for attached media, see https://exiv2.org/tags.html'; + -- -- TABLE post-origin -- diff --git a/doc/en/spec/database/db-post-media-exif.md b/doc/en/spec/database/db-post-media-exif.md new file mode 100644 index 0000000000..fb5e6cc015 --- /dev/null +++ b/doc/en/spec/database/db-post-media-exif.md @@ -0,0 +1,55 @@ +# Table post-media-exif + +Exif data for attached media, see https://exiv2.org/tags.html + +## Fields + +| Field | Description | Type | Null | Key | Default | Extra | +| ----------------- | ------------------------------------------------------------------------------------------------------------------- | ----------------- | ---- | --- | ------- | ----- | +| media-id | If of the post-media entry with EXIF data | int unsigned | NO | PRI | NULL | | +| uri-id | Id of the item-uri table entry that contains the item uri | int unsigned | NO | | NULL | | +| raw-data | JSON array with the raw exif data | text | YES | | NULL | | +| coord | GPS coordinates (latitude and longitude) representing the location where the picture was taken. | varchar(255) | YES | | NULL | | +| FocalLength | The focal length of the lens in mm. | varchar(16) | YES | | NULL | | +| ExposureTime | The exposure time in fractions of 1/x or full seconds. | varchar(16) | YES | | NULL | | +| ApertureFNumber | The lens aperture calculated as f number | varchar(16) | YES | | NULL | | +| ISOSpeedRatings | The ISO speed used to expose the image. | smallint unsigned | YES | | NULL | | +| LensSpecification | Lens specifications, for example 35mm f/2.8 or 70-200mm f/2.8-6.3 | varchar(32) | YES | | NULL | | +| FocusDistance | The distance to the subject, given in meters. | varchar(16) | YES | | NULL | | +| CCDWidth | | varchar(16) | YES | | NULL | | +| BodySerialNumber | The serial number of the body of the camera. | varchar(255) | YES | | NULL | | +| Artist | The name of the camera owner, photographer or image creator. | varchar(255) | YES | | NULL | | +| Copyright | Copyright information. In this standard the tag is used to indicate both the photographer and editor copyrights. | varchar(255) | YES | | NULL | | +| DateTime | The date and time of image creation. In Exif standard, it is the time the file was changed. | datetime | YES | | NULL | | +| DateTimeOriginal | The date and time when the original image data was generated. | datetime | YES | | NULL | | +| DateTimeDigitized | The date and time when the image was stored as digital data. | datetime | YES | | NULL | | +| ExpandFilm | The type or brand of film used for the image, such as analog film types (e.g., Kodak E100SW). | varchar(255) | YES | | NULL | | +| ExpandLens | The lens model or description used for the image (e.g., Nikkor 20-35mm f/2.8 zoom). | varchar(255) | YES | | NULL | | +| HostComputer | Information about the host computer used to generate the image. | varchar(255) | YES | | NULL | | +| ImageDescription | A character string giving the title of the image. | text | YES | | NULL | | +| ImageUniqueID | A unique identifier for each image, typically in the form of a UUID or other unique string. | varchar(255) | YES | | NULL | | +| LensMake | The name of the lens manufacturer. | varchar(255) | YES | | NULL | | +| LensModel | The model name or model number of the lens used. | varchar(255) | YES | | NULL | | +| Make | The manufacturer of the recording equipment. | varchar(255) | YES | | NULL | | +| MakerNote | A tag for manufacturers of Exif writers to record any desired information. The contents are up to the manufacturer. | varchar(255) | YES | | NULL | | +| Model | The model name or model number of the equipment. | varchar(255) | YES | | NULL | | +| OwnerName | The owner of the camera. | varchar(255) | YES | | NULL | | +| Orientation | The image orientation in terms of rows and columns. | tinyint unsigned | YES | | NULL | | +| Software | The name and version of the software or firmware of the camera or image input device used to generate the image. | varchar(255) | YES | | NULL | | +| UserComment | A comment provided by the user about the image. | text | YES | | NULL | | + +## Indexes + +| Name | Fields | +| ------- | -------- | +| PRIMARY | media-id | +| uri-id | uri-id | + +## Foreign keys + +| Field | Target Table | Target Field | +|-------|--------------|--------------| +| media-id | [post-media](help/spec/database/db-post-media) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | + +Return to [database documentation](help/spec/database/index) diff --git a/doc/en/spec/database/index.md b/doc/en/spec/database/index.md index 3c0e2e0df5..3ad69622bf 100644 --- a/doc/en/spec/database/index.md +++ b/doc/en/spec/database/index.md @@ -65,6 +65,7 @@ | [post-history](help/spec/database/db-post-history) | Post history | | [post-link](help/spec/database/db-post-link) | Post related external links | | [post-media](help/spec/database/db-post-media) | Attached media | +| [post-media-exif](help/spec/database/db-post-media-exif) | Exif data for attached media, see https://exiv2.org/tags.html | | [post-origin](help/spec/database/db-post-origin) | Posts from local users | | [post-question](help/spec/database/db-post-question) | Question | | [post-question-option](help/spec/database/db-post-question-option) | Question option | diff --git a/src/Model/Post/Media.php b/src/Model/Post/Media.php index f75d8adfff..6ea7b677ae 100644 --- a/src/Model/Post/Media.php +++ b/src/Model/Post/Media.php @@ -105,15 +105,22 @@ class Media $stored = $media; $media = self::fetchAdditionalData($media); + $exif = $media['exif'] ?? null; $media = self::unsetEmptyFields($media); $media = DI::dbaDefinition()->truncateFieldsForTable('post-media', $media); if (array_diff_assoc($media, $stored)) { $result = DBA::insert('post-media', $media, Database::INSERT_UPDATE); - DI::logger()->info('Updated media', ['result' => $result, 'media' => $media]); + $id = $media['id'] ?? DBA::lastInsertId(); + DI::logger()->info('Updated media', ['result' => $result, 'id' => $id, 'media' => $media]); } else { + $id = null; DI::logger()->info('Nothing to update', ['media' => $media]); } + + if (isset($id) && isset($exif)) { + MediaExif::insert($id, $media['uri-id'], $exif); + } return $result; } @@ -253,6 +260,7 @@ class Media $media['width'] = $imagedata[0]; $media['height'] = $imagedata[1]; $media['blurhash'] = $imagedata['blurhash'] ?? null; + $media['exif'] = $imagedata['exif'] ?? null; if (!empty($imagedata['description']) && empty($media['description'])) { $media['description'] = $imagedata['description']; DI::logger()->debug('Detected text for image', $media); diff --git a/src/Model/Post/MediaExif.php b/src/Model/Post/MediaExif.php new file mode 100644 index 0000000000..c5cbc3e37d --- /dev/null +++ b/src/Model/Post/MediaExif.php @@ -0,0 +1,265 @@ + $media_id, + 'uri-id' => $uri_id, + 'raw-data' => json_encode($data), + 'FocalLength' => self::getFocalLength($exif), + 'ExposureTime' => self::getExposureTime($exif), + 'LensSpecification' => self::getLensSpecification($exif), + 'ApertureFNumber' => $data['COMPUTED']['ApertureFNumber'] ?? null, + 'FocusDistance' => $data['COMPUTED']['FocusDistance'] ?? null, + 'CCDWidth' => $data['COMPUTED']['CCDWidth'] ?? null, + 'ISOSpeedRatings' => $exif['ISOSpeedRatings'] ?? null, + 'DateTime' => self::getDateTime($exif), + 'DateTimeOriginal' => self::getDateTimeOriginal($exif), + 'DateTimeDigitized' => self::getDateTimeDigitized($exif), + 'BodySerialNumber' => $exif['BodySerialNumber'] ?? null, + 'Orientation' => $exif['Orientation'] ?? null, + 'Artist' => $exif['Artist'] ?? null, + 'Copyright' => $data['COMPUTED']['Copyright'] ?? null, + 'ExpandFilm' => $exif['ExpandFilm'] ?? null, + 'ExpandLens' => $exif['ExpandLens'] ?? null, + 'HostComputer' => $exif['HostComputer'] ?? null, + 'ImageDescription' => $exif['ImageDescription'] ?? null, + "ImageUniqueID" => $exif['ImageUniqueID'] ?? null, + "LensMake" => $exif['LensMake'] ?? null, + "LensModel" => $exif['LensModel'] ?? null, + 'Make' => $exif['Make'] ?? null, + 'MakerNote' => $exif['MakerNote'] ?? null, + 'Model' => $exif['Model'] ?? null, + 'OwnerName' => $exif['OwnerName'] ?? null, + 'Software' => $exif['Software'] ?? null, + "UserComment" => $exif['UserComment'] ?? null, + ]; + + if (isset($exif['GPSLatitude']) && isset($exif['GPSLatitudeRef']) && isset($exif['GPSLongitude']) && isset($exif['GPSLongitudeRef'])) { + $row['coord'] = Photo::getGps($exif['GPSLatitude'], $exif['GPSLatitudeRef']) . ' ' . Photo::getGps($exif['GPSLongitude'], $exif['GPSLongitudeRef']); + } + + $row = DI::dbaDefinition()->truncateFieldsForTable('post-media-exif', $row); + + $result = DBA::insert('post-media-exif', $row, Database::INSERT_UPDATE); + DI::logger()->info('Updated media exif', ['result' => $result, 'row' => $row]); + return $result; + } + + /** + * Get the lens specification from exif data + * + * @param array $exif + * @return string|null + */ + private static function getLensSpecification(array $exif): ?string + { + if (!isset($exif['LensSpecification']) || !is_array($exif['LensSpecification']) || count($exif['LensSpecification']) != 4) { + return null; + } + + $vals = []; + foreach ($exif['LensSpecification'] as $val) { + $parts = explode('/', $val); + if (count($parts) == 2 && is_numeric($parts[0]) && is_numeric($parts[1]) && $parts[1] != 0) { + $vals[] = (float) $parts[0] / (float) $parts[1]; + } else { + $vals[] = null; + } + } + + $LensSpecification = null; + if (count($vals) == 4 && !in_array(null, $vals)) { + if (isset($vals[0]) && $vals[0] == $vals[1]) { + $LensSpecification = round($vals[0]) . 'mm'; + } elseif (isset($vals[0]) && isset($vals[1])) { + $LensSpecification = round($vals[0]) . '-' . round($vals[1]) . 'mm'; + } + if (isset($vals[2]) && $vals[2] == $vals[3]) { + $LensSpecification .= ' f/' . round($vals[2], 1); + } elseif (isset($vals[2]) && isset($vals[3])) { + $LensSpecification .= ' f/' . round($vals[2], 1) . '-' . round($vals[3], 1); + } + } + + return $LensSpecification; + } + + /** + * Get the focal length from exif data + * + * @param array $exif + * @return string|null + */ + private static function getFocalLength(array $exif): ?string + { + if (!isset($exif['FocalLength'])) { + return null; + } + + $parts = explode('/', $exif['FocalLength']); + if (count($parts) == 2 && is_numeric($parts[0]) && is_numeric($parts[1]) && $parts[1] != 0) { + return round((float) $parts[0] / (float) $parts[1], 1) . ' mm'; + } + + return null; + } + + /** + * Get the exposure time from exif data + * + * @param array $exif + * @return string|null + */ + private static function getExposureTime(array $exif): ?string + { + if (!isset($exif['ExposureTime'])) { + return null; + } + + $parts = explode('/', $exif['ExposureTime']); + if (count($parts) == 2 && is_numeric($parts[0]) && is_numeric($parts[1]) && $parts[1] != 0) { + $value = (float) $parts[0] / (float) $parts[1]; + if ($value >= 1) { + return (string) round($value, 0); + } elseif ($value > 0) { + return '1/' . round(1 / $value); + } + } + + return null; + } + + /** + * Get the DateTime from exif data + * + * @param array $exif + * @return string|null + */ + private static function getDateTime(array $exif): ?string + { + $dateTime = $exif['DateTime'] ?? null; + if ($dateTime && isset($exif['OffsetTime'])) { + $dateTime .= ' ' . $exif['OffsetTime']; + } + return $dateTime ? DateTimeFormat::utc($dateTime) : null; + } + + /** + * Get the DateTimeOriginal from exif data + * + * @param array $exif + * @return string|null + */ + private static function getDateTimeOriginal(array $exif): ?string + { + $dateTime = $exif['DateTimeOriginal'] ?? null; + if ($dateTime && isset($exif['OffsetTimeOriginal'])) { + $dateTime .= ' ' . $exif['OffsetTimeOriginal']; + } + return $dateTime ? DateTimeFormat::utc($dateTime) : null; + } + + /** + * Get the DateTimeDigitized from exif data + * + * @param array $exif + * @return string|null + */ + private static function getDateTimeDigitized(array $exif): ?string + { + $dateTime = $exif['DateTimeDigitized'] ?? null; + if ($dateTime && isset($exif['OffsetTimeDigitized'])) { + $dateTime .= ' ' . $exif['OffsetTimeDigitized']; + } + return $dateTime ? DateTimeFormat::utc($dateTime) : null; + } + + /** + * Translation for all tags that aren't known by "exif_read_data" + * @see https://exiv2.org/tags.html + * @param array $data + * @return array + */ + public static function translate(array $data): array + { + $translation = [ + 'UndefinedTag:0x4746' => 'Rating', + 'UndefinedTag:0x8830' => 'SensitivityType', + 'UndefinedTag:0x8831' => 'StandardOutputSensitivity', + 'UndefinedTag:0x8832' => 'RecommendedExposureIndex', + 'UndefinedTag:0x9010' => 'OffsetTime', + 'UndefinedTag:0x9011' => 'OffsetTimeOriginal', + 'UndefinedTag:0x9012' => 'OffsetTimeDigitized', + 'UndefinedTag:0x9402' => 'Pressure', + 'UndefinedTag:0xA431' => 'BodySerialNumber', + 'UndefinedTag:0xA432' => 'LensSpecification', + 'UndefinedTag:0xA433' => 'LensMake', + 'UndefinedTag:0xA434' => 'LensModel', + 'UndefinedTag:0xA460' => 'CompositeImage', + 'UndefinedTag:0xAFC1' => 'ExpandLens', + 'UndefinedTag:0xAFC2' => 'ExpandFilm', + 'UndefinedTag:0xC4A5' => 'PrintImageMatching', + ]; + $exif = []; + foreach ($data as $key => $value) { + if (isset($translation[$key])) { + $exif[$translation[$key]] = $value; + } else { + $exif[$key] = $value; + } + } + + $translation = [ + 'InternalSerialNumber' => 'BodySerialNumber', + 'Author' => 'Artist', + ]; + + foreach ($translation as $key => $value) { + if (!isset($exif[$value]) && isset($exif[$key])) { + $exif[$value] = $exif[$key]; + } + unset($exif[$key]); + } + + if (isset($data['COMPUTED']['UserComment'])) { + $exif['UserComment'] = $data['COMPUTED']['UserComment']; + } + + if (!isset($exif['UserComment']) && isset($data['COMMENT']) && is_array($data['COMMENT'])) { + $exif['UserComment'] = implode("\n", $data['COMMENT']); + unset($exif['COMMENT']); + } + return $exif; + } +} diff --git a/src/Util/Images.php b/src/Util/Images.php index 5fcdb29381..ec251fee73 100644 --- a/src/Util/Images.php +++ b/src/Util/Images.php @@ -20,7 +20,7 @@ use Friendica\Object\Image; class Images { // @todo add IMAGETYPE_AVIF once our minimal supported PHP version is 8.1.0 - const IMAGETYPES = [IMAGETYPE_WEBP, IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF, IMAGETYPE_BMP]; + public const IMAGETYPES = [IMAGETYPE_WEBP, IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF, IMAGETYPE_BMP]; /** * Get the Imagick format for the given image type @@ -377,6 +377,19 @@ class Images $data['description'] = $media['description']; } } + + try { + $stream = fopen('php://memory', 'r+'); + fwrite($stream, $img_str); + rewind($stream); + $exif = @exif_read_data($stream, 'ANY_TAG, IFD0, EXIF, APP12, GPS, INTEROP'); + fclose($stream); + if (is_array($exif)) { + $data['exif'] = self::sanitizeExifArray($exif); + } + } catch (\Exception $e) { + DI::logger()->error('Exception when trying to read EXIF data', ['code' => $e->getCode(), 'message' => $e->getMessage()]); + } } $data['size'] = $filesize; @@ -384,6 +397,22 @@ class Images return $data; } + /** + * Sanitize EXIF array by removing invalid UTF-8 characters from strings + * + * @param array $exif + * @return array + */ + private static function sanitizeExifArray(array $exif): array + { + array_walk_recursive($exif, function (&$value) { + if (is_string($value)) { + $value = trim(iconv('UTF-8', 'UTF-8//IGNORE', $value)); + } + }); + return $exif; + } + /** * Returns scaling information * @@ -454,7 +483,7 @@ class Images return self::getBBCodeByUrl( DI::baseUrl() . '/photos/' . $nickname . '/image/' . $resource_id, DI::baseUrl() . '/photo/' . $resource_id . '-' . $preview . $ext, - $description + $description, ); } diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index f71c1d870b..bcb10cad41 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -44,7 +44,7 @@ use Friendica\Database\DBA; // This file is required several times during the test in DbaDefinition which justifies this condition if (!defined('DB_UPDATE_VERSION')) { - define('DB_UPDATE_VERSION', 1589); + define('DB_UPDATE_VERSION', 1590); } return [ @@ -1498,6 +1498,46 @@ return [ "attach-id" => ["attach-id"], ] ], + "post-media-exif" => [ + "comment" => "Exif data for attached media, see https://exiv2.org/tags.html", + "fields" => [ + "media-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["post-media" => "id"], "primary" => "1", "comment" => "If of the post-media entry with EXIF data"], + "uri-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "raw-data" => ["type" => "text", "comment" => "JSON array with the raw exif data"], + "coord" => ["type" => "varchar(255)", "comment" => "GPS coordinates (latitude and longitude) representing the location where the picture was taken."], + "FocalLength" => ["type" => "varchar(16)", "comment" => "The focal length of the lens in mm."], + "ExposureTime" => ["type" => "varchar(16)", "comment" => "The exposure time in fractions of 1/x or full seconds."], + "ApertureFNumber" => ["type" => "varchar(16)", "comment" => "The lens aperture calculated as f number"], + "ISOSpeedRatings" => ["type" => "smallint unsigned", "comment" => "The ISO speed used to expose the image."], + "LensSpecification" => ["type" => "varchar(32)", "comment" => "Lens specifications, for example 35mm f/2.8 or 70-200mm f/2.8-6.3"], + "FocusDistance" => ["type" => "varchar(16)", "comment" => "The distance to the subject, given in meters."], + "CCDWidth" => ["type" => "varchar(16)", "comment" => ""], + "BodySerialNumber" => ["type" => "varchar(255)", "comment" => "The serial number of the body of the camera."], + "Artist" => ["type" => "varchar(255)", "comment" => "The name of the camera owner, photographer or image creator."], + "Copyright" => ["type" => "varchar(255)", "comment" => "Copyright information. In this standard the tag is used to indicate both the photographer and editor copyrights."], + "DateTime" => ["type" => "datetime", "comment" => "The date and time of image creation. In Exif standard, it is the time the file was changed."], + "DateTimeOriginal" => ["type" => "datetime", "comment" => "The date and time when the original image data was generated."], + "DateTimeDigitized" => ["type" => "datetime", "comment" => "The date and time when the image was stored as digital data."], + "ExpandFilm" => ["type" => "varchar(255)", "comment" => "The type or brand of film used for the image, such as analog film types (e.g., Kodak E100SW)."], + "ExpandLens" => ["type" => "varchar(255)", "comment" => "The lens model or description used for the image (e.g., Nikkor 20-35mm f/2.8 zoom)."], + "HostComputer" => ["type" => "varchar(255)", "comment" => "Information about the host computer used to generate the image."], + "ImageDescription" => ["type" => "text", "comment" => "A character string giving the title of the image."], + "ImageUniqueID" => ["type" => "varchar(255)", "comment" => "A unique identifier for each image, typically in the form of a UUID or other unique string."], + "LensMake" => ["type" => "varchar(255)", "comment" => "The name of the lens manufacturer."], + "LensModel" => ["type" => "varchar(255)", "comment" => "The model name or model number of the lens used."], + "Make" => ["type" => "varchar(255)", "comment" => "The manufacturer of the recording equipment."], + "MakerNote" => ["type" => "varchar(255)", "comment" => "A tag for manufacturers of Exif writers to record any desired information. The contents are up to the manufacturer."], + "Model" => ["type" => "varchar(255)", "comment" => "The model name or model number of the equipment."], + "OwnerName" => ["type" => "varchar(255)", "comment" => "The owner of the camera."], + "Orientation" => ["type" => "tinyint unsigned", "comment" => "The image orientation in terms of rows and columns."], + "Software" => ["type" => "varchar(255)", "comment" => "The name and version of the software or firmware of the camera or image input device used to generate the image."], + "UserComment" => ["type" => "text", "comment" => "A comment provided by the user about the image."], + ], + "indexes" => [ + "PRIMARY" => ["media-id"], + "uri-id" => ["uri-id"], + ] + ], "post-origin" => [ "comment" => "Posts from local users", "fields" => [ From 7e7ceb671ac5308a9f754e57fd337d43d7ee1145 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 8 Mar 2026 16:00:29 +0000 Subject: [PATCH 183/197] Fix code style --- src/Model/Post/Media.php | 74 +- static/dbstructure.config.php | 2668 ++++++++++++++++----------------- 2 files changed, 1371 insertions(+), 1371 deletions(-) diff --git a/src/Model/Post/Media.php b/src/Model/Post/Media.php index 6ea7b677ae..c19b10511b 100644 --- a/src/Model/Post/Media.php +++ b/src/Model/Post/Media.php @@ -44,22 +44,22 @@ use GuzzleHttp\Psr7\Uri; */ class Media { - const UNKNOWN = 0; - const IMAGE = 1; - const VIDEO = 2; - const AUDIO = 3; - const TEXT = 4; - const APPLICATION = 5; - const TORRENT = 16; - const HTML = 17; - const XML = 18; - const PLAIN = 19; - const ACTIVITY = 20; - const ACCOUNT = 21; - const HLS = 22; - const JSON = 23; - const LD = 24; - const DOCUMENT = 128; + public const UNKNOWN = 0; + public const IMAGE = 1; + public const VIDEO = 2; + public const AUDIO = 3; + public const TEXT = 4; + public const APPLICATION = 5; + public const TORRENT = 16; + public const HTML = 17; + public const XML = 18; + public const PLAIN = 19; + public const ACTIVITY = 20; + public const ACCOUNT = 21; + public const HLS = 22; + public const JSON = 23; + public const LD = 24; + public const DOCUMENT = 128; /** * Insert a post-media record @@ -173,11 +173,11 @@ class Media 'url' => $href, 'size' => $length, 'mimetype' => $type, - 'description' => $title + 'description' => $title, ]); - return '[attach]href="' . $media['url'] . '" length="' . $media['size'] . - '" type="' . $media['mimetype'] . '" title="' . $media['description'] . '"[/attach]'; + return '[attach]href="' . $media['url'] . '" length="' . $media['size'] + . '" type="' . $media['mimetype'] . '" title="' . $media['description'] . '"[/attach]'; } private static function setModified(array $media, string $lastModified): array @@ -235,7 +235,7 @@ class Media $media['mimetype'] = $curlResult->getContentType(); } if (empty($media['size']) && $is_head) { - $media['size'] = (int)($curlResult->getHeader('Content-Length')[0] ?? strlen($curlResult->getBodyString() ?? '')); + $media['size'] = (int) ($curlResult->getHeader('Content-Length')[0] ?? strlen($curlResult->getBodyString() ?? '')); } $media = self::setModified($media, $curlResult->getHeader('Last-Modified')[0] ?? ''); } else { @@ -260,7 +260,7 @@ class Media $media['width'] = $imagedata[0]; $media['height'] = $imagedata[1]; $media['blurhash'] = $imagedata['blurhash'] ?? null; - $media['exif'] = $imagedata['exif'] ?? null; + $media['exif'] = $imagedata['exif'] ?? null; if (!empty($imagedata['description']) && empty($media['description'])) { $media['description'] = $imagedata['description']; DI::logger()->debug('Detected text for image', $media); @@ -373,8 +373,8 @@ class Media } if ( - !empty($item['plink']) && Strings::compareLink($item['plink'], $media['url']) && - parse_url($item['plink'], PHP_URL_HOST) != parse_url($item['uri'], PHP_URL_HOST) + !empty($item['plink']) && Strings::compareLink($item['plink'], $media['url']) + && parse_url($item['plink'], PHP_URL_HOST) != parse_url($item['uri'], PHP_URL_HOST) ) { DI::logger()->debug('Not a link to an activity', ['uri-id' => $media['uri-id'], 'url' => $media['url'], 'plink' => $item['plink'], 'uri' => $item['uri']]); $media['type'] = $media['type'] == self::ACTIVITY ? self::JSON : $media['type']; @@ -794,7 +794,7 @@ class Media foreach (explode("\n", $curlResult->getBodyString() ?? '') as $line) { if (strpos(trim($line), '#EXT-X-STREAM-INF') === 0) { if (preg_match('/RESOLUTION=([\d]+)x([\d]+)/', $line, $matches)) { - $resolutions[$matches[1]] = [(int)$matches[1], (int)$matches[2]]; + $resolutions[$matches[1]] = [(int) $matches[1], (int) $matches[2]]; } } } @@ -893,7 +893,7 @@ class Media 'type' => self::IMAGE, 'url' => $image, 'preview' => $picture[2], - 'description' => $picture[3] + 'description' => $picture[3], ]; } elseif (self::isLinkToPhoto($picture[1], $picture[2])) { $body = str_replace($picture[0], '', $body); @@ -903,7 +903,7 @@ class Media 'type' => self::IMAGE, 'url' => $picture[1], 'preview' => $picture[2], - 'description' => $picture[3] + 'description' => $picture[3], ]; } elseif ($removepicturelinks) { $body = str_replace($picture[0], '', $body); @@ -913,7 +913,7 @@ class Media 'type' => self::UNKNOWN, 'url' => $picture[1], 'preview' => $picture[2], - 'description' => $picture[3] + 'description' => $picture[3], ]; } } @@ -938,7 +938,7 @@ class Media 'type' => self::IMAGE, 'url' => $image, 'preview' => $picture[2], - 'description' => null + 'description' => null, ]; } elseif (self::isLinkToPhoto($picture[1], $picture[2])) { $body = str_replace($picture[0], '', $body); @@ -948,7 +948,7 @@ class Media 'type' => self::IMAGE, 'url' => $picture[1], 'preview' => $picture[2], - 'description' => null + 'description' => null, ]; } elseif ($removepicturelinks) { $body = str_replace($picture[0], '', $body); @@ -958,7 +958,7 @@ class Media 'type' => self::UNKNOWN, 'url' => $picture[1], 'preview' => $picture[2], - 'description' => null + 'description' => null, ]; } } @@ -1362,7 +1362,7 @@ class Media 'src' => $links[0]['preview'], 'height' => $links[0]['preview-height'], 'width' => $links[0]['preview-width'], - ]] + ]], ]; $body .= "\n" . PageInfo::getFooterFromData($data); @@ -1424,9 +1424,9 @@ class Media */ public static function getPreviewUrlForId(int $id, string $size = ''): string { - return DI::baseUrl() . '/photo/preview/' . - (Proxy::getPixelsFromSize($size) ? Proxy::getPixelsFromSize($size) . '/' : '') . - $id; + return DI::baseUrl() . '/photo/preview/' + . (Proxy::getPixelsFromSize($size) ? Proxy::getPixelsFromSize($size) . '/' : '') + . $id; } /** @@ -1438,9 +1438,9 @@ class Media */ public static function getUrlForId(int $id, string $size = ''): string { - return DI::baseUrl() . '/photo/media/' . - (Proxy::getPixelsFromSize($size) ? Proxy::getPixelsFromSize($size) . '/' : '') . - $id; + return DI::baseUrl() . '/photo/media/' + . (Proxy::getPixelsFromSize($size) ? Proxy::getPixelsFromSize($size) . '/' : '') + . $id; } /** diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index bcb10cad41..af36604681 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -51,560 +51,560 @@ return [ // Side tables "gserver" => [ "comment" => "Global servers", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "url" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], - "nurl" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], - "version" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "The version of this server software."], - "site_name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], - "info" => ["type" => "text", "comment" => ""], - "register_policy" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => ""], - "registered-users" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => "Number of registered users"], - "active-week-users" => ["type" => "int unsigned", "comment" => "Number of active users in the last week"], - "active-month-users" => ["type" => "int unsigned", "comment" => "Number of active users in the last month"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "url" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "nurl" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "version" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "The version of this server software."], + "site_name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "info" => ["type" => "text", "comment" => ""], + "register_policy" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => ""], + "registered-users" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => "Number of registered users"], + "active-week-users" => ["type" => "int unsigned", "comment" => "Number of active users in the last week"], + "active-month-users" => ["type" => "int unsigned", "comment" => "Number of active users in the last month"], "active-halfyear-users" => ["type" => "int unsigned", "comment" => "Number of active users in the last six month"], - "local-posts" => ["type" => "int unsigned", "comment" => "Number of local posts"], - "local-comments" => ["type" => "int unsigned", "comment" => "Number of local comments"], - "directory-type" => ["type" => "tinyint", "default" => "0", "comment" => "Type of directory service (Poco, Mastodon)"], - "poco" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], - "openwebauth" => ["type" => "varbinary(383)", "comment" => "Path to the OpenWebAuth endpoint"], - "authredirect" => ["type" => "varbinary(383)", "comment" => "Path to the authRedirect endpoint"], - "noscrape" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], - "network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => ""], - "protocol" => ["type" => "tinyint unsigned", "comment" => "The protocol of the server"], - "platform" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "The canonical name of this server software."], - "repository" => ["type" => "varbinary(383)", "comment" => "The url of the source code repository of this server software."], - "homepage" => ["type" => "varbinary(383)", "comment" => "The url of the homepage of this server software."], - "relay-subscribe" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Has the server subscribed to the relay system"], - "relay-scope" => ["type" => "varchar(10)", "not null" => "1", "default" => "", "comment" => "The scope of messages that the server wants to get"], - "detection-method" => ["type" => "tinyint unsigned", "comment" => "Method that had been used to detect that server"], - "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], - "last_poco_query" => ["type" => "datetime", "default" => DBA::NULL_DATETIME, "comment" => ""], - "last_contact" => ["type" => "datetime", "default" => DBA::NULL_DATETIME, "comment" => "Last successful connection request"], - "last_failure" => ["type" => "datetime", "default" => DBA::NULL_DATETIME, "comment" => "Last failed connection request"], - "blocked" => ["type" => "boolean", "comment" => "Server is blocked"], - "failed" => ["type" => "boolean", "comment" => "Connection failed"], - "next_contact" => ["type" => "datetime", "default" => DBA::NULL_DATETIME, "comment" => "Next connection request"], - "redirect-gsid" => ["type" => "int unsigned", "foreign" => ["gserver" => "id"], "comment" => "Target Gserver id in case of a redirect"], + "local-posts" => ["type" => "int unsigned", "comment" => "Number of local posts"], + "local-comments" => ["type" => "int unsigned", "comment" => "Number of local comments"], + "directory-type" => ["type" => "tinyint", "default" => "0", "comment" => "Type of directory service (Poco, Mastodon)"], + "poco" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "openwebauth" => ["type" => "varbinary(383)", "comment" => "Path to the OpenWebAuth endpoint"], + "authredirect" => ["type" => "varbinary(383)", "comment" => "Path to the authRedirect endpoint"], + "noscrape" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => ""], + "protocol" => ["type" => "tinyint unsigned", "comment" => "The protocol of the server"], + "platform" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "The canonical name of this server software."], + "repository" => ["type" => "varbinary(383)", "comment" => "The url of the source code repository of this server software."], + "homepage" => ["type" => "varbinary(383)", "comment" => "The url of the homepage of this server software."], + "relay-subscribe" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Has the server subscribed to the relay system"], + "relay-scope" => ["type" => "varchar(10)", "not null" => "1", "default" => "", "comment" => "The scope of messages that the server wants to get"], + "detection-method" => ["type" => "tinyint unsigned", "comment" => "Method that had been used to detect that server"], + "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "last_poco_query" => ["type" => "datetime", "default" => DBA::NULL_DATETIME, "comment" => ""], + "last_contact" => ["type" => "datetime", "default" => DBA::NULL_DATETIME, "comment" => "Last successful connection request"], + "last_failure" => ["type" => "datetime", "default" => DBA::NULL_DATETIME, "comment" => "Last failed connection request"], + "blocked" => ["type" => "boolean", "comment" => "Server is blocked"], + "failed" => ["type" => "boolean", "comment" => "Connection failed"], + "next_contact" => ["type" => "datetime", "default" => DBA::NULL_DATETIME, "comment" => "Next connection request"], + "redirect-gsid" => ["type" => "int unsigned", "foreign" => ["gserver" => "id"], "comment" => "Target Gserver id in case of a redirect"], ], "indexes" => [ - "PRIMARY" => ["id"], - "nurl" => ["UNIQUE", "nurl(190)"], - "next_contact" => ["next_contact"], - "network" => ["network"], + "PRIMARY" => ["id"], + "nurl" => ["UNIQUE", "nurl(190)"], + "next_contact" => ["next_contact"], + "network" => ["network"], "redirect-gsid" => ["redirect-gsid"], - ] + ], ], "user" => [ "comment" => "The local users", - "fields" => [ - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "parent-uid" => ["type" => "mediumint unsigned", "foreign" => ["user" => "uid"], "comment" => "The parent user that has full control about this user"], - "guid" => ["type" => "varchar(64)", "not null" => "1", "default" => "", "comment" => "A unique identifier for this user"], - "username" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Name that this user is known by"], - "password" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "encrypted password"], - "legacy_password" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Is the password hash double-hashed?"], - "nickname" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "nick- and user name"], - "email" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "the users email address"], - "openid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], - "timezone" => ["type" => "varchar(128)", "not null" => "1", "default" => "", "comment" => "PHP-legal timezone"], - "language" => ["type" => "varchar(32)", "not null" => "1", "default" => "en", "comment" => "default language"], - "register_date" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "timestamp of registration"], - "login_date" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "timestamp of last login"], - "last-activity" => ["type" => "date", "comment" => "Day of the last activity"], - "default-location" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Default for item.location"], - "allow_location" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "1 allows to display the location"], - "theme" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "user theme preference"], - "pubkey" => ["type" => "text", "comment" => "RSA public key 4096 bit"], - "prvkey" => ["type" => "text", "comment" => "RSA private key 4096 bit"], - "verified" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "user is verified through email"], - "blocked" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "1 for user is blocked"], - "blockwall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Prohibit contacts to post to the profile page of the user"], - "hidewall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Hide profile details from unknown viewers"], - "blocktags" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Prohibit contacts to tag the post of this user"], - "notify-flags" => ["type" => "smallint unsigned", "not null" => "1", "default" => "65535", "comment" => "email notification options"], - "page-flags" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "page/profile type"], - "account-type" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""], - "prvnets" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "pwdreset" => ["type" => "varchar(255)", "comment" => "Password reset request token"], - "pwdreset_time" => ["type" => "datetime", "comment" => "Timestamp of the last password reset request"], - "maxreq" => ["type" => "int unsigned", "not null" => "1", "default" => "10", "comment" => ""], - "expire" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => "Delay in days before deleting user-related posts. Scope is controlled by pConfig."], - "account_removed" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "if 1 the account is removed"], - "account_expired" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "account_expires_on" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "timestamp when account expires and will be deleted"], + "fields" => [ + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "parent-uid" => ["type" => "mediumint unsigned", "foreign" => ["user" => "uid"], "comment" => "The parent user that has full control about this user"], + "guid" => ["type" => "varchar(64)", "not null" => "1", "default" => "", "comment" => "A unique identifier for this user"], + "username" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Name that this user is known by"], + "password" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "encrypted password"], + "legacy_password" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Is the password hash double-hashed?"], + "nickname" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "nick- and user name"], + "email" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "the users email address"], + "openid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "timezone" => ["type" => "varchar(128)", "not null" => "1", "default" => "", "comment" => "PHP-legal timezone"], + "language" => ["type" => "varchar(32)", "not null" => "1", "default" => "en", "comment" => "default language"], + "register_date" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "timestamp of registration"], + "login_date" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "timestamp of last login"], + "last-activity" => ["type" => "date", "comment" => "Day of the last activity"], + "default-location" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Default for item.location"], + "allow_location" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "1 allows to display the location"], + "theme" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "user theme preference"], + "pubkey" => ["type" => "text", "comment" => "RSA public key 4096 bit"], + "prvkey" => ["type" => "text", "comment" => "RSA private key 4096 bit"], + "verified" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "user is verified through email"], + "blocked" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "1 for user is blocked"], + "blockwall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Prohibit contacts to post to the profile page of the user"], + "hidewall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Hide profile details from unknown viewers"], + "blocktags" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Prohibit contacts to tag the post of this user"], + "notify-flags" => ["type" => "smallint unsigned", "not null" => "1", "default" => "65535", "comment" => "email notification options"], + "page-flags" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "page/profile type"], + "account-type" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""], + "prvnets" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "pwdreset" => ["type" => "varchar(255)", "comment" => "Password reset request token"], + "pwdreset_time" => ["type" => "datetime", "comment" => "Timestamp of the last password reset request"], + "maxreq" => ["type" => "int unsigned", "not null" => "1", "default" => "10", "comment" => ""], + "expire" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => "Delay in days before deleting user-related posts. Scope is controlled by pConfig."], + "account_removed" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "if 1 the account is removed"], + "account_expired" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "account_expires_on" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "timestamp when account expires and will be deleted"], "expire_notification_sent" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "timestamp of last warning of account expiration"], - "def_gid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => ""], - "allow_cid" => ["type" => "mediumtext", "comment" => "default permission for this user"], - "allow_gid" => ["type" => "mediumtext", "comment" => "default permission for this user"], - "deny_cid" => ["type" => "mediumtext", "comment" => "default permission for this user"], - "deny_gid" => ["type" => "mediumtext", "comment" => "default permission for this user"], - "openidserver" => ["type" => "text", "comment" => ""], + "def_gid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => ""], + "allow_cid" => ["type" => "mediumtext", "comment" => "default permission for this user"], + "allow_gid" => ["type" => "mediumtext", "comment" => "default permission for this user"], + "deny_cid" => ["type" => "mediumtext", "comment" => "default permission for this user"], + "deny_gid" => ["type" => "mediumtext", "comment" => "default permission for this user"], + "openidserver" => ["type" => "text", "comment" => ""], ], "indexes" => [ - "PRIMARY" => ["uid"], - "nickname" => ["nickname(32)"], + "PRIMARY" => ["uid"], + "nickname" => ["nickname(32)"], "parent-uid" => ["parent-uid"], - "guid" => ["guid"], - "email" => ["email(64)"], - ] + "guid" => ["guid"], + "email" => ["email(64)"], + ], ], "user-gserver" => [ "comment" => "User settings about remote servers", - "fields" => [ - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "primary" => "1", "comment" => "Owner User id"], - "gsid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["gserver" => "id"], "primary" => "1", "comment" => "Gserver id"], + "fields" => [ + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "primary" => "1", "comment" => "Owner User id"], + "gsid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["gserver" => "id"], "primary" => "1", "comment" => "Gserver id"], "ignored" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "server accounts are ignored for the user"], ], "indexes" => [ "PRIMARY" => ["uid", "gsid"], - "gsid" => ["gsid"] + "gsid" => ["gsid"], ], ], "item-uri" => [ "comment" => "URI and GUID for items", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"], - "uri" => ["type" => "varbinary(383)", "not null" => "1", "comment" => "URI of an item"], - "guid" => ["type" => "varbinary(255)", "comment" => "A unique identifier for an item"] + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"], + "uri" => ["type" => "varbinary(383)", "not null" => "1", "comment" => "URI of an item"], + "guid" => ["type" => "varbinary(255)", "comment" => "A unique identifier for an item"], ], "indexes" => [ "PRIMARY" => ["id"], - "uri" => ["UNIQUE", "uri"], - "guid" => ["guid"] - ] + "uri" => ["UNIQUE", "uri"], + "guid" => ["guid"], + ], ], "contact" => [ "comment" => "contact table", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], - "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], - "updated" => ["type" => "datetime", "default" => DBA::NULL_DATETIME, "comment" => "Date of last contact update"], - "network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => "Network of the contact"], - "name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Name that this contact is known by"], - "nick" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Nick- and user name of the contact"], - "location" => ["type" => "varchar(255)", "default" => "", "comment" => ""], - "about" => ["type" => "text", "comment" => ""], - "keywords" => ["type" => "text", "comment" => "public keywords (interests) of the contact"], - "xmpp" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "XMPP address"], - "matrix" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Matrix address"], - "avatar" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], - "blurhash" => ["type" => "varbinary(255)", "comment" => "BlurHash representation of the avatar"], - "header" => ["type" => "varbinary(383)", "comment" => "Header picture"], - "url" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], - "nurl" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], - "uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the contact url"], - "addr" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], - "alias" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], - "pubkey" => ["type" => "text", "comment" => "RSA public key 4096 bit"], - "prvkey" => ["type" => "text", "comment" => "RSA private key 4096 bit"], - "batch" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], - "notify" => ["type" => "varbinary(383)", "comment" => ""], - "poll" => ["type" => "varbinary(383)", "comment" => ""], - "subscribe" => ["type" => "varbinary(383)", "comment" => ""], - "last-update" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of the last try to update the contact info"], - "next-update" => ["type" => "datetime", "comment" => "Next connection request"], - "success_update" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of the last successful contact update"], - "failure_update" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of the last failed update"], - "failed" => ["type" => "boolean", "comment" => "Connection failed"], - "term-date" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], - "last-item" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "date of the last post"], - "last-discovery" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "date of the last follower discovery"], - "local-data" => ["type" => "boolean", "comment" => "Is true when there are posts with this contact on the system"], - "blocked" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => "Node-wide block status"], - "block_reason" => ["type" => "text", "comment" => "Node-wide block reason"], - "readonly" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "posts of the contact are readonly"], - "contact-type" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => "Person, organisation, news, community, relay"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], + "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "updated" => ["type" => "datetime", "default" => DBA::NULL_DATETIME, "comment" => "Date of last contact update"], + "network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => "Network of the contact"], + "name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Name that this contact is known by"], + "nick" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Nick- and user name of the contact"], + "location" => ["type" => "varchar(255)", "default" => "", "comment" => ""], + "about" => ["type" => "text", "comment" => ""], + "keywords" => ["type" => "text", "comment" => "public keywords (interests) of the contact"], + "xmpp" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "XMPP address"], + "matrix" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Matrix address"], + "avatar" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "blurhash" => ["type" => "varbinary(255)", "comment" => "BlurHash representation of the avatar"], + "header" => ["type" => "varbinary(383)", "comment" => "Header picture"], + "url" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "nurl" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the contact url"], + "addr" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "alias" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "pubkey" => ["type" => "text", "comment" => "RSA public key 4096 bit"], + "prvkey" => ["type" => "text", "comment" => "RSA private key 4096 bit"], + "batch" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "notify" => ["type" => "varbinary(383)", "comment" => ""], + "poll" => ["type" => "varbinary(383)", "comment" => ""], + "subscribe" => ["type" => "varbinary(383)", "comment" => ""], + "last-update" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of the last try to update the contact info"], + "next-update" => ["type" => "datetime", "comment" => "Next connection request"], + "success_update" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of the last successful contact update"], + "failure_update" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of the last failed update"], + "failed" => ["type" => "boolean", "comment" => "Connection failed"], + "term-date" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "last-item" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "date of the last post"], + "last-discovery" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "date of the last follower discovery"], + "local-data" => ["type" => "boolean", "comment" => "Is true when there are posts with this contact on the system"], + "blocked" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => "Node-wide block status"], + "block_reason" => ["type" => "text", "comment" => "Node-wide block reason"], + "readonly" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "posts of the contact are readonly"], + "contact-type" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => "Person, organisation, news, community, relay"], "manually-approve" => ["type" => "boolean", "comment" => "Contact requests have to be approved manually"], - "archive" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "unsearchable" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Contact prefers to not be searchable"], - "sensitive" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Contact posts sensitive content"], - "baseurl" => ["type" => "varbinary(383)", "default" => "", "comment" => "baseurl of the contact from the gserver record, can be missing"], - "gsid" => ["type" => "int unsigned", "foreign" => ["gserver" => "id", "on delete" => "restrict"], "comment" => "Global Server ID, can be missing"], - "bd" => ["type" => "date", "not null" => "1", "default" => DBA::NULL_DATE, "comment" => ""], + "archive" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "unsearchable" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Contact prefers to not be searchable"], + "sensitive" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Contact posts sensitive content"], + "baseurl" => ["type" => "varbinary(383)", "default" => "", "comment" => "baseurl of the contact from the gserver record, can be missing"], + "gsid" => ["type" => "int unsigned", "foreign" => ["gserver" => "id", "on delete" => "restrict"], "comment" => "Global Server ID, can be missing"], + "bd" => ["type" => "date", "not null" => "1", "default" => DBA::NULL_DATE, "comment" => ""], // User depending fields - "reason" => ["type" => "text", "comment" => ""], - "self" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "1 if the contact is the user him/her self"], - "remote_self" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "rel" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "The kind of the relation between the user and the contact"], - "protocol" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => "Protocol of the contact"], - "hub-verify" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], - "rating" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => "Automatically detected feed poll frequency"], - "priority" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "Feed poll priority"], - "attag" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], - "hidden" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "pending" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => "Contact request is pending"], - "deleted" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Contact has been deleted"], - "info" => ["type" => "mediumtext", "comment" => ""], - "notify_new_posts" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "reason" => ["type" => "text", "comment" => ""], + "self" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "1 if the contact is the user him/her self"], + "remote_self" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "rel" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "The kind of the relation between the user and the contact"], + "protocol" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => "Protocol of the contact"], + "hub-verify" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "rating" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => "Automatically detected feed poll frequency"], + "priority" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "Feed poll priority"], + "attag" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "hidden" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "pending" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => "Contact request is pending"], + "deleted" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Contact has been deleted"], + "info" => ["type" => "mediumtext", "comment" => ""], + "notify_new_posts" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], "fetch_further_information" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""], - "ffi_keyword_denylist" => ["type" => "text", "comment" => ""], + "ffi_keyword_denylist" => ["type" => "text", "comment" => ""], // Deprecated, but still in use - "photo" => ["type" => "varbinary(383)", "default" => "", "comment" => "Link to the profile photo of the contact"], - "thumb" => ["type" => "varbinary(383)", "default" => "", "comment" => "Link to the profile photo (thumb size)"], - "micro" => ["type" => "varbinary(383)", "default" => "", "comment" => "Link to the profile photo (micro size)"], - "name-date" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], - "uri-date" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "photo" => ["type" => "varbinary(383)", "default" => "", "comment" => "Link to the profile photo of the contact"], + "thumb" => ["type" => "varbinary(383)", "default" => "", "comment" => "Link to the profile photo (thumb size)"], + "micro" => ["type" => "varbinary(383)", "default" => "", "comment" => "Link to the profile photo (micro size)"], + "name-date" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "uri-date" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], "avatar-date" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], - "request" => ["type" => "varbinary(383)", "comment" => ""], - "confirm" => ["type" => "varbinary(383)", "comment" => ""], - "poco" => ["type" => "varbinary(383)", "comment" => ""], - "writable" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "forum" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "contact is a group. Deprecated, use 'contact-type' = 'community' and 'manually-approve' = false instead"], - "prv" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "contact is a private group. Deprecated, use 'contact-type' = 'community' and 'manually-approve' = true instead"], - "bdyear" => ["type" => "varchar(4)", "not null" => "1", "default" => "", "comment" => ""], + "request" => ["type" => "varbinary(383)", "comment" => ""], + "confirm" => ["type" => "varbinary(383)", "comment" => ""], + "poco" => ["type" => "varbinary(383)", "comment" => ""], + "writable" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "forum" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "contact is a group. Deprecated, use 'contact-type' = 'community' and 'manually-approve' = false instead"], + "prv" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "contact is a private group. Deprecated, use 'contact-type' = 'community' and 'manually-approve' = true instead"], + "bdyear" => ["type" => "varchar(4)", "not null" => "1", "default" => "", "comment" => ""], // Deprecated fields that aren't in use anymore "site-pubkey" => ["type" => "text", "comment" => "Deprecated"], - "gender" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => "Deprecated"], - "duplex" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Deprecated"], - "issued-id" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => "Deprecated"], - "dfrn-id" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => "Deprecated"], - "aes_allow" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Deprecated"], - "ret-aes" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Deprecated"], - "usehub" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Deprecated"], - "closeness" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "99", "comment" => "Deprecated"], - "profile-id" => ["type" => "int unsigned", "comment" => "Deprecated"], + "gender" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => "Deprecated"], + "duplex" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Deprecated"], + "issued-id" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => "Deprecated"], + "dfrn-id" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => "Deprecated"], + "aes_allow" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Deprecated"], + "ret-aes" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Deprecated"], + "usehub" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Deprecated"], + "closeness" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "99", "comment" => "Deprecated"], + "profile-id" => ["type" => "int unsigned", "comment" => "Deprecated"], ], "indexes" => [ - "PRIMARY" => ["id"], - "uid_name" => ["uid", "name(190)"], - "self_uid" => ["self", "uid"], - "alias_uid" => ["alias(128)", "uid"], - "pending_uid" => ["pending", "uid"], - "blocked_uid" => ["blocked", "uid"], - "uid_rel_network_poll" => ["uid", "rel", "network", "poll(64)", "archive"], - "uid_network_batch" => ["uid", "network", "batch(64)"], - "batch_contact-type" => ["batch(64)", "contact-type"], - "addr_uid" => ["addr(128)", "uid"], - "nurl_uid" => ["nurl(128)", "uid"], - "nick_uid" => ["nick(128)", "uid"], - "attag_uid" => ["attag(96)", "uid"], - "network_uid_lastupdate" => ["network", "uid", "last-update"], + "PRIMARY" => ["id"], + "uid_name" => ["uid", "name(190)"], + "self_uid" => ["self", "uid"], + "alias_uid" => ["alias(128)", "uid"], + "pending_uid" => ["pending", "uid"], + "blocked_uid" => ["blocked", "uid"], + "uid_rel_network_poll" => ["uid", "rel", "network", "poll(64)", "archive"], + "uid_network_batch" => ["uid", "network", "batch(64)"], + "batch_contact-type" => ["batch(64)", "contact-type"], + "addr_uid" => ["addr(128)", "uid"], + "nurl_uid" => ["nurl(128)", "uid"], + "nick_uid" => ["nick(128)", "uid"], + "attag_uid" => ["attag(96)", "uid"], + "network_uid_lastupdate" => ["network", "uid", "last-update"], "uid_network_self_lastupdate" => ["uid", "network", "self", "last-update"], - "next-update" => ["next-update"], - "local-data-next-update" => ["local-data", "next-update"], - "uid_lastitem" => ["uid", "last-item"], - "uid_created" => ["uid", "created"], - "baseurl" => ["baseurl(64)"], - "uid_contact-type" => ["uid", "contact-type"], - "uid_self_contact-type" => ["uid", "self", "contact-type"], - "self_network_uid" => ["self", "network", "uid"], - "gsid_uid_failed" => ["gsid", "uid", "failed"], - "uri-id" => ["uri-id"], - ] + "next-update" => ["next-update"], + "local-data-next-update" => ["local-data", "next-update"], + "uid_lastitem" => ["uid", "last-item"], + "uid_created" => ["uid", "created"], + "baseurl" => ["baseurl(64)"], + "uid_contact-type" => ["uid", "contact-type"], + "uid_self_contact-type" => ["uid", "self", "contact-type"], + "self_network_uid" => ["self", "network", "uid"], + "gsid_uid_failed" => ["gsid", "uid", "failed"], + "uri-id" => ["uri-id"], + ], ], "tag" => [ "comment" => "tags and mentions", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""], "name" => ["type" => "varchar(96)", "not null" => "1", "default" => "", "comment" => ""], - "url" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "url" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], "type" => ["type" => "tinyint unsigned", "comment" => "Type of the tag (Unknown, General Collection, Follower Collection or Account)"], ], "indexes" => [ - "PRIMARY" => ["id"], + "PRIMARY" => ["id"], "type_name_url" => ["UNIQUE", "name", "url"], - "url" => ["url"] - ] + "url" => ["url"], + ], ], "permissionset" => [ "comment" => "", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner id of this permission set"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner id of this permission set"], "allow_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed contact.id '<19><78>'"], "allow_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed circles"], - "deny_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied contact.id"], - "deny_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied circles"], + "deny_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied contact.id"], + "deny_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied circles"], ], "indexes" => [ - "PRIMARY" => ["id"], + "PRIMARY" => ["id"], "uid_allow_cid_allow_gid_deny_cid_deny_gid" => ["uid", "allow_cid(50)", "allow_gid(30)", "deny_cid(50)", "deny_gid(30)"], - ] + ], ], "verb" => [ "comment" => "Activity Verbs", - "fields" => [ - "id" => ["type" => "smallint unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"], - "name" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => ""] + "fields" => [ + "id" => ["type" => "smallint unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"], + "name" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => ""], ], "indexes" => [ "PRIMARY" => ["id"], - "name" => ["name"] - ] + "name" => ["name"], + ], ], // Main tables "2fa_app_specific_password" => [ "comment" => "Two-factor app-specific _password", - "fields" => [ - "id" => ["type" => "mediumint unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "Password ID for revocation"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "foreign" => ["user" => "uid"], "comment" => "User ID"], - "description" => ["type" => "varchar(255)", "comment" => "Description of the usage of the password"], + "fields" => [ + "id" => ["type" => "mediumint unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "Password ID for revocation"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "foreign" => ["user" => "uid"], "comment" => "User ID"], + "description" => ["type" => "varchar(255)", "comment" => "Description of the usage of the password"], "hashed_password" => ["type" => "varchar(255)", "not null" => "1", "comment" => "Hashed password"], - "generated" => ["type" => "datetime", "not null" => "1", "comment" => "Datetime the password was generated"], - "last_used" => ["type" => "datetime", "comment" => "Datetime the password was last used"], + "generated" => ["type" => "datetime", "not null" => "1", "comment" => "Datetime the password was generated"], + "last_used" => ["type" => "datetime", "comment" => "Datetime the password was last used"], ], "indexes" => [ - "PRIMARY" => ["id"], + "PRIMARY" => ["id"], "uid_description" => ["uid", "description(190)"], - ] + ], ], "2fa_recovery_codes" => [ "comment" => "Two-factor authentication recovery codes", - "fields" => [ - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "User ID"], - "code" => ["type" => "varchar(50)", "not null" => "1", "primary" => "1", "comment" => "Recovery code string"], + "fields" => [ + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "User ID"], + "code" => ["type" => "varchar(50)", "not null" => "1", "primary" => "1", "comment" => "Recovery code string"], "generated" => ["type" => "datetime", "not null" => "1", "comment" => "Datetime the code was generated"], - "used" => ["type" => "datetime", "comment" => "Datetime the code was used"], + "used" => ["type" => "datetime", "comment" => "Datetime the code was used"], ], "indexes" => [ - "PRIMARY" => ["uid", "code"] - ] + "PRIMARY" => ["uid", "code"], + ], ], "2fa_trusted_browser" => [ "comment" => "Two-factor authentication trusted browsers", - "fields" => [ + "fields" => [ "cookie_hash" => ["type" => "varchar(80)", "not null" => "1", "primary" => "1", "comment" => "Trusted cookie hash"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "foreign" => ["user" => "uid"], "comment" => "User ID"], - "user_agent" => ["type" => "text", "comment" => "User agent string"], - "trusted" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => "Whenever this browser should be trusted or not"], - "created" => ["type" => "datetime", "not null" => "1", "comment" => "Datetime the trusted browser was recorded"], - "last_used" => ["type" => "datetime", "comment" => "Datetime the trusted browser was last used"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "foreign" => ["user" => "uid"], "comment" => "User ID"], + "user_agent" => ["type" => "text", "comment" => "User agent string"], + "trusted" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => "Whenever this browser should be trusted or not"], + "created" => ["type" => "datetime", "not null" => "1", "comment" => "Datetime the trusted browser was recorded"], + "last_used" => ["type" => "datetime", "comment" => "Datetime the trusted browser was last used"], ], "indexes" => [ "PRIMARY" => ["cookie_hash"], - "uid" => ["uid"], - ] + "uid" => ["uid"], + ], ], "account-suggestion" => [ "comment" => "Account suggestion", - "fields" => [ + "fields" => [ "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the account url"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "User ID"], - "level" => ["type" => "smallint unsigned", "comment" => "level of closeness"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "User ID"], + "level" => ["type" => "smallint unsigned", "comment" => "level of closeness"], "ignore" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "If set, this account will not be suggested again"], ], "indexes" => [ - "PRIMARY" => ["uid", "uri-id"], + "PRIMARY" => ["uid", "uri-id"], "uri-id_uid" => ["uri-id", "uid"], - ] + ], ], "account-user" => [ "comment" => "Remote and local accounts", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], "uri-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the account url"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "foreign" => ["user" => "uid"], "comment" => "User ID"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "foreign" => ["user" => "uid"], "comment" => "User ID"], ], "indexes" => [ - "PRIMARY" => ["id"], + "PRIMARY" => ["id"], "uri-id_uid" => ["UNIQUE", "uri-id", "uid"], "uid_uri-id" => ["uid", "uri-id"], - ] + ], ], "apcontact" => [ "comment" => "ActivityPub compatible contacts - used in the ActivityPub implementation", - "fields" => [ - "url" => ["type" => "varbinary(383)", "not null" => "1", "primary" => "1", "comment" => "URL of the contact"], - "uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the apcontact url"], - "uuid" => ["type" => "varbinary(255)", "comment" => ""], - "type" => ["type" => "varchar(20)", "not null" => "1", "comment" => ""], - "following" => ["type" => "varbinary(383)", "comment" => ""], - "followers" => ["type" => "varbinary(383)", "comment" => ""], - "inbox" => ["type" => "varbinary(383)", "not null" => "1", "comment" => ""], - "outbox" => ["type" => "varbinary(383)", "comment" => ""], - "sharedinbox" => ["type" => "varbinary(383)", "comment" => ""], - "featured" => ["type" => "varbinary(383)", "comment" => "Address for the collection of featured posts"], - "featured-tags" => ["type" => "varbinary(383)", "comment" => "Address for the collection of featured tags"], - "manually-approve" => ["type" => "boolean", "comment" => ""], - "discoverable" => ["type" => "boolean", "comment" => "Mastodon extension: true if profile is published in their directory"], - "suspended" => ["type" => "boolean", "comment" => "Mastodon extension: true if profile is suspended"], + "fields" => [ + "url" => ["type" => "varbinary(383)", "not null" => "1", "primary" => "1", "comment" => "URL of the contact"], + "uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the apcontact url"], + "uuid" => ["type" => "varbinary(255)", "comment" => ""], + "type" => ["type" => "varchar(20)", "not null" => "1", "comment" => ""], + "following" => ["type" => "varbinary(383)", "comment" => ""], + "followers" => ["type" => "varbinary(383)", "comment" => ""], + "inbox" => ["type" => "varbinary(383)", "not null" => "1", "comment" => ""], + "outbox" => ["type" => "varbinary(383)", "comment" => ""], + "sharedinbox" => ["type" => "varbinary(383)", "comment" => ""], + "featured" => ["type" => "varbinary(383)", "comment" => "Address for the collection of featured posts"], + "featured-tags" => ["type" => "varbinary(383)", "comment" => "Address for the collection of featured tags"], + "manually-approve" => ["type" => "boolean", "comment" => ""], + "discoverable" => ["type" => "boolean", "comment" => "Mastodon extension: true if profile is published in their directory"], + "suspended" => ["type" => "boolean", "comment" => "Mastodon extension: true if profile is suspended"], "posting-restricted" => ["type" => "boolean", "comment" => "lemmy:postingRestrictedToMods"], - "nick" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], - "name" => ["type" => "varchar(255)", "comment" => ""], - "about" => ["type" => "text", "comment" => ""], - "xmpp" => ["type" => "varchar(255)", "comment" => "XMPP address"], - "matrix" => ["type" => "varchar(255)", "comment" => "Matrix address"], - "photo" => ["type" => "varbinary(383)", "comment" => ""], - "header" => ["type" => "varbinary(383)", "comment" => "Header picture"], - "addr" => ["type" => "varchar(255)", "comment" => ""], - "alias" => ["type" => "varbinary(383)", "comment" => ""], - "pubkey" => ["type" => "text", "comment" => ""], - "subscribe" => ["type" => "varbinary(383)", "comment" => ""], - "baseurl" => ["type" => "varbinary(383)", "comment" => "baseurl of the ap contact"], - "gsid" => ["type" => "int unsigned", "foreign" => ["gserver" => "id", "on delete" => "restrict"], "comment" => "Global Server ID"], - "generator" => ["type" => "varchar(255)", "comment" => "Name of the contact's system"], - "following_count" => ["type" => "int unsigned", "default" => 0, "comment" => "Number of following contacts"], - "followers_count" => ["type" => "int unsigned", "default" => 0, "comment" => "Number of followers"], - "statuses_count" => ["type" => "int unsigned", "default" => 0, "comment" => "Number of posts"], - "updated" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""] + "nick" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "name" => ["type" => "varchar(255)", "comment" => ""], + "about" => ["type" => "text", "comment" => ""], + "xmpp" => ["type" => "varchar(255)", "comment" => "XMPP address"], + "matrix" => ["type" => "varchar(255)", "comment" => "Matrix address"], + "photo" => ["type" => "varbinary(383)", "comment" => ""], + "header" => ["type" => "varbinary(383)", "comment" => "Header picture"], + "addr" => ["type" => "varchar(255)", "comment" => ""], + "alias" => ["type" => "varbinary(383)", "comment" => ""], + "pubkey" => ["type" => "text", "comment" => ""], + "subscribe" => ["type" => "varbinary(383)", "comment" => ""], + "baseurl" => ["type" => "varbinary(383)", "comment" => "baseurl of the ap contact"], + "gsid" => ["type" => "int unsigned", "foreign" => ["gserver" => "id", "on delete" => "restrict"], "comment" => "Global Server ID"], + "generator" => ["type" => "varchar(255)", "comment" => "Name of the contact's system"], + "following_count" => ["type" => "int unsigned", "default" => 0, "comment" => "Number of following contacts"], + "followers_count" => ["type" => "int unsigned", "default" => 0, "comment" => "Number of followers"], + "statuses_count" => ["type" => "int unsigned", "default" => 0, "comment" => "Number of posts"], + "updated" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], ], "indexes" => [ - "PRIMARY" => ["url"], - "addr" => ["addr(32)"], - "alias" => ["alias(190)"], - "followers" => ["followers(190)"], - "baseurl" => ["baseurl(190)"], + "PRIMARY" => ["url"], + "addr" => ["addr(32)"], + "alias" => ["alias(190)"], + "followers" => ["followers(190)"], + "baseurl" => ["baseurl(190)"], "sharedinbox" => ["sharedinbox(190)"], - "gsid" => ["gsid"], - "uri-id" => ["UNIQUE", "uri-id"], - ] + "gsid" => ["gsid"], + "uri-id" => ["UNIQUE", "uri-id"], + ], ], "application" => [ "comment" => "OAuth application", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "generated index"], - "client_id" => ["type" => "varchar(64)", "not null" => "1", "comment" => ""], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "generated index"], + "client_id" => ["type" => "varchar(64)", "not null" => "1", "comment" => ""], "client_secret" => ["type" => "varchar(64)", "not null" => "1", "comment" => ""], - "name" => ["type" => "varchar(255)", "not null" => "1", "comment" => ""], - "redirect_uri" => ["type" => "varbinary(383)", "not null" => "1", "comment" => ""], - "website" => ["type" => "varbinary(383)", "comment" => ""], - "scopes" => ["type" => "varchar(511)", "comment" => ""], - "read" => ["type" => "boolean", "comment" => "Read scope"], - "write" => ["type" => "boolean", "comment" => "Write scope"], - "follow" => ["type" => "boolean", "comment" => "Follow scope"], - "push" => ["type" => "boolean", "comment" => "Push scope"], + "name" => ["type" => "varchar(255)", "not null" => "1", "comment" => ""], + "redirect_uri" => ["type" => "varbinary(383)", "not null" => "1", "comment" => ""], + "website" => ["type" => "varbinary(383)", "comment" => ""], + "scopes" => ["type" => "varchar(511)", "comment" => ""], + "read" => ["type" => "boolean", "comment" => "Read scope"], + "write" => ["type" => "boolean", "comment" => "Write scope"], + "follow" => ["type" => "boolean", "comment" => "Follow scope"], + "push" => ["type" => "boolean", "comment" => "Push scope"], ], "indexes" => [ - "PRIMARY" => ["id"], - "client_id" => ["UNIQUE", "client_id"] - ] + "PRIMARY" => ["id"], + "client_id" => ["UNIQUE", "client_id"], + ], ], "application-marker" => [ "comment" => "Timeline marker", - "fields" => [ + "fields" => [ "application-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["application" => "id"], "comment" => ""], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], - "timeline" => ["type" => "varchar(64)", "not null" => "1", "primary" => "1", "comment" => "Marker (home, notifications)"], - "last_read_id" => ["type" => "varbinary(383)", "comment" => "Marker id for the timeline"], - "version" => ["type" => "smallint unsigned", "comment" => "Version number"], - "updated_at" => ["type" => "datetime", "comment" => "creation time"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], + "timeline" => ["type" => "varchar(64)", "not null" => "1", "primary" => "1", "comment" => "Marker (home, notifications)"], + "last_read_id" => ["type" => "varbinary(383)", "comment" => "Marker id for the timeline"], + "version" => ["type" => "smallint unsigned", "comment" => "Version number"], + "updated_at" => ["type" => "datetime", "comment" => "creation time"], ], "indexes" => [ "PRIMARY" => ["application-id", "uid", "timeline"], - "uid_id" => ["uid"], - ] + "uid_id" => ["uid"], + ], ], "application-token" => [ "comment" => "OAuth user token", - "fields" => [ + "fields" => [ "application-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["application" => "id"], "comment" => ""], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], - "code" => ["type" => "varchar(64)", "not null" => "1", "comment" => ""], - "access_token" => ["type" => "varchar(64)", "not null" => "1", "comment" => ""], - "created_at" => ["type" => "datetime", "not null" => "1", "comment" => "creation time"], - "scopes" => ["type" => "varchar(255)", "comment" => ""], - "read" => ["type" => "boolean", "comment" => "Read scope"], - "write" => ["type" => "boolean", "comment" => "Write scope"], - "follow" => ["type" => "boolean", "comment" => "Follow scope"], - "push" => ["type" => "boolean", "comment" => "Push scope"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], + "code" => ["type" => "varchar(64)", "not null" => "1", "comment" => ""], + "access_token" => ["type" => "varchar(64)", "not null" => "1", "comment" => ""], + "created_at" => ["type" => "datetime", "not null" => "1", "comment" => "creation time"], + "scopes" => ["type" => "varchar(255)", "comment" => ""], + "read" => ["type" => "boolean", "comment" => "Read scope"], + "write" => ["type" => "boolean", "comment" => "Write scope"], + "follow" => ["type" => "boolean", "comment" => "Follow scope"], + "push" => ["type" => "boolean", "comment" => "Push scope"], ], "indexes" => [ "PRIMARY" => ["application-id", "uid"], - "uid_id" => ["uid", "application-id"], - ] + "uid_id" => ["uid", "application-id"], + ], ], "attach" => [ "comment" => "file attachments", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "generated index"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], - "hash" => ["type" => "varchar(64)", "not null" => "1", "default" => "", "comment" => "hash"], - "filename" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "filename of original"], - "filetype" => ["type" => "varchar(64)", "not null" => "1", "default" => "", "comment" => "mimetype"], - "filesize" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => "size in bytes"], - "data" => ["type" => "longblob", "not null" => "1", "comment" => "file data"], - "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "creation time"], - "edited" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "last edit time"], - "allow_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed contact.id '<19><78>"], - "allow_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed circles"], - "deny_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied contact.id"], - "deny_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied circles"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "generated index"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], + "hash" => ["type" => "varchar(64)", "not null" => "1", "default" => "", "comment" => "hash"], + "filename" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "filename of original"], + "filetype" => ["type" => "varchar(64)", "not null" => "1", "default" => "", "comment" => "mimetype"], + "filesize" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => "size in bytes"], + "data" => ["type" => "longblob", "not null" => "1", "comment" => "file data"], + "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "creation time"], + "edited" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "last edit time"], + "allow_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed contact.id '<19><78>"], + "allow_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed circles"], + "deny_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied contact.id"], + "deny_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied circles"], "backend-class" => ["type" => "tinytext", "comment" => "Storage backend class"], - "backend-ref" => ["type" => "text", "comment" => "Storage backend data reference"], + "backend-ref" => ["type" => "text", "comment" => "Storage backend data reference"], ], "indexes" => [ "PRIMARY" => ["id"], - "uid" => ["uid"], - ] + "uid" => ["uid"], + ], ], "cache" => [ "comment" => "Stores temporary data", - "fields" => [ - "k" => ["type" => "varbinary(255)", "not null" => "1", "primary" => "1", "comment" => "cache key"], - "v" => ["type" => "mediumtext", "comment" => "cached serialized value"], + "fields" => [ + "k" => ["type" => "varbinary(255)", "not null" => "1", "primary" => "1", "comment" => "cache key"], + "v" => ["type" => "mediumtext", "comment" => "cached serialized value"], "expires" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "datetime of cache expiration"], "updated" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "datetime of cache insertion"], ], "indexes" => [ - "PRIMARY" => ["k"], + "PRIMARY" => ["k"], "k_expires" => ["k", "expires"], - ] + ], ], "channel" => [ "comment" => "User defined Channels", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "foreign" => ["user" => "uid"], "comment" => "User id"], - "label" => ["type" => "varchar(64)", "not null" => "1", "comment" => "Channel label"], - "description" => ["type" => "varchar(64)", "comment" => "Channel description"], - "circle" => ["type" => "int", "comment" => "Circle or channel that this channel is based on"], - "access-key" => ["type" => "varchar(1)", "comment" => "Access key"], - "include-tags" => ["type" => "varchar(1023)", "comment" => "Comma separated list of tags that will be included in the channel"], - "exclude-tags" => ["type" => "varchar(1023)", "comment" => "Comma separated list of tags that aren't allowed in the channel"], - "min-size" => ["type" => "int unsigned", "comment" => "Minimum post size"], - "max-size" => ["type" => "int unsigned", "comment" => "Maximum post size"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "foreign" => ["user" => "uid"], "comment" => "User id"], + "label" => ["type" => "varchar(64)", "not null" => "1", "comment" => "Channel label"], + "description" => ["type" => "varchar(64)", "comment" => "Channel description"], + "circle" => ["type" => "int", "comment" => "Circle or channel that this channel is based on"], + "access-key" => ["type" => "varchar(1)", "comment" => "Access key"], + "include-tags" => ["type" => "varchar(1023)", "comment" => "Comma separated list of tags that will be included in the channel"], + "exclude-tags" => ["type" => "varchar(1023)", "comment" => "Comma separated list of tags that aren't allowed in the channel"], + "min-size" => ["type" => "int unsigned", "comment" => "Minimum post size"], + "max-size" => ["type" => "int unsigned", "comment" => "Maximum post size"], "full-text-search" => ["type" => "varchar(1023)", "comment" => "Full text search pattern, see https://mariadb.com/kb/en/full-text-index-overview/#in-boolean-mode"], - "media-type" => ["type" => "smallint unsigned", "comment" => "Filtered media types"], - "languages" => ["type" => "mediumtext", "comment" => "Desired languages"], - "publish" => ["type" => "boolean", "comment" => "publish channel content"], - "valid" => ["type" => "boolean", "comment" => "Set, when the full-text-search is valid"], + "media-type" => ["type" => "smallint unsigned", "comment" => "Filtered media types"], + "languages" => ["type" => "mediumtext", "comment" => "Desired languages"], + "publish" => ["type" => "boolean", "comment" => "publish channel content"], + "valid" => ["type" => "boolean", "comment" => "Set, when the full-text-search is valid"], ], "indexes" => [ "PRIMARY" => ["id"], - "uid" => ["uid"], - ] + "uid" => ["uid"], + ], ], "config" => [ "comment" => "main configuration storage", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""], "cat" => ["type" => "varbinary(50)", "not null" => "1", "default" => "", "comment" => "The category of the entry"], - "k" => ["type" => "varbinary(50)", "not null" => "1", "default" => "", "comment" => "The key of the entry"], - "v" => ["type" => "mediumtext", "comment" => ""], + "k" => ["type" => "varbinary(50)", "not null" => "1", "default" => "", "comment" => "The key of the entry"], + "v" => ["type" => "mediumtext", "comment" => ""], ], "indexes" => [ "PRIMARY" => ["id"], - "cat_k" => ["UNIQUE", "cat", "k"], - ] + "cat_k" => ["UNIQUE", "cat", "k"], + ], ], "contact-relation" => [ "comment" => "Contact relations", - "fields" => [ - "cid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "primary" => "1", "comment" => "contact the related contact had interacted with"], - "relation-cid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "primary" => "1", "comment" => "related contact who had interacted with the contact"], - "last-interaction" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of the last interaction by relation-cid on cid"], - "follow-updated" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of the last update of the contact relationship"], - "follows" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "if true, relation-cid follows cid"], - "score" => ["type" => "smallint unsigned", "comment" => "score for interactions of cid on relation-cid"], - "relation-score" => ["type" => "smallint unsigned", "comment" => "score for interactions of relation-cid on cid"], - "thread-score" => ["type" => "smallint unsigned", "comment" => "score for interactions of cid on threads of relation-cid"], + "fields" => [ + "cid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "primary" => "1", "comment" => "contact the related contact had interacted with"], + "relation-cid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "primary" => "1", "comment" => "related contact who had interacted with the contact"], + "last-interaction" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of the last interaction by relation-cid on cid"], + "follow-updated" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of the last update of the contact relationship"], + "follows" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "if true, relation-cid follows cid"], + "score" => ["type" => "smallint unsigned", "comment" => "score for interactions of cid on relation-cid"], + "relation-score" => ["type" => "smallint unsigned", "comment" => "score for interactions of relation-cid on cid"], + "thread-score" => ["type" => "smallint unsigned", "comment" => "score for interactions of cid on threads of relation-cid"], "relation-thread-score" => ["type" => "smallint unsigned", "comment" => "score for interactions of relation-cid on threads of cid"], - "post-score" => ["type" => "smallint unsigned", "comment" => "score for the amount of posts from cid that can be seen by relation-cid"], + "post-score" => ["type" => "smallint unsigned", "comment" => "score for the amount of posts from cid that can be seen by relation-cid"], ], "indexes" => [ - "PRIMARY" => ["cid", "relation-cid"], + "PRIMARY" => ["cid", "relation-cid"], "relation-cid" => ["relation-cid"], - ] + ], ], "conv" => [ "comment" => "private messages", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "guid" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => "A unique identifier for this conversation"], - "recips" => ["type" => "text", "comment" => "sender_handle;recipient_handle"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "guid" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => "A unique identifier for this conversation"], + "recips" => ["type" => "text", "comment" => "sender_handle;recipient_handle"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], "creator" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "handle of creator"], "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "creation timestamp"], "updated" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "edited timestamp"], @@ -612,329 +612,329 @@ return [ ], "indexes" => [ "PRIMARY" => ["id"], - "uid" => ["uid"], - ] + "uid" => ["uid"], + ], ], "workerqueue" => [ "comment" => "Background tasks queue entries", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "Auto incremented worker task id"], - "command" => ["type" => "varchar(100)", "comment" => "Task command"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "Auto incremented worker task id"], + "command" => ["type" => "varchar(100)", "comment" => "Task command"], "parameter" => ["type" => "mediumtext", "comment" => "Task parameter"], - "priority" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "Task priority"], - "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Creation date"], - "pid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => "Process id of the worker"], - "executed" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Execution date"], - "next_try" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Next retrial date"], - "retrial" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => "Retrial counter"], - "done" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Marked 1 when the task was done - will be deleted later"], + "priority" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "Task priority"], + "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Creation date"], + "pid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => "Process id of the worker"], + "executed" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Execution date"], + "next_try" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Next retrial date"], + "retrial" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => "Retrial counter"], + "done" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Marked 1 when the task was done - will be deleted later"], ], "indexes" => [ - "PRIMARY" => ["id"], - "command" => ["command"], - "done_command_parameter" => ["done", "command", "parameter(64)"], - "done_executed" => ["done", "executed"], + "PRIMARY" => ["id"], + "command" => ["command"], + "done_command_parameter" => ["done", "command", "parameter(64)"], + "done_executed" => ["done", "executed"], "done_priority_retrial_created" => ["done", "priority", "retrial", "created"], - "done_priority_next_try" => ["done", "priority", "next_try"], - "done_pid_next_try" => ["done", "pid", "next_try"], - "done_pid_retrial" => ["done", "pid", "retrial"], - "done_pid_priority_created" => ["done", "pid", "priority", "created"] - ] + "done_priority_next_try" => ["done", "priority", "next_try"], + "done_pid_next_try" => ["done", "pid", "next_try"], + "done_pid_retrial" => ["done", "pid", "retrial"], + "done_pid_priority_created" => ["done", "pid", "priority", "created"], + ], ], "delayed-post" => [ "comment" => "Posts that are about to be distributed at a later time", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"], - "uri" => ["type" => "varbinary(383)", "comment" => "URI of the post that will be distributed later"], - "uid" => ["type" => "mediumint unsigned", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"], + "uri" => ["type" => "varbinary(383)", "comment" => "URI of the post that will be distributed later"], + "uid" => ["type" => "mediumint unsigned", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], "delayed" => ["type" => "datetime", "comment" => "delay time"], - "wid" => ["type" => "int unsigned", "foreign" => ["workerqueue" => "id"], "comment" => "Workerqueue id"], + "wid" => ["type" => "int unsigned", "foreign" => ["workerqueue" => "id"], "comment" => "Workerqueue id"], ], "indexes" => [ "PRIMARY" => ["id"], "uid_uri" => ["UNIQUE", "uid", "uri(190)"], - "wid" => ["wid"], - ] + "wid" => ["wid"], + ], ], "delivery-queue" => [ "comment" => "Delivery data for posts for the batch processing", - "fields" => [ - "gsid" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["gserver" => "id", "on delete" => "restrict"], "comment" => "Target server"], - "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Delivered post"], + "fields" => [ + "gsid" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["gserver" => "id", "on delete" => "restrict"], "comment" => "Target server"], + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Delivered post"], "created" => ["type" => "datetime", "comment" => ""], "command" => ["type" => "varbinary(32)", "comment" => ""], - "cid" => ["type" => "int unsigned", "foreign" => ["contact" => "id"], "comment" => "Target contact"], - "uid" => ["type" => "mediumint unsigned", "foreign" => ["user" => "uid"], "comment" => "Delivering user"], - "failed" => ["type" => "tinyint", "default" => 0, "comment" => "Number of times the delivery has failed"], + "cid" => ["type" => "int unsigned", "foreign" => ["contact" => "id"], "comment" => "Target contact"], + "uid" => ["type" => "mediumint unsigned", "foreign" => ["user" => "uid"], "comment" => "Delivering user"], + "failed" => ["type" => "tinyint", "default" => 0, "comment" => "Number of times the delivery has failed"], ], "indexes" => [ - "PRIMARY" => ["uri-id", "gsid"], + "PRIMARY" => ["uri-id", "gsid"], "gsid_created" => ["gsid", "created"], - "uid" => ["uid"], - "cid" => ["cid"], - ] + "uid" => ["uid"], + "cid" => ["cid"], + ], ], "diaspora-contact" => [ "comment" => "Diaspora compatible contacts - used in the Diaspora implementation", - "fields" => [ - "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the contact URL"], - "addr" => ["type" => "varchar(255)", "comment" => ""], - "alias" => ["type" => "varchar(255)", "comment" => ""], - "nick" => ["type" => "varchar(255)", "comment" => ""], - "name" => ["type" => "varchar(255)", "comment" => ""], - "given-name" => ["type" => "varchar(255)", "comment" => ""], - "family-name" => ["type" => "varchar(255)", "comment" => ""], - "photo" => ["type" => "varchar(255)", "comment" => ""], - "photo-medium" => ["type" => "varchar(255)", "comment" => ""], - "photo-small" => ["type" => "varchar(255)", "comment" => ""], - "batch" => ["type" => "varchar(255)", "comment" => ""], - "notify" => ["type" => "varchar(255)", "comment" => ""], - "poll" => ["type" => "varchar(255)", "comment" => ""], - "subscribe" => ["type" => "varchar(255)", "comment" => ""], - "searchable" => ["type" => "boolean", "comment" => ""], - "pubkey" => ["type" => "text", "comment" => ""], - "gsid" => ["type" => "int unsigned", "foreign" => ["gserver" => "id", "on delete" => "restrict"], "comment" => "Global Server ID"], - "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], - "updated" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "fields" => [ + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the contact URL"], + "addr" => ["type" => "varchar(255)", "comment" => ""], + "alias" => ["type" => "varchar(255)", "comment" => ""], + "nick" => ["type" => "varchar(255)", "comment" => ""], + "name" => ["type" => "varchar(255)", "comment" => ""], + "given-name" => ["type" => "varchar(255)", "comment" => ""], + "family-name" => ["type" => "varchar(255)", "comment" => ""], + "photo" => ["type" => "varchar(255)", "comment" => ""], + "photo-medium" => ["type" => "varchar(255)", "comment" => ""], + "photo-small" => ["type" => "varchar(255)", "comment" => ""], + "batch" => ["type" => "varchar(255)", "comment" => ""], + "notify" => ["type" => "varchar(255)", "comment" => ""], + "poll" => ["type" => "varchar(255)", "comment" => ""], + "subscribe" => ["type" => "varchar(255)", "comment" => ""], + "searchable" => ["type" => "boolean", "comment" => ""], + "pubkey" => ["type" => "text", "comment" => ""], + "gsid" => ["type" => "int unsigned", "foreign" => ["gserver" => "id", "on delete" => "restrict"], "comment" => "Global Server ID"], + "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "updated" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], "interacting_count" => ["type" => "int unsigned", "default" => 0, "comment" => "Number of contacts this contact interacts with"], - "interacted_count" => ["type" => "int unsigned", "default" => 0, "comment" => "Number of contacts that interacted with this contact"], - "post_count" => ["type" => "int unsigned", "default" => 0, "comment" => "Number of posts and comments"], + "interacted_count" => ["type" => "int unsigned", "default" => 0, "comment" => "Number of contacts that interacted with this contact"], + "post_count" => ["type" => "int unsigned", "default" => 0, "comment" => "Number of posts and comments"], ], "indexes" => [ "PRIMARY" => ["uri-id"], - "addr" => ["UNIQUE", "addr"], - "alias" => ["alias"], - "gsid" => ["gsid"], - ] + "addr" => ["UNIQUE", "addr"], + "alias" => ["alias"], + "gsid" => ["gsid"], + ], ], "diaspora-interaction" => [ "comment" => "Signed Diaspora Interaction", - "fields" => [ - "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], - "interaction" => ["type" => "mediumtext", "comment" => "The Diaspora interaction"] + "fields" => [ + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "interaction" => ["type" => "mediumtext", "comment" => "The Diaspora interaction"], ], "indexes" => [ - "PRIMARY" => ["uri-id"] - ] + "PRIMARY" => ["uri-id"], + ], ], "endpoint" => [ "comment" => "ActivityPub endpoints - used in the ActivityPub implementation", - "fields" => [ - "url" => ["type" => "varbinary(383)", "not null" => "1", "primary" => "1", "comment" => "URL of the contact"], - "type" => ["type" => "varchar(20)", "not null" => "1", "comment" => ""], + "fields" => [ + "url" => ["type" => "varbinary(383)", "not null" => "1", "primary" => "1", "comment" => "URL of the contact"], + "type" => ["type" => "varchar(20)", "not null" => "1", "comment" => ""], "owner-uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the apcontact url"], ], "indexes" => [ - "PRIMARY" => ["url"], + "PRIMARY" => ["url"], "owner-uri-id_type" => ["UNIQUE", "owner-uri-id", "type"], - ] + ], ], "event" => [ "comment" => "Events", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "guid" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => ""], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], - "cid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "comment" => "contact_id (ID of the contact in contact table)"], - "uri" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], - "uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the event uri"], - "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "creation time"], - "edited" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "last edit time"], - "start" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "event start time"], - "finish" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "event end time"], - "summary" => ["type" => "text", "comment" => "short description or title of the event"], - "desc" => ["type" => "text", "comment" => "event description"], - "location" => ["type" => "text", "comment" => "event location"], - "type" => ["type" => "varchar(20)", "not null" => "1", "default" => "", "comment" => "event or birthday"], - "nofinish" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "if event does have no end this is 1"], - "ignore" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "0 or 1"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "guid" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => ""], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], + "cid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "comment" => "contact_id (ID of the contact in contact table)"], + "uri" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the event uri"], + "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "creation time"], + "edited" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "last edit time"], + "start" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "event start time"], + "finish" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "event end time"], + "summary" => ["type" => "text", "comment" => "short description or title of the event"], + "desc" => ["type" => "text", "comment" => "event description"], + "location" => ["type" => "text", "comment" => "event location"], + "type" => ["type" => "varchar(20)", "not null" => "1", "default" => "", "comment" => "event or birthday"], + "nofinish" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "if event does have no end this is 1"], + "ignore" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "0 or 1"], "allow_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed contact.id '<19><78>'"], "allow_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed circles"], - "deny_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied contact.id"], - "deny_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied circles"], + "deny_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied contact.id"], + "deny_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied circles"], ], "indexes" => [ - "PRIMARY" => ["id"], + "PRIMARY" => ["id"], "uid_start" => ["uid", "start"], - "cid" => ["cid"], - "uri-id" => ["uri-id"], - ] + "cid" => ["cid"], + "uri-id" => ["uri-id"], + ], ], "fetch-entry" => [ "comment" => "", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "url" => ["type" => "varbinary(383)", "comment" => "url that awaiting to be fetched"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "url" => ["type" => "varbinary(383)", "comment" => "url that awaiting to be fetched"], "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Creation date of the fetch request"], - "wid" => ["type" => "int unsigned", "foreign" => ["workerqueue" => "id"], "comment" => "Workerqueue id"], + "wid" => ["type" => "int unsigned", "foreign" => ["workerqueue" => "id"], "comment" => "Workerqueue id"], ], "indexes" => [ "PRIMARY" => ["id"], - "url" => ["UNIQUE", "url"], + "url" => ["UNIQUE", "url"], "created" => ["created"], - "wid" => ["wid"], - ] + "wid" => ["wid"], + ], ], "fsuggest" => [ "comment" => "friend suggestion stuff", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "User id"], - "cid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "comment" => ""], - "name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], - "url" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "User id"], + "cid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "comment" => ""], + "name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "url" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], "request" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], - "photo" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], - "note" => ["type" => "text", "comment" => ""], + "photo" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "note" => ["type" => "text", "comment" => ""], "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], ], "indexes" => [ "PRIMARY" => ["id"], - "cid" => ["cid"], - "uid" => ["uid"], - ] + "cid" => ["cid"], + "uid" => ["uid"], + ], ], "group" => [ "comment" => "privacy circles, circle info", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], "visible" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "1 indicates the member list is not private"], "deleted" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "1 indicates the circle has been deleted"], - "cid" => ["type" => "int unsigned", "foreign" => ["contact" => "id"], "comment" => "Contact id of group. When this field is filled then the members are synced automatically."], - "name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "human readable name of circle"], + "cid" => ["type" => "int unsigned", "foreign" => ["contact" => "id"], "comment" => "Contact id of group. When this field is filled then the members are synced automatically."], + "name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "human readable name of circle"], ], "indexes" => [ "PRIMARY" => ["id"], - "uid" => ["uid"], - "cid" => ["cid"], - ] + "uid" => ["uid"], + "cid" => ["cid"], + ], ], "group_member" => [ "comment" => "privacy circles, member info", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "gid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["group" => "id"], "comment" => "group.id of the associated circle"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "gid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["group" => "id"], "comment" => "group.id of the associated circle"], "contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "comment" => "contact.id of the member assigned to the associated circle"], ], "indexes" => [ - "PRIMARY" => ["id"], - "contactid" => ["contact-id"], + "PRIMARY" => ["id"], + "contactid" => ["contact-id"], "gid_contactid" => ["UNIQUE", "gid", "contact-id"], - ] + ], ], "gserver-tag" => [ "comment" => "Tags that the server has subscribed", - "fields" => [ + "fields" => [ "gserver-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["gserver" => "id"], "primary" => "1", "comment" => "The id of the gserver"], - "tag" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "primary" => "1", "comment" => "Tag that the server has subscribed"], + "tag" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "primary" => "1", "comment" => "Tag that the server has subscribed"], ], "indexes" => [ "PRIMARY" => ["gserver-id", "tag"], - "tag" => ["tag"], - ] + "tag" => ["tag"], + ], ], "hook" => [ "comment" => "addon hook registry", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "hook" => ["type" => "varbinary(100)", "not null" => "1", "default" => "", "comment" => "name of hook"], - "file" => ["type" => "varbinary(200)", "not null" => "1", "default" => "", "comment" => "relative filename of hook handler"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "hook" => ["type" => "varbinary(100)", "not null" => "1", "default" => "", "comment" => "name of hook"], + "file" => ["type" => "varbinary(200)", "not null" => "1", "default" => "", "comment" => "relative filename of hook handler"], "function" => ["type" => "varbinary(200)", "not null" => "1", "default" => "", "comment" => "function name of hook handler"], "priority" => ["type" => "smallint unsigned", "not null" => "1", "default" => "0", "comment" => "not yet implemented - can be used to sort conflicts in hook handling by calling handlers in priority order"], ], "indexes" => [ - "PRIMARY" => ["id"], - "priority" => ["priority"], + "PRIMARY" => ["id"], + "priority" => ["priority"], "hook_file_function" => ["UNIQUE", "hook", "file", "function"], - ] + ], ], "inbox-entry" => [ "comment" => "Incoming activity", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "activity-id" => ["type" => "varbinary(383)", "comment" => "id of the incoming activity"], - "object-id" => ["type" => "varbinary(383)", "comment" => ""], - "in-reply-to-id" => ["type" => "varbinary(383)", "comment" => ""], - "context" => ["type" => "varbinary(383)", "comment" => ""], - "conversation" => ["type" => "varbinary(383)", "comment" => ""], - "type" => ["type" => "varchar(64)", "comment" => "Type of the activity"], - "object-type" => ["type" => "varchar(64)", "comment" => "Type of the object activity"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "activity-id" => ["type" => "varbinary(383)", "comment" => "id of the incoming activity"], + "object-id" => ["type" => "varbinary(383)", "comment" => ""], + "in-reply-to-id" => ["type" => "varbinary(383)", "comment" => ""], + "context" => ["type" => "varbinary(383)", "comment" => ""], + "conversation" => ["type" => "varbinary(383)", "comment" => ""], + "type" => ["type" => "varchar(64)", "comment" => "Type of the activity"], + "object-type" => ["type" => "varchar(64)", "comment" => "Type of the object activity"], "object-object-type" => ["type" => "varchar(64)", "comment" => "Type of the object's object activity"], - "received" => ["type" => "datetime", "comment" => "Receiving date"], - "activity" => ["type" => "mediumtext", "comment" => "The JSON activity"], - "signer" => ["type" => "varchar(255)", "comment" => ""], - "push" => ["type" => "boolean", "comment" => "Is the entry pushed or have pulled it?"], - "trust" => ["type" => "boolean", "comment" => "Do we trust this entry?"], - "wid" => ["type" => "int unsigned", "foreign" => ["workerqueue" => "id"], "comment" => "Workerqueue id"], - "retrial" => ["type" => "tinyint unsigned", "default" => "0", "comment" => "Retrial counter"], + "received" => ["type" => "datetime", "comment" => "Receiving date"], + "activity" => ["type" => "mediumtext", "comment" => "The JSON activity"], + "signer" => ["type" => "varchar(255)", "comment" => ""], + "push" => ["type" => "boolean", "comment" => "Is the entry pushed or have pulled it?"], + "trust" => ["type" => "boolean", "comment" => "Do we trust this entry?"], + "wid" => ["type" => "int unsigned", "foreign" => ["workerqueue" => "id"], "comment" => "Workerqueue id"], + "retrial" => ["type" => "tinyint unsigned", "default" => "0", "comment" => "Retrial counter"], ], "indexes" => [ - "PRIMARY" => ["id"], + "PRIMARY" => ["id"], "activity-id" => ["UNIQUE", "activity-id"], - "object-id" => ["object-id"], - "received" => ["received"], - "wid" => ["wid"], - ] + "object-id" => ["object-id"], + "received" => ["received"], + "wid" => ["wid"], + ], ], "inbox-entry-receiver" => [ "comment" => "Receiver for the incoming activity", - "fields" => [ + "fields" => [ "queue-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["inbox-entry" => "id"], "comment" => ""], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "User id"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "User id"], ], "indexes" => [ "PRIMARY" => ["queue-id", "uid"], - "uid" => ["uid"], - ] + "uid" => ["uid"], + ], ], "inbox-status" => [ "comment" => "Status of ActivityPub inboxes", - "fields" => [ - "url" => ["type" => "varbinary(383)", "not null" => "1", "primary" => "1", "comment" => "URL of the inbox"], - "uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Item-uri id of inbox url"], - "gsid" => ["type" => "int unsigned", "foreign" => ["gserver" => "id", "on delete" => "restrict"], "comment" => "ID of the related server"], - "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Creation date of this entry"], - "success" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of the last successful delivery"], - "failure" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of the last failed delivery"], + "fields" => [ + "url" => ["type" => "varbinary(383)", "not null" => "1", "primary" => "1", "comment" => "URL of the inbox"], + "uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Item-uri id of inbox url"], + "gsid" => ["type" => "int unsigned", "foreign" => ["gserver" => "id", "on delete" => "restrict"], "comment" => "ID of the related server"], + "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Creation date of this entry"], + "success" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of the last successful delivery"], + "failure" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of the last failed delivery"], "previous" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Previous delivery date"], - "archive" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Is the inbox archived?"], - "shared" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Is it a shared inbox?"] + "archive" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Is the inbox archived?"], + "shared" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Is it a shared inbox?"], ], "indexes" => [ "PRIMARY" => ["url"], - "uri-id" => ["uri-id"], - "gsid" => ["gsid"], - ] + "uri-id" => ["uri-id"], + "gsid" => ["gsid"], + ], ], "intro" => [ "comment" => "", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "User id"], - "fid" => ["type" => "int unsigned", "comment" => "deprecated"], - "contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "comment" => ""], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "User id"], + "fid" => ["type" => "int unsigned", "comment" => "deprecated"], + "contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "comment" => ""], "suggest-cid" => ["type" => "int unsigned", "foreign" => ["contact" => "id"], "comment" => "Suggested contact"], - "knowyou" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "duplex" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "deprecated"], - "note" => ["type" => "text", "comment" => ""], - "hash" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => ""], - "datetime" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], - "blocked" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "deprecated"], - "ignore" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "knowyou" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "duplex" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "deprecated"], + "note" => ["type" => "text", "comment" => ""], + "hash" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => ""], + "datetime" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "blocked" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "deprecated"], + "ignore" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], ], "indexes" => [ - "PRIMARY" => ["id"], - "contact-id" => ["contact-id"], + "PRIMARY" => ["id"], + "contact-id" => ["contact-id"], "suggest-cid" => ["suggest-cid"], - "uid" => ["uid"], - ] + "uid" => ["uid"], + ], ], "key-value" => [ "comment" => "A key value storage", - "fields" => [ - "k" => ["type" => "varbinary(50)", "not null" => "1", "primary" => "1", "comment" => ""], - "v" => ["type" => "mediumtext", "comment" => ""], + "fields" => [ + "k" => ["type" => "varbinary(50)", "not null" => "1", "primary" => "1", "comment" => ""], + "v" => ["type" => "mediumtext", "comment" => ""], "updated_at" => ["type" => "int unsigned", "not null" => "1", "comment" => "timestamp of the last update"], ], "indexes" => [ @@ -943,1117 +943,1117 @@ return [ ], "locks" => [ "comment" => "", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "name" => ["type" => "varchar(128)", "not null" => "1", "default" => "", "comment" => ""], - "locked" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "pid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => "Process ID"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "name" => ["type" => "varchar(128)", "not null" => "1", "default" => "", "comment" => ""], + "locked" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "pid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => "Process ID"], "expires" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "datetime of cache expiration"], ], "indexes" => [ - "PRIMARY" => ["id"], - "name_expires" => ["name", "expires"] - ] + "PRIMARY" => ["id"], + "name_expires" => ["name", "expires"], + ], ], "mail" => [ "comment" => "private messages", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], - "guid" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => "A unique identifier for this private message"], - "from-name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "name of the sender"], - "from-photo" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => "contact photo link of the sender"], - "from-url" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => "profile link of the sender"], - "contact-id" => ["type" => "varbinary(255)", "relation" => ["contact" => "id"], "comment" => "contact.id"], - "author-id" => ["type" => "int unsigned", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the author of the mail"], - "convid" => ["type" => "int unsigned", "relation" => ["conv" => "id"], "comment" => "conv.id"], - "title" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], - "body" => ["type" => "mediumtext", "comment" => ""], - "seen" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "if message visited it is 1"], - "reply" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "replied" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "unknown" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "if sender not in the contact table this is 1"], - "uri" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], - "uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Item-uri id of the related mail"], - "parent-uri" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], + "guid" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => "A unique identifier for this private message"], + "from-name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "name of the sender"], + "from-photo" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => "contact photo link of the sender"], + "from-url" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => "profile link of the sender"], + "contact-id" => ["type" => "varbinary(255)", "relation" => ["contact" => "id"], "comment" => "contact.id"], + "author-id" => ["type" => "int unsigned", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the author of the mail"], + "convid" => ["type" => "int unsigned", "relation" => ["conv" => "id"], "comment" => "conv.id"], + "title" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "body" => ["type" => "mediumtext", "comment" => ""], + "seen" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "if message visited it is 1"], + "reply" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "replied" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "unknown" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "if sender not in the contact table this is 1"], + "uri" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Item-uri id of the related mail"], + "parent-uri" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], "parent-uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Item-uri id of the parent of the related mail"], - "thr-parent" => ["type" => "varbinary(383)", "comment" => ""], + "thr-parent" => ["type" => "varbinary(383)", "comment" => ""], "thr-parent-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table that contains the thread parent uri"], - "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "creation time of the private message"], + "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "creation time of the private message"], ], "indexes" => [ - "PRIMARY" => ["id"], - "uid_seen" => ["uid", "seen"], - "convid" => ["convid"], - "uri" => ["uri(64)"], - "parent-uri" => ["parent-uri(64)"], - "contactid" => ["contact-id(32)"], - "author-id" => ["author-id"], - "uri-id" => ["uri-id"], + "PRIMARY" => ["id"], + "uid_seen" => ["uid", "seen"], + "convid" => ["convid"], + "uri" => ["uri(64)"], + "parent-uri" => ["parent-uri(64)"], + "contactid" => ["contact-id(32)"], + "author-id" => ["author-id"], + "uri-id" => ["uri-id"], "parent-uri-id" => ["parent-uri-id"], "thr-parent-id" => ["thr-parent-id"], - ] + ], ], "mailacct" => [ "comment" => "Mail account data for fetching mails", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "User id"], - "server" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], - "port" => ["type" => "smallint unsigned", "not null" => "1", "default" => "0", "comment" => ""], - "ssltype" => ["type" => "varchar(16)", "not null" => "1", "default" => "", "comment" => ""], - "mailbox" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], - "user" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], - "pass" => ["type" => "text", "comment" => ""], - "reply_to" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], - "action" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "User id"], + "server" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "port" => ["type" => "smallint unsigned", "not null" => "1", "default" => "0", "comment" => ""], + "ssltype" => ["type" => "varchar(16)", "not null" => "1", "default" => "", "comment" => ""], + "mailbox" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "user" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "pass" => ["type" => "text", "comment" => ""], + "reply_to" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "action" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""], "movetofolder" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], - "pubmail" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "last_check" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "pubmail" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "last_check" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], ], "indexes" => [ "PRIMARY" => ["id"], - "uid" => ["uid"], - ] + "uid" => ["uid"], + ], ], "manage" => [ "comment" => "table of accounts that can manage each other", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "User id"], "mid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "User id"], ], "indexes" => [ "PRIMARY" => ["id"], "uid_mid" => ["UNIQUE", "uid", "mid"], - "mid" => ["mid"], - ] + "mid" => ["mid"], + ], ], "notification" => [ "comment" => "notifications", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "uid" => ["type" => "mediumint unsigned", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], - "vid" => ["type" => "smallint unsigned", "foreign" => ["verb" => "id", "on delete" => "restrict"], "comment" => "Id of the verb table entry that contains the activity verbs"], - "type" => ["type" => "smallint unsigned", "comment" => ""], - "actor-id" => ["type" => "int unsigned", "foreign" => ["contact" => "id"], "comment" => "Link to the contact table with uid=0 of the actor that caused the notification"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "uid" => ["type" => "mediumint unsigned", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], + "vid" => ["type" => "smallint unsigned", "foreign" => ["verb" => "id", "on delete" => "restrict"], "comment" => "Id of the verb table entry that contains the activity verbs"], + "type" => ["type" => "smallint unsigned", "comment" => ""], + "actor-id" => ["type" => "int unsigned", "foreign" => ["contact" => "id"], "comment" => "Link to the contact table with uid=0 of the actor that caused the notification"], "target-uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Item-uri id of the related post"], "parent-uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Item-uri id of the parent of the related post"], - "created" => ["type" => "datetime", "comment" => ""], - "seen" => ["type" => "boolean", "default" => "0", "comment" => "Seen on the desktop"], - "dismissed" => ["type" => "boolean", "default" => "0", "comment" => "Dismissed via the API"], + "created" => ["type" => "datetime", "comment" => ""], + "seen" => ["type" => "boolean", "default" => "0", "comment" => "Seen on the desktop"], + "dismissed" => ["type" => "boolean", "default" => "0", "comment" => "Dismissed via the API"], ], "indexes" => [ - "PRIMARY" => ["id"], + "PRIMARY" => ["id"], "uid_vid_type_actor-id_target-uri-id" => ["UNIQUE", "uid", "vid", "type", "actor-id", "target-uri-id"], - "vid" => ["vid"], - "actor-id" => ["actor-id"], - "target-uri-id" => ["target-uri-id"], - "parent-uri-id" => ["parent-uri-id"], - "seen_uid" => ["seen", "uid"], - "uid_type_parent-uri-id_actor-id" => ["uid", "type", "parent-uri-id", "actor-id"], - ] + "vid" => ["vid"], + "actor-id" => ["actor-id"], + "target-uri-id" => ["target-uri-id"], + "parent-uri-id" => ["parent-uri-id"], + "seen_uid" => ["seen", "uid"], + "uid_type_parent-uri-id_actor-id" => ["uid", "type", "parent-uri-id", "actor-id"], + ], ], "notify" => [ "comment" => "[Deprecated] User notifications", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "type" => ["type" => "smallint unsigned", "not null" => "1", "default" => "0", "comment" => ""], - "name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], - "url" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], - "photo" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], - "date" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], - "msg" => ["type" => "mediumtext", "comment" => ""], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], - "link" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], - "iid" => ["type" => "int unsigned", "comment" => ""], - "parent" => ["type" => "int unsigned", "comment" => ""], - "uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Item-uri id of the related post"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "type" => ["type" => "smallint unsigned", "not null" => "1", "default" => "0", "comment" => ""], + "name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "url" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "photo" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "date" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "msg" => ["type" => "mediumtext", "comment" => ""], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], + "link" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "iid" => ["type" => "int unsigned", "comment" => ""], + "parent" => ["type" => "int unsigned", "comment" => ""], + "uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Item-uri id of the related post"], "parent-uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Item-uri id of the parent of the related post"], - "seen" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "verb" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => ""], - "otype" => ["type" => "varchar(10)", "not null" => "1", "default" => "", "comment" => ""], - "name_cache" => ["type" => "tinytext", "comment" => "Cached bbcode parsing of name"], - "msg_cache" => ["type" => "mediumtext", "comment" => "Cached bbcode parsing of msg"] + "seen" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "verb" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => ""], + "otype" => ["type" => "varchar(10)", "not null" => "1", "default" => "", "comment" => ""], + "name_cache" => ["type" => "tinytext", "comment" => "Cached bbcode parsing of name"], + "msg_cache" => ["type" => "mediumtext", "comment" => "Cached bbcode parsing of msg"], ], "indexes" => [ - "PRIMARY" => ["id"], + "PRIMARY" => ["id"], "seen_uid_date" => ["seen", "uid", "date"], - "uid_date" => ["uid", "date"], + "uid_date" => ["uid", "date"], "uid_type_link" => ["uid", "type", "link(190)"], - "uri-id" => ["uri-id"], + "uri-id" => ["uri-id"], "parent-uri-id" => ["parent-uri-id"], - ] + ], ], "notify-threads" => [ "comment" => "", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "notify-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["notify" => "id"], "comment" => ""], - "master-parent-item" => ["type" => "int unsigned", "comment" => "Deprecated"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "notify-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["notify" => "id"], "comment" => ""], + "master-parent-item" => ["type" => "int unsigned", "comment" => "Deprecated"], "master-parent-uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Item-uri id of the parent of the related post"], - "parent-item" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => ""], - "receiver-uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "User id"], + "parent-item" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => ""], + "receiver-uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "User id"], ], "indexes" => [ - "PRIMARY" => ["id"], + "PRIMARY" => ["id"], "master-parent-uri-id" => ["master-parent-uri-id"], - "receiver-uid" => ["receiver-uid"], - "notify-id" => ["notify-id"], - ] + "receiver-uid" => ["receiver-uid"], + "notify-id" => ["notify-id"], + ], ], "openwebauth-token" => [ "comment" => "Store OpenWebAuth token to verify contacts", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "User id - currently unused"], - "type" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => "Verify type"], - "token" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "A generated token"], - "meta" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "User id - currently unused"], + "type" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => "Verify type"], + "token" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "A generated token"], + "meta" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "datetime of creation"], ], "indexes" => [ "PRIMARY" => ["id"], - "uid" => ["uid"], - ] + "uid" => ["uid"], + ], ], "parsed_url" => [ "comment" => "cache for 'parse_url' queries", - "fields" => [ + "fields" => [ "url_hash" => ["type" => "binary(64)", "not null" => "1", "primary" => "1", "comment" => "page url hash"], "guessing" => ["type" => "boolean", "not null" => "1", "default" => "0", "primary" => "1", "comment" => "is the 'guessing' mode active?"], - "oembed" => ["type" => "boolean", "not null" => "1", "default" => "0", "primary" => "1", "comment" => "is the data the result of oembed? - Obsolete field."], - "url" => ["type" => "text", "not null" => "1", "comment" => "page url"], - "content" => ["type" => "mediumtext", "comment" => "page data"], - "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "datetime of creation"], - "expires" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "datetime of expiration"], + "oembed" => ["type" => "boolean", "not null" => "1", "default" => "0", "primary" => "1", "comment" => "is the data the result of oembed? - Obsolete field."], + "url" => ["type" => "text", "not null" => "1", "comment" => "page url"], + "content" => ["type" => "mediumtext", "comment" => "page data"], + "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "datetime of creation"], + "expires" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "datetime of expiration"], ], "indexes" => [ "PRIMARY" => ["url_hash", "guessing", "oembed"], "created" => ["created"], "expires" => ["expires"], - ] + ], ], "pconfig" => [ "comment" => "personal (per user) configuration storage", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "Primary key"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "Primary key"], "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "User id"], "cat" => ["type" => "varchar(50)", "not null" => "1", "default" => "", "comment" => "Category"], - "k" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => "Key"], - "v" => ["type" => "mediumtext", "comment" => "Value"], + "k" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => "Key"], + "v" => ["type" => "mediumtext", "comment" => "Value"], ], "indexes" => [ - "PRIMARY" => ["id"], + "PRIMARY" => ["id"], "uid_cat_k" => ["UNIQUE", "uid", "cat", "k"], - ] + ], ], "photo" => [ "comment" => "photo storage", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid", "on delete" => "restrict"], "comment" => "Owner User id"], - "contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "contact.id"], - "guid" => ["type" => "char(16)", "not null" => "1", "default" => "", "comment" => "A unique identifier for this photo"], - "resource-id" => ["type" => "char(32)", "not null" => "1", "default" => "", "comment" => ""], - "hash" => ["type" => "char(32)", "comment" => "hash value of the photo"], - "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "creation date"], - "edited" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "last edited date"], - "title" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], - "desc" => ["type" => "text", "comment" => ""], - "album" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "The name of the album to which the photo belongs"], - "photo-type" => ["type" => "tinyint unsigned", "comment" => "User avatar, user banner, contact avatar, contact banner or default"], - "filename" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], - "type" => ["type" => "varchar(30)", "not null" => "1", "default" => "image/jpeg"], - "height" => ["type" => "smallint unsigned", "not null" => "1", "default" => "0", "comment" => ""], - "width" => ["type" => "smallint unsigned", "not null" => "1", "default" => "0", "comment" => ""], - "datasize" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => ""], - "blurhash" => ["type" => "varbinary(255)", "comment" => "BlurHash representation of the photo"], - "data" => ["type" => "mediumblob", "not null" => "1", "comment" => ""], - "scale" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""], - "profile" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "allow_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed contact.id '<19><78>'"], - "allow_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed circles"], - "deny_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied contact.id"], - "deny_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied circles"], - "accessible" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Make photo publicly accessible, ignoring permissions"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid", "on delete" => "restrict"], "comment" => "Owner User id"], + "contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "contact.id"], + "guid" => ["type" => "char(16)", "not null" => "1", "default" => "", "comment" => "A unique identifier for this photo"], + "resource-id" => ["type" => "char(32)", "not null" => "1", "default" => "", "comment" => ""], + "hash" => ["type" => "char(32)", "comment" => "hash value of the photo"], + "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "creation date"], + "edited" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "last edited date"], + "title" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "desc" => ["type" => "text", "comment" => ""], + "album" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "The name of the album to which the photo belongs"], + "photo-type" => ["type" => "tinyint unsigned", "comment" => "User avatar, user banner, contact avatar, contact banner or default"], + "filename" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "type" => ["type" => "varchar(30)", "not null" => "1", "default" => "image/jpeg"], + "height" => ["type" => "smallint unsigned", "not null" => "1", "default" => "0", "comment" => ""], + "width" => ["type" => "smallint unsigned", "not null" => "1", "default" => "0", "comment" => ""], + "datasize" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => ""], + "blurhash" => ["type" => "varbinary(255)", "comment" => "BlurHash representation of the photo"], + "data" => ["type" => "mediumblob", "not null" => "1", "comment" => ""], + "scale" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""], + "profile" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "allow_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed contact.id '<19><78>'"], + "allow_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed circles"], + "deny_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied contact.id"], + "deny_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied circles"], + "accessible" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Make photo publicly accessible, ignoring permissions"], "backend-class" => ["type" => "tinytext", "comment" => "Storage backend class"], - "backend-ref" => ["type" => "text", "comment" => "Storage backend data reference"], - "updated" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""] + "backend-ref" => ["type" => "text", "comment" => "Storage backend data reference"], + "updated" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], ], "indexes" => [ - "PRIMARY" => ["id"], - "contactid" => ["contact-id"], - "uid_contactid" => ["uid", "contact-id"], - "uid_profile" => ["uid", "profile"], - "uid_album_scale_created" => ["uid", "album(32)", "scale", "created"], + "PRIMARY" => ["id"], + "contactid" => ["contact-id"], + "uid_contactid" => ["uid", "contact-id"], + "uid_profile" => ["uid", "profile"], + "uid_album_scale_created" => ["uid", "album(32)", "scale", "created"], "uid_album_resource-id_created" => ["uid", "album(32)", "resource-id", "created"], - "resource-id" => ["resource-id"], - "uid_photo-type" => ["uid", "photo-type"], - ] + "resource-id" => ["resource-id"], + "uid_photo-type" => ["uid", "photo-type"], + ], ], "post" => [ "comment" => "Structure for all posts", - "fields" => [ - "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "fields" => [ + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], "parent-uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table that contains the parent uri"], "thr-parent-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table that contains the thread parent uri"], - "external-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the external uri"], - "replies-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the endpoint for the replies collection"], - "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Creation timestamp."], - "edited" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of last edit (default is created)"], - "received" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "datetime"], - "gravity" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""], - "network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => "Network from where the item comes from"], - "owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the owner of this item"], - "author-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the author of this item"], - "causer-id" => ["type" => "int unsigned", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the contact that caused the item creation"], - "post-type" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "Post type (personal note, image, article, ...)"], - "vid" => ["type" => "smallint unsigned", "foreign" => ["verb" => "id", "on delete" => "restrict"], "comment" => "Id of the verb table entry that contains the activity verbs"], - "private" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "0=public, 1=private, 2=unlisted"], - "global" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "visible" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "deleted" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "item has been marked for deletion"] + "external-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the external uri"], + "replies-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the endpoint for the replies collection"], + "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Creation timestamp."], + "edited" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of last edit (default is created)"], + "received" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "datetime"], + "gravity" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""], + "network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => "Network from where the item comes from"], + "owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the owner of this item"], + "author-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the author of this item"], + "causer-id" => ["type" => "int unsigned", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the contact that caused the item creation"], + "post-type" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "Post type (personal note, image, article, ...)"], + "vid" => ["type" => "smallint unsigned", "foreign" => ["verb" => "id", "on delete" => "restrict"], "comment" => "Id of the verb table entry that contains the activity verbs"], + "private" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "0=public, 1=private, 2=unlisted"], + "global" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "visible" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "deleted" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "item has been marked for deletion"], ], "indexes" => [ - "PRIMARY" => ["uri-id"], + "PRIMARY" => ["uri-id"], "parent-uri-id" => ["parent-uri-id"], "thr-parent-id" => ["thr-parent-id"], - "external-id" => ["external-id"], - "replies-id" => ["replies-id"], - "owner-id" => ["owner-id"], - "author-id" => ["author-id"], - "causer-id" => ["causer-id"], - "vid" => ["vid"], - ] + "external-id" => ["external-id"], + "replies-id" => ["replies-id"], + "owner-id" => ["owner-id"], + "author-id" => ["author-id"], + "causer-id" => ["causer-id"], + "vid" => ["vid"], + ], ], "post-activity" => [ "comment" => "Original remote activity", - "fields" => [ - "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "fields" => [ + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], "activity" => ["type" => "mediumtext", "comment" => "Original activity"], "received" => ["type" => "datetime", "comment" => ""], ], "indexes" => [ "PRIMARY" => ["uri-id"], - ] + ], ], "post-category" => [ "comment" => "post relation to categories", - "fields" => [ + "fields" => [ "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "User id"], - "type" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "primary" => "1", "comment" => ""], - "tid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "primary" => "1", "foreign" => ["tag" => "id", "on delete" => "restrict"], "comment" => ""], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "User id"], + "type" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "primary" => "1", "comment" => ""], + "tid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "primary" => "1", "foreign" => ["tag" => "id", "on delete" => "restrict"], "comment" => ""], ], "indexes" => [ - "PRIMARY" => ["uri-id", "uid", "type", "tid"], - "tid" => ["tid"], + "PRIMARY" => ["uri-id", "uid", "type", "tid"], + "tid" => ["tid"], "uid_uri-id" => ["uid", "uri-id"], - ] + ], ], "post-counts" => [ "comment" => "Original remote activity", - "fields" => [ - "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], - "vid" => ["type" => "smallint unsigned", "not null" => "1", "primary" => "1", "foreign" => ["verb" => "id", "on delete" => "restrict"], "comment" => "Id of the verb table entry that contains the activity verbs"], - "reaction" => ["type" => "varchar(4)", "not null" => "1", "primary" => "1", "comment" => "Emoji Reaction"], + "fields" => [ + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "vid" => ["type" => "smallint unsigned", "not null" => "1", "primary" => "1", "foreign" => ["verb" => "id", "on delete" => "restrict"], "comment" => "Id of the verb table entry that contains the activity verbs"], + "reaction" => ["type" => "varchar(4)", "not null" => "1", "primary" => "1", "comment" => "Emoji Reaction"], "parent-uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table that contains the parent uri"], - "count" => ["type" => "int unsigned", "default" => 0, "comment" => "Number of activities"], + "count" => ["type" => "int unsigned", "default" => 0, "comment" => "Number of activities"], ], "indexes" => [ - "PRIMARY" => ["uri-id", "vid", "reaction"], - "vid" => ["vid"], + "PRIMARY" => ["uri-id", "vid", "reaction"], + "vid" => ["vid"], "parent-uri-id" => ["parent-uri-id"], - ] + ], ], "post-collection" => [ "comment" => "Collection of posts", - "fields" => [ - "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], - "type" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "primary" => "1", "comment" => "0 - Featured"], + "fields" => [ + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "type" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "primary" => "1", "comment" => "0 - Featured"], "author-id" => ["type" => "int unsigned", "foreign" => ["contact" => "id"], "comment" => "Author of the featured post"], ], "indexes" => [ - "PRIMARY" => ["uri-id", "type"], - "type" => ["type"], + "PRIMARY" => ["uri-id", "type"], + "type" => ["type"], "author-id" => ["author-id"], - ] + ], ], "post-content" => [ "comment" => "Content for all posts", - "fields" => [ - "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], - "title" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "item title"], + "fields" => [ + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "title" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "item title"], "content-warning" => ["type" => "varchar(500)", "not null" => "1", "default" => "", "comment" => ""], - "body" => ["type" => "mediumtext", "comment" => "item body content"], - "raw-body" => ["type" => "mediumtext", "comment" => "Body without embedded media links"], - "quote-uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table that contains the quoted uri"], - "location" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "text location where this item originated"], - "coord" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "longitude/latitude pair representing location where this item originated"], - "language" => ["type" => "text", "comment" => "Language information about this post"], - "sensitive" => ["type" => "boolean", "comment" => "If true, this post contains sensitive content"], - "app" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "application which generated this item"], - "rendered-hash" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => ""], - "rendered-html" => ["type" => "mediumtext", "comment" => "item.body converted to html"], - "object-type" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => "ActivityStreams object type"], - "object" => ["type" => "text", "comment" => "JSON encoded object structure unless it is an implied object (normal post)"], - "target-type" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => "ActivityStreams target type if applicable (URI)"], - "target" => ["type" => "text", "comment" => "JSON encoded target structure if used"], - "resource-id" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => "Used to link other tables to items, it identifies the linked resource (e.g. photo) and if set must also set resource_type"], - "plink" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => "permalink or URL to a displayable copy of the message at its source"] + "body" => ["type" => "mediumtext", "comment" => "item body content"], + "raw-body" => ["type" => "mediumtext", "comment" => "Body without embedded media links"], + "quote-uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table that contains the quoted uri"], + "location" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "text location where this item originated"], + "coord" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "longitude/latitude pair representing location where this item originated"], + "language" => ["type" => "text", "comment" => "Language information about this post"], + "sensitive" => ["type" => "boolean", "comment" => "If true, this post contains sensitive content"], + "app" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "application which generated this item"], + "rendered-hash" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => ""], + "rendered-html" => ["type" => "mediumtext", "comment" => "item.body converted to html"], + "object-type" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => "ActivityStreams object type"], + "object" => ["type" => "text", "comment" => "JSON encoded object structure unless it is an implied object (normal post)"], + "target-type" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => "ActivityStreams target type if applicable (URI)"], + "target" => ["type" => "text", "comment" => "JSON encoded target structure if used"], + "resource-id" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => "Used to link other tables to items, it identifies the linked resource (e.g. photo) and if set must also set resource_type"], + "plink" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => "permalink or URL to a displayable copy of the message at its source"], ], "indexes" => [ - "PRIMARY" => ["uri-id"], - "plink" => ["plink(191)"], - "resource-id" => ["resource-id"], + "PRIMARY" => ["uri-id"], + "plink" => ["plink(191)"], + "resource-id" => ["resource-id"], "quote-uri-id" => ["quote-uri-id"], - ] + ], ], "post-delivery" => [ "comment" => "Delivery data for posts for the batch processing", - "fields" => [ - "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], - "inbox-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Item-uri id of inbox url"], - "uid" => ["type" => "mediumint unsigned", "foreign" => ["user" => "uid"], "comment" => "Delivering user"], - "created" => ["type" => "datetime", "default" => DBA::NULL_DATETIME, "comment" => ""], - "command" => ["type" => "varbinary(32)", "comment" => ""], - "failed" => ["type" => "tinyint", "default" => 0, "comment" => "Number of times the delivery has failed"], + "fields" => [ + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "inbox-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Item-uri id of inbox url"], + "uid" => ["type" => "mediumint unsigned", "foreign" => ["user" => "uid"], "comment" => "Delivering user"], + "created" => ["type" => "datetime", "default" => DBA::NULL_DATETIME, "comment" => ""], + "command" => ["type" => "varbinary(32)", "comment" => ""], + "failed" => ["type" => "tinyint", "default" => 0, "comment" => "Number of times the delivery has failed"], "receivers" => ["type" => "mediumtext", "comment" => "JSON encoded array with the receiving contacts"], ], "indexes" => [ - "PRIMARY" => ["uri-id", "inbox-id"], + "PRIMARY" => ["uri-id", "inbox-id"], "inbox-id_created" => ["inbox-id", "created"], - "uid" => ["uid"], - ] + "uid" => ["uid"], + ], ], "post-delivery-data" => [ "comment" => "Delivery data for items", - "fields" => [ - "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], - "postopts" => ["type" => "text", "comment" => "External post connectors add their network name to this comma-separated string to identify that they should be delivered to these networks during delivery"], - "inform" => ["type" => "mediumtext", "comment" => "Additional receivers of the linked item"], - "queue_count" => ["type" => "mediumint", "not null" => "1", "default" => "0", "comment" => "Initial number of delivery recipients, used as item.delivery_queue_count"], - "queue_done" => ["type" => "mediumint", "not null" => "1", "default" => "0", "comment" => "Number of successful deliveries, used as item.delivery_queue_done"], + "fields" => [ + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "postopts" => ["type" => "text", "comment" => "External post connectors add their network name to this comma-separated string to identify that they should be delivered to these networks during delivery"], + "inform" => ["type" => "mediumtext", "comment" => "Additional receivers of the linked item"], + "queue_count" => ["type" => "mediumint", "not null" => "1", "default" => "0", "comment" => "Initial number of delivery recipients, used as item.delivery_queue_count"], + "queue_done" => ["type" => "mediumint", "not null" => "1", "default" => "0", "comment" => "Number of successful deliveries, used as item.delivery_queue_done"], "queue_failed" => ["type" => "mediumint", "not null" => "1", "default" => "0", "comment" => "Number of unsuccessful deliveries, used as item.delivery_queue_failed"], - "activitypub" => ["type" => "mediumint", "not null" => "1", "default" => "0", "comment" => "Number of successful deliveries via ActivityPub"], - "dfrn" => ["type" => "mediumint", "not null" => "1", "default" => "0", "comment" => "Number of successful deliveries via DFRN"], - "legacy_dfrn" => ["type" => "mediumint", "not null" => "1", "default" => "0", "comment" => "Number of successful deliveries via legacy DFRN"], - "diaspora" => ["type" => "mediumint", "not null" => "1", "default" => "0", "comment" => "Number of successful deliveries via Diaspora"], + "activitypub" => ["type" => "mediumint", "not null" => "1", "default" => "0", "comment" => "Number of successful deliveries via ActivityPub"], + "dfrn" => ["type" => "mediumint", "not null" => "1", "default" => "0", "comment" => "Number of successful deliveries via DFRN"], + "legacy_dfrn" => ["type" => "mediumint", "not null" => "1", "default" => "0", "comment" => "Number of successful deliveries via legacy DFRN"], + "diaspora" => ["type" => "mediumint", "not null" => "1", "default" => "0", "comment" => "Number of successful deliveries via Diaspora"], ], "indexes" => [ "PRIMARY" => ["uri-id"], - ] + ], ], "post-engagement" => [ "comment" => "Engagement data per post", - "fields" => [ - "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], - "owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "comment" => "Item owner"], + "fields" => [ + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "comment" => "Item owner"], "contact-type" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => "Person, organisation, news, community, relay"], - "media-type" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => "Type of media in a bit array (1 = image, 2 = video, 4 = audio)"], - "language" => ["type" => "char(2)", "comment" => "Language information about this post in the ISO 639-1 format"], - "searchtext" => ["type" => "mediumtext", "comment" => "Simplified text for the full text search"], - "size" => ["type" => "int unsigned", "comment" => "Body size"], - "created" => ["type" => "datetime", "comment" => ""], - "network" => ["type" => "char(4)", "comment" => ""], - "restricted" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "If true, this post is either unlisted or not from a federated network"], - "comments" => ["type" => "mediumint unsigned", "comment" => "Number of comments"], - "activities" => ["type" => "mediumint unsigned", "comment" => "Number of activities (like, dislike, ...)"], - "views" => ["type" => "mediumint unsigned", "comment" => "Number of views"], + "media-type" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => "Type of media in a bit array (1 = image, 2 = video, 4 = audio)"], + "language" => ["type" => "char(2)", "comment" => "Language information about this post in the ISO 639-1 format"], + "searchtext" => ["type" => "mediumtext", "comment" => "Simplified text for the full text search"], + "size" => ["type" => "int unsigned", "comment" => "Body size"], + "created" => ["type" => "datetime", "comment" => ""], + "network" => ["type" => "char(4)", "comment" => ""], + "restricted" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "If true, this post is either unlisted or not from a federated network"], + "comments" => ["type" => "mediumint unsigned", "comment" => "Number of comments"], + "activities" => ["type" => "mediumint unsigned", "comment" => "Number of activities (like, dislike, ...)"], + "views" => ["type" => "mediumint unsigned", "comment" => "Number of views"], ], "indexes" => [ - "PRIMARY" => ["uri-id"], - "owner-id" => ["owner-id"], - "created" => ["created"], + "PRIMARY" => ["uri-id"], + "owner-id" => ["owner-id"], + "created" => ["created"], "searchtext" => ["FULLTEXT", "searchtext"], - ] + ], ], "channel-post" => [ "comment" => "Posts in a user defined channel", - "fields" => [ - "channel" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["channel" => "id"], "comment" => "Channel id"], - "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["post-engagement" => "uri-id"], "comment" => "Post engagement entry"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "foreign" => ["user" => "uid"], "comment" => "User id"], + "fields" => [ + "channel" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["channel" => "id"], "comment" => "Channel id"], + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["post-engagement" => "uri-id"], "comment" => "Post engagement entry"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "foreign" => ["user" => "uid"], "comment" => "User id"], "in-timeline" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "If true, this post is in the user's main timeline"], - "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], - "received" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], - "commented" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""] + "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "received" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "commented" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], ], "indexes" => [ - "PRIMARY" => ["channel", "uri-id"], - "uri-id" => ["uri-id"], - "uid" => ["uid"], - "channel_created" => ["channel", "created"], - "channel_received" => ["channel", "received"], + "PRIMARY" => ["channel", "uri-id"], + "uri-id" => ["uri-id"], + "uid" => ["uid"], + "channel_created" => ["channel", "created"], + "channel_received" => ["channel", "received"], "channel_commented" => ["channel", "commented"], - ] + ], ], "system-channel-post" => [ "comment" => "Posts in a system channel", - "fields" => [ - "channel" => ["type" => "varchar(20)", "not null" => "1", "primary" => "1", "comment" => "System channel id"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "User id"], - "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["post-engagement" => "uri-id"], "comment" => "Post engagement entry"], + "fields" => [ + "channel" => ["type" => "varchar(20)", "not null" => "1", "primary" => "1", "comment" => "System channel id"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "User id"], + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["post-engagement" => "uri-id"], "comment" => "Post engagement entry"], "in-timeline" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "If true, this post is in the user's main timeline"], - "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], - "received" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], - "commented" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""] + "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "received" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "commented" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], ], "indexes" => [ - "PRIMARY" => ["channel", "uid", "uri-id"], - "uri-id" => ["uri-id"], - "uid" => ["uid"], + "PRIMARY" => ["channel", "uid", "uri-id"], + "uri-id" => ["uri-id"], + "uid" => ["uid"], "channel_uid_created" => ["channel", "uid", "created"], - ] + ], ], "post-history" => [ "comment" => "Post history", - "fields" => [ - "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], - "edited" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "primary" => "1", "comment" => "Date of edit"], - "title" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "item title"], + "fields" => [ + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "edited" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "primary" => "1", "comment" => "Date of edit"], + "title" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "item title"], "content-warning" => ["type" => "varchar(500)", "not null" => "1", "default" => "", "comment" => ""], - "body" => ["type" => "mediumtext", "comment" => "item body content"], - "raw-body" => ["type" => "mediumtext", "comment" => "Body without embedded media links"], - "quote-uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table that contains the quoted uri"], - "location" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "text location where this item originated"], - "coord" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "longitude/latitude pair representing location where this item originated"], - "language" => ["type" => "text", "comment" => "Language information about this post"], - "sensitive" => ["type" => "boolean", "comment" => "If true, this post contains sensitive content"], - "app" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "application which generated this item"], - "rendered-hash" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => ""], - "rendered-html" => ["type" => "mediumtext", "comment" => "item.body converted to html"], - "object-type" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => "ActivityStreams object type"], - "object" => ["type" => "text", "comment" => "JSON encoded object structure unless it is an implied object (normal post)"], - "target-type" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => "ActivityStreams target type if applicable (URI)"], - "target" => ["type" => "text", "comment" => "JSON encoded target structure if used"], - "resource-id" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => "Used to link other tables to items, it identifies the linked resource (e.g. photo) and if set must also set resource_type"], - "plink" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => "permalink or URL to a displayable copy of the message at its source"] + "body" => ["type" => "mediumtext", "comment" => "item body content"], + "raw-body" => ["type" => "mediumtext", "comment" => "Body without embedded media links"], + "quote-uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table that contains the quoted uri"], + "location" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "text location where this item originated"], + "coord" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "longitude/latitude pair representing location where this item originated"], + "language" => ["type" => "text", "comment" => "Language information about this post"], + "sensitive" => ["type" => "boolean", "comment" => "If true, this post contains sensitive content"], + "app" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "application which generated this item"], + "rendered-hash" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => ""], + "rendered-html" => ["type" => "mediumtext", "comment" => "item.body converted to html"], + "object-type" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => "ActivityStreams object type"], + "object" => ["type" => "text", "comment" => "JSON encoded object structure unless it is an implied object (normal post)"], + "target-type" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => "ActivityStreams target type if applicable (URI)"], + "target" => ["type" => "text", "comment" => "JSON encoded target structure if used"], + "resource-id" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => "Used to link other tables to items, it identifies the linked resource (e.g. photo) and if set must also set resource_type"], + "plink" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => "permalink or URL to a displayable copy of the message at its source"], ], "indexes" => [ - "PRIMARY" => ["uri-id", "edited"], + "PRIMARY" => ["uri-id", "edited"], "quote-uri-id" => ["quote-uri-id"], - ] + ], ], "post-link" => [ "comment" => "Post related external links", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "uri-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], - "url" => ["type" => "varbinary(511)", "not null" => "1", "comment" => "External URL"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "uri-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "url" => ["type" => "varbinary(511)", "not null" => "1", "comment" => "External URL"], "mimetype" => ["type" => "varchar(60)", "comment" => ""], - "height" => ["type" => "smallint unsigned", "comment" => "Height of the media"], - "width" => ["type" => "smallint unsigned", "comment" => "Width of the media"], + "height" => ["type" => "smallint unsigned", "comment" => "Height of the media"], + "width" => ["type" => "smallint unsigned", "comment" => "Width of the media"], "blurhash" => ["type" => "varbinary(255)", "comment" => "BlurHash representation of the link"], ], "indexes" => [ - "PRIMARY" => ["id"], + "PRIMARY" => ["id"], "uri-id-url" => ["UNIQUE", "uri-id", "url"], - ] + ], ], "post-media" => [ "comment" => "Attached media", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "uri-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], - "url" => ["type" => "varbinary(1024)", "not null" => "1", "comment" => "Media URL"], - "media-uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the activities uri-id"], - "attach-id" => ["type" => "int unsigned", "foreign" => ["attach" => "id"], "comment" => "In case of a local attachment, this field is filled with the id in the attach table"], - "type" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "Media type"], - "mimetype" => ["type" => "varchar(60)", "comment" => ""], - "height" => ["type" => "smallint unsigned", "comment" => "Height of the media"], - "width" => ["type" => "smallint unsigned", "comment" => "Width of the media"], - "size" => ["type" => "bigint unsigned", "comment" => "Media size"], - "blurhash" => ["type" => "varbinary(255)", "comment" => "BlurHash representation of the image"], - "preview" => ["type" => "varbinary(512)", "comment" => "Preview URL"], - "preview-height" => ["type" => "smallint unsigned", "comment" => "Height of the preview picture"], - "preview-width" => ["type" => "smallint unsigned", "comment" => "Width of the preview picture"], - "description" => ["type" => "text", "comment" => ""], - "name" => ["type" => "varchar(255)", "comment" => "Name of the media"], - "author-url" => ["type" => "varbinary(383)", "comment" => "URL of the author of the media"], - "author-name" => ["type" => "varchar(255)", "comment" => "Name of the author of the media"], - "author-image" => ["type" => "varbinary(383)", "comment" => "Image of the author of the media"], - "publisher-url" => ["type" => "varbinary(383)", "comment" => "URL of the publisher of the media"], - "publisher-name" => ["type" => "varchar(255)", "comment" => "Name of the publisher of the media"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "uri-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "url" => ["type" => "varbinary(1024)", "not null" => "1", "comment" => "Media URL"], + "media-uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the activities uri-id"], + "attach-id" => ["type" => "int unsigned", "foreign" => ["attach" => "id"], "comment" => "In case of a local attachment, this field is filled with the id in the attach table"], + "type" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "Media type"], + "mimetype" => ["type" => "varchar(60)", "comment" => ""], + "height" => ["type" => "smallint unsigned", "comment" => "Height of the media"], + "width" => ["type" => "smallint unsigned", "comment" => "Width of the media"], + "size" => ["type" => "bigint unsigned", "comment" => "Media size"], + "blurhash" => ["type" => "varbinary(255)", "comment" => "BlurHash representation of the image"], + "preview" => ["type" => "varbinary(512)", "comment" => "Preview URL"], + "preview-height" => ["type" => "smallint unsigned", "comment" => "Height of the preview picture"], + "preview-width" => ["type" => "smallint unsigned", "comment" => "Width of the preview picture"], + "description" => ["type" => "text", "comment" => ""], + "name" => ["type" => "varchar(255)", "comment" => "Name of the media"], + "author-url" => ["type" => "varbinary(383)", "comment" => "URL of the author of the media"], + "author-name" => ["type" => "varchar(255)", "comment" => "Name of the author of the media"], + "author-image" => ["type" => "varbinary(383)", "comment" => "Image of the author of the media"], + "publisher-url" => ["type" => "varbinary(383)", "comment" => "URL of the publisher of the media"], + "publisher-name" => ["type" => "varchar(255)", "comment" => "Name of the publisher of the media"], "publisher-image" => ["type" => "varbinary(383)", "comment" => "Image of the publisher of the media"], - "player-url" => ["type" => "varbinary(383)", "comment" => "URL of the embedded player for this media"], - "player-height" => ["type" => "smallint unsigned", "comment" => "Height of the embedded player"], - "player-width" => ["type" => "smallint unsigned", "comment" => "Width of the embedded player"], - "embed-type" => ["type" => "varchar(10)", "comment" => "Type of the embed (e.g. rich or video)"], - "embed-html" => ["type" => "text", "comment" => "HTML embed code for this media"], - "embed-height" => ["type" => "smallint unsigned", "comment" => "Height of the embed"], - "embed-width" => ["type" => "smallint unsigned", "comment" => "Width of the embed"], - "page-type" => ["type" => "varchar(30)", "comment" => "Type of the page (e.g. article, website)"], - "schematypes" => ["type" => "varchar(255)", "comment" => "Schema types of the page as JSON string"], - "language" => ["type" => "char(3)", "comment" => "Language information about this media in the ISO 639 format"], - "published" => ["type" => "datetime", "comment" => "Publification date of this media"], - "modified" => ["type" => "datetime", "comment" => "Modification date of this media"], + "player-url" => ["type" => "varbinary(383)", "comment" => "URL of the embedded player for this media"], + "player-height" => ["type" => "smallint unsigned", "comment" => "Height of the embedded player"], + "player-width" => ["type" => "smallint unsigned", "comment" => "Width of the embedded player"], + "embed-type" => ["type" => "varchar(10)", "comment" => "Type of the embed (e.g. rich or video)"], + "embed-html" => ["type" => "text", "comment" => "HTML embed code for this media"], + "embed-height" => ["type" => "smallint unsigned", "comment" => "Height of the embed"], + "embed-width" => ["type" => "smallint unsigned", "comment" => "Width of the embed"], + "page-type" => ["type" => "varchar(30)", "comment" => "Type of the page (e.g. article, website)"], + "schematypes" => ["type" => "varchar(255)", "comment" => "Schema types of the page as JSON string"], + "language" => ["type" => "char(3)", "comment" => "Language information about this media in the ISO 639 format"], + "published" => ["type" => "datetime", "comment" => "Publification date of this media"], + "modified" => ["type" => "datetime", "comment" => "Modification date of this media"], ], "indexes" => [ - "PRIMARY" => ["id"], - "uri-id-url" => ["UNIQUE", "uri-id", "url(512)"], - "uri-id-id" => ["uri-id", "id"], + "PRIMARY" => ["id"], + "uri-id-url" => ["UNIQUE", "uri-id", "url(512)"], + "uri-id-id" => ["uri-id", "id"], "media-uri-id" => ["media-uri-id"], - "attach-id" => ["attach-id"], - ] + "attach-id" => ["attach-id"], + ], ], "post-media-exif" => [ "comment" => "Exif data for attached media, see https://exiv2.org/tags.html", - "fields" => [ - "media-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["post-media" => "id"], "primary" => "1", "comment" => "If of the post-media entry with EXIF data"], - "uri-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], - "raw-data" => ["type" => "text", "comment" => "JSON array with the raw exif data"], - "coord" => ["type" => "varchar(255)", "comment" => "GPS coordinates (latitude and longitude) representing the location where the picture was taken."], - "FocalLength" => ["type" => "varchar(16)", "comment" => "The focal length of the lens in mm."], - "ExposureTime" => ["type" => "varchar(16)", "comment" => "The exposure time in fractions of 1/x or full seconds."], - "ApertureFNumber" => ["type" => "varchar(16)", "comment" => "The lens aperture calculated as f number"], - "ISOSpeedRatings" => ["type" => "smallint unsigned", "comment" => "The ISO speed used to expose the image."], + "fields" => [ + "media-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["post-media" => "id"], "primary" => "1", "comment" => "If of the post-media entry with EXIF data"], + "uri-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "raw-data" => ["type" => "text", "comment" => "JSON array with the raw exif data"], + "coord" => ["type" => "varchar(255)", "comment" => "GPS coordinates (latitude and longitude) representing the location where the picture was taken."], + "FocalLength" => ["type" => "varchar(16)", "comment" => "The focal length of the lens in mm."], + "ExposureTime" => ["type" => "varchar(16)", "comment" => "The exposure time in fractions of 1/x or full seconds."], + "ApertureFNumber" => ["type" => "varchar(16)", "comment" => "The lens aperture calculated as f number"], + "ISOSpeedRatings" => ["type" => "smallint unsigned", "comment" => "The ISO speed used to expose the image."], "LensSpecification" => ["type" => "varchar(32)", "comment" => "Lens specifications, for example 35mm f/2.8 or 70-200mm f/2.8-6.3"], "FocusDistance" => ["type" => "varchar(16)", "comment" => "The distance to the subject, given in meters."], "CCDWidth" => ["type" => "varchar(16)", "comment" => ""], - "BodySerialNumber" => ["type" => "varchar(255)", "comment" => "The serial number of the body of the camera."], - "Artist" => ["type" => "varchar(255)", "comment" => "The name of the camera owner, photographer or image creator."], - "Copyright" => ["type" => "varchar(255)", "comment" => "Copyright information. In this standard the tag is used to indicate both the photographer and editor copyrights."], - "DateTime" => ["type" => "datetime", "comment" => "The date and time of image creation. In Exif standard, it is the time the file was changed."], - "DateTimeOriginal" => ["type" => "datetime", "comment" => "The date and time when the original image data was generated."], + "BodySerialNumber" => ["type" => "varchar(255)", "comment" => "The serial number of the body of the camera."], + "Artist" => ["type" => "varchar(255)", "comment" => "The name of the camera owner, photographer or image creator."], + "Copyright" => ["type" => "varchar(255)", "comment" => "Copyright information. In this standard the tag is used to indicate both the photographer and editor copyrights."], + "DateTime" => ["type" => "datetime", "comment" => "The date and time of image creation. In Exif standard, it is the time the file was changed."], + "DateTimeOriginal" => ["type" => "datetime", "comment" => "The date and time when the original image data was generated."], "DateTimeDigitized" => ["type" => "datetime", "comment" => "The date and time when the image was stored as digital data."], - "ExpandFilm" => ["type" => "varchar(255)", "comment" => "The type or brand of film used for the image, such as analog film types (e.g., Kodak E100SW)."], - "ExpandLens" => ["type" => "varchar(255)", "comment" => "The lens model or description used for the image (e.g., Nikkor 20-35mm f/2.8 zoom)."], - "HostComputer" => ["type" => "varchar(255)", "comment" => "Information about the host computer used to generate the image."], - "ImageDescription" => ["type" => "text", "comment" => "A character string giving the title of the image."], - "ImageUniqueID" => ["type" => "varchar(255)", "comment" => "A unique identifier for each image, typically in the form of a UUID or other unique string."], - "LensMake" => ["type" => "varchar(255)", "comment" => "The name of the lens manufacturer."], - "LensModel" => ["type" => "varchar(255)", "comment" => "The model name or model number of the lens used."], - "Make" => ["type" => "varchar(255)", "comment" => "The manufacturer of the recording equipment."], - "MakerNote" => ["type" => "varchar(255)", "comment" => "A tag for manufacturers of Exif writers to record any desired information. The contents are up to the manufacturer."], - "Model" => ["type" => "varchar(255)", "comment" => "The model name or model number of the equipment."], - "OwnerName" => ["type" => "varchar(255)", "comment" => "The owner of the camera."], - "Orientation" => ["type" => "tinyint unsigned", "comment" => "The image orientation in terms of rows and columns."], - "Software" => ["type" => "varchar(255)", "comment" => "The name and version of the software or firmware of the camera or image input device used to generate the image."], - "UserComment" => ["type" => "text", "comment" => "A comment provided by the user about the image."], + "ExpandFilm" => ["type" => "varchar(255)", "comment" => "The type or brand of film used for the image, such as analog film types (e.g., Kodak E100SW)."], + "ExpandLens" => ["type" => "varchar(255)", "comment" => "The lens model or description used for the image (e.g., Nikkor 20-35mm f/2.8 zoom)."], + "HostComputer" => ["type" => "varchar(255)", "comment" => "Information about the host computer used to generate the image."], + "ImageDescription" => ["type" => "text", "comment" => "A character string giving the title of the image."], + "ImageUniqueID" => ["type" => "varchar(255)", "comment" => "A unique identifier for each image, typically in the form of a UUID or other unique string."], + "LensMake" => ["type" => "varchar(255)", "comment" => "The name of the lens manufacturer."], + "LensModel" => ["type" => "varchar(255)", "comment" => "The model name or model number of the lens used."], + "Make" => ["type" => "varchar(255)", "comment" => "The manufacturer of the recording equipment."], + "MakerNote" => ["type" => "varchar(255)", "comment" => "A tag for manufacturers of Exif writers to record any desired information. The contents are up to the manufacturer."], + "Model" => ["type" => "varchar(255)", "comment" => "The model name or model number of the equipment."], + "OwnerName" => ["type" => "varchar(255)", "comment" => "The owner of the camera."], + "Orientation" => ["type" => "tinyint unsigned", "comment" => "The image orientation in terms of rows and columns."], + "Software" => ["type" => "varchar(255)", "comment" => "The name and version of the software or firmware of the camera or image input device used to generate the image."], + "UserComment" => ["type" => "text", "comment" => "A comment provided by the user about the image."], ], "indexes" => [ "PRIMARY" => ["media-id"], - "uri-id" => ["uri-id"], - ] + "uri-id" => ["uri-id"], + ], ], "post-origin" => [ "comment" => "Posts from local users", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1"], - "uri-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "foreign" => ["user" => "uid"], "comment" => "Owner id which owns this copy of the item"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1"], + "uri-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "foreign" => ["user" => "uid"], "comment" => "Owner id which owns this copy of the item"], "parent-uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table that contains the parent uri"], "thr-parent-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table that contains the thread parent uri"], - "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Creation timestamp."], - "received" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "datetime"], - "gravity" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""], - "vid" => ["type" => "smallint unsigned", "foreign" => ["verb" => "id", "on delete" => "restrict"], "comment" => "Id of the verb table entry that contains the activity verbs"], - "private" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "0=public, 1=private, 2=unlisted"], - "wall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "This item was posted to the wall of uid"], + "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Creation timestamp."], + "received" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "datetime"], + "gravity" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""], + "vid" => ["type" => "smallint unsigned", "foreign" => ["verb" => "id", "on delete" => "restrict"], "comment" => "Id of the verb table entry that contains the activity verbs"], + "private" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "0=public, 1=private, 2=unlisted"], + "wall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "This item was posted to the wall of uid"], ], "indexes" => [ - "PRIMARY" => ["id"], - "uid_uri-id" => ["UNIQUE", "uid", "uri-id"], - "uri-id" => ["uri-id"], - "parent-uri-id" => ["parent-uri-id"], - "thr-parent-id" => ["thr-parent-id"], - "vid" => ["vid"], + "PRIMARY" => ["id"], + "uid_uri-id" => ["UNIQUE", "uid", "uri-id"], + "uri-id" => ["uri-id"], + "parent-uri-id" => ["parent-uri-id"], + "thr-parent-id" => ["thr-parent-id"], + "vid" => ["vid"], "parent-uri-id_uid" => ["parent-uri-id", "uid"], "uid_wall_received" => ["uid", "wall", "received"], ], ], "post-question" => [ "comment" => "Question", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "uri-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "uri-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], "multiple" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Multiple choice"], - "voters" => ["type" => "int unsigned", "comment" => "Number of voters for this question"], + "voters" => ["type" => "int unsigned", "comment" => "Number of voters for this question"], "end-time" => ["type" => "datetime", "default" => DBA::NULL_DATETIME, "comment" => "Question end time"], ], "indexes" => [ "PRIMARY" => ["id"], - "uri-id" => ["UNIQUE", "uri-id"], - ] + "uri-id" => ["UNIQUE", "uri-id"], + ], ], "post-question-option" => [ "comment" => "Question option", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "comment" => "Id of the question"], - "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], - "name" => ["type" => "varchar(255)", "comment" => "Name of the option"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "comment" => "Id of the question"], + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "name" => ["type" => "varchar(255)", "comment" => "Name of the option"], "replies" => ["type" => "int unsigned", "comment" => "Number of replies for this question option"], ], "indexes" => [ "PRIMARY" => ["uri-id", "id"], - ] + ], ], "post-searchindex" => [ "comment" => "Content for all posts", - "fields" => [ - "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], - "owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "comment" => "Item owner"], + "fields" => [ + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "comment" => "Item owner"], "media-type" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => "Type of media in a bit array (1 = image, 2 = video, 4 = audio)"], - "language" => ["type" => "char(2)", "comment" => "Language information about this post in the ISO 639-1 format"], + "language" => ["type" => "char(2)", "comment" => "Language information about this post in the ISO 639-1 format"], "searchtext" => ["type" => "mediumtext", "comment" => "Simplified text for the full text search"], - "size" => ["type" => "int unsigned", "comment" => "Body size"], - "created" => ["type" => "datetime", "comment" => ""], + "size" => ["type" => "int unsigned", "comment" => "Body size"], + "created" => ["type" => "datetime", "comment" => ""], "restricted" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "If true, this post is either unlisted or not from a federated network"], ], "indexes" => [ - "PRIMARY" => ["uri-id"], - "owner-id" => ["owner-id"], - "created" => ["created"], + "PRIMARY" => ["uri-id"], + "owner-id" => ["owner-id"], + "created" => ["created"], "searchtext" => ["FULLTEXT", "searchtext"], - ] + ], ], "post-tag" => [ "comment" => "post relation to tags", - "fields" => [ + "fields" => [ "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], - "type" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "primary" => "1", "comment" => ""], - "tid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "primary" => "1", "foreign" => ["tag" => "id", "on delete" => "restrict"], "comment" => ""], - "cid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "primary" => "1", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Contact id of the mentioned public contact"], + "type" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "primary" => "1", "comment" => ""], + "tid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "primary" => "1", "foreign" => ["tag" => "id", "on delete" => "restrict"], "comment" => ""], + "cid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "primary" => "1", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Contact id of the mentioned public contact"], ], "indexes" => [ "PRIMARY" => ["uri-id", "type", "tid", "cid"], - "tid" => ["tid"], - "cid" => ["cid"] - ] + "tid" => ["tid"], + "cid" => ["cid"], + ], ], "post-thread" => [ "comment" => "Thread related data", - "fields" => [ - "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], - "context-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the endpoint for the context collection"], + "fields" => [ + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "context-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the endpoint for the context collection"], "conversation-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the conversation uri"], - "owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Item owner"], - "author-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Item author"], - "causer-id" => ["type" => "int unsigned", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the contact that caused the item creation"], - "network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => ""], - "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], - "received" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], - "changed" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date that something in the conversation changed, indicating clients should fetch the conversation again"], - "commented" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""] + "owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Item owner"], + "author-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Item author"], + "causer-id" => ["type" => "int unsigned", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the contact that caused the item creation"], + "network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => ""], + "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "received" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "changed" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date that something in the conversation changed, indicating clients should fetch the conversation again"], + "commented" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], ], "indexes" => [ - "PRIMARY" => ["uri-id"], - "context-id" => ["context-id"], + "PRIMARY" => ["uri-id"], + "context-id" => ["context-id"], "conversation-id" => ["conversation-id"], - "owner-id" => ["owner-id"], - "author-id" => ["author-id"], - "causer-id" => ["causer-id"], - "received" => ["received"], - "commented" => ["commented"], - ] + "owner-id" => ["owner-id"], + "author-id" => ["author-id"], + "causer-id" => ["causer-id"], + "received" => ["received"], + "commented" => ["commented"], + ], ], "post-user" => [ "comment" => "User specific post data", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"], - "uri-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], - "parent-uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table that contains the parent uri"], - "thr-parent-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table that contains the thread parent uri"], - "external-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the external uri"], - "replies-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the endpoint for the replies collection"], - "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Creation timestamp."], - "edited" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of last edit (default is created)"], - "received" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "datetime"], - "gravity" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""], - "network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => "Network from where the item comes from"], - "owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the owner of this item"], - "author-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the author of this item"], - "causer-id" => ["type" => "int unsigned", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the contact that caused the item creation"], - "post-type" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "Post type (personal note, image, article, ...)"], - "post-reason" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "Reason why the post arrived at the user"], - "vid" => ["type" => "smallint unsigned", "foreign" => ["verb" => "id", "on delete" => "restrict"], "comment" => "Id of the verb table entry that contains the activity verbs"], - "private" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "0=public, 1=private, 2=unlisted"], - "restrictions" => ["type" => "tinyint unsigned", "comment" => "Bit array of post restrictions (1 = Reply, 2 = Like, 4 = Announce)"], - "global" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "visible" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "deleted" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "item has been marked for deletion"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "foreign" => ["user" => "uid"], "comment" => "Owner id which owns this copy of the item"], - "protocol" => ["type" => "tinyint unsigned", "comment" => "Protocol used to deliver the item for this user"], - "contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "comment" => "contact.id"], - "event-id" => ["type" => "int unsigned", "foreign" => ["event" => "id"], "comment" => "Used to link to the event.id"], - "unseen" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => "post has not been seen"], - "hidden" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Marker to hide the post from the user"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"], + "uri-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "parent-uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table that contains the parent uri"], + "thr-parent-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table that contains the thread parent uri"], + "external-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the external uri"], + "replies-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the endpoint for the replies collection"], + "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Creation timestamp."], + "edited" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of last edit (default is created)"], + "received" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "datetime"], + "gravity" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""], + "network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => "Network from where the item comes from"], + "owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the owner of this item"], + "author-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the author of this item"], + "causer-id" => ["type" => "int unsigned", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the contact that caused the item creation"], + "post-type" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "Post type (personal note, image, article, ...)"], + "post-reason" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "Reason why the post arrived at the user"], + "vid" => ["type" => "smallint unsigned", "foreign" => ["verb" => "id", "on delete" => "restrict"], "comment" => "Id of the verb table entry that contains the activity verbs"], + "private" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "0=public, 1=private, 2=unlisted"], + "restrictions" => ["type" => "tinyint unsigned", "comment" => "Bit array of post restrictions (1 = Reply, 2 = Like, 4 = Announce)"], + "global" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "visible" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "deleted" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "item has been marked for deletion"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "foreign" => ["user" => "uid"], "comment" => "Owner id which owns this copy of the item"], + "protocol" => ["type" => "tinyint unsigned", "comment" => "Protocol used to deliver the item for this user"], + "contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "comment" => "contact.id"], + "event-id" => ["type" => "int unsigned", "foreign" => ["event" => "id"], "comment" => "Used to link to the event.id"], + "unseen" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => "post has not been seen"], + "hidden" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Marker to hide the post from the user"], "notification-type" => ["type" => "smallint unsigned", "not null" => "1", "default" => "0", "comment" => ""], - "wall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "This item was posted to the wall of uid"], - "origin" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "item originated at this site"], - "psid" => ["type" => "int unsigned", "foreign" => ["permissionset" => "id", "on delete" => "restrict"], "comment" => "ID of the permission set of this post"], + "wall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "This item was posted to the wall of uid"], + "origin" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "item originated at this site"], + "psid" => ["type" => "int unsigned", "foreign" => ["permissionset" => "id", "on delete" => "restrict"], "comment" => "ID of the permission set of this post"], ], "indexes" => [ - "PRIMARY" => ["id"], - "uid_uri-id" => ["UNIQUE", "uid", "uri-id"], + "PRIMARY" => ["id"], + "uid_uri-id" => ["UNIQUE", "uid", "uri-id"], "uri-id_origin_deleted" => ["uri-id", "origin", "deleted"], - "parent-uri-id" => ["parent-uri-id"], - "thr-parent-id" => ["thr-parent-id"], - "external-id" => ["external-id"], - "replies-id" => ["replies-id"], - "owner-id" => ["owner-id"], - "author-id" => ["author-id"], - "causer-id" => ["causer-id"], - "vid" => ["vid"], - "contact-id" => ["contact-id"], - "event-id" => ["event-id"], - "psid" => ["psid"], - "author-id_uid" => ["author-id", "uid"], - "author-id_created" => ["author-id", "created"], - "owner-id_created" => ["owner-id", "created"], - "parent-uri-id_uid" => ["parent-uri-id", "uid"], - "uid_wall_received" => ["uid", "wall", "received"], - "uid_contactid" => ["uid", "contact-id"], - "uid_unseen_contactid" => ["uid", "unseen", "contact-id"], - "uid_unseen" => ["uid", "unseen"], - "uid_hidden_uri-id" => ["uid", "hidden", "uri-id"], + "parent-uri-id" => ["parent-uri-id"], + "thr-parent-id" => ["thr-parent-id"], + "external-id" => ["external-id"], + "replies-id" => ["replies-id"], + "owner-id" => ["owner-id"], + "author-id" => ["author-id"], + "causer-id" => ["causer-id"], + "vid" => ["vid"], + "contact-id" => ["contact-id"], + "event-id" => ["event-id"], + "psid" => ["psid"], + "author-id_uid" => ["author-id", "uid"], + "author-id_created" => ["author-id", "created"], + "owner-id_created" => ["owner-id", "created"], + "parent-uri-id_uid" => ["parent-uri-id", "uid"], + "uid_wall_received" => ["uid", "wall", "received"], + "uid_contactid" => ["uid", "contact-id"], + "uid_unseen_contactid" => ["uid", "unseen", "contact-id"], + "uid_unseen" => ["uid", "unseen"], + "uid_hidden_uri-id" => ["uid", "hidden", "uri-id"], ], ], "post-thread-user" => [ "comment" => "Thread related data per user", - "fields" => [ - "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], - "context-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the endpoint for the context collection"], + "fields" => [ + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "context-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the endpoint for the context collection"], "conversation-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the conversation uri"], - "owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Item owner"], - "author-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Item author"], - "causer-id" => ["type" => "int unsigned", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the contact that caused the item creation"], - "network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => ""], - "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], - "received" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], - "changed" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date that something in the conversation changed, indicating clients should fetch the conversation again"], - "commented" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "Owner id which owns this copy of the item"], - "pinned" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "deprecated"], - "starred" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "ignored" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Ignore updates for this thread"], - "wall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "This item was posted to the wall of uid"], - "mention" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "pubmail" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "forum_mode" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "Deprecated"], - "contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "comment" => "contact.id"], - "unseen" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => "post has not been seen"], - "hidden" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Marker to hide the post from the user"], - "origin" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "item originated at this site"], - "psid" => ["type" => "int unsigned", "foreign" => ["permissionset" => "id", "on delete" => "restrict"], "comment" => "ID of the permission set of this post"], - "post-user-id" => ["type" => "int unsigned", "foreign" => ["post-user" => "id"], "comment" => "Id of the post-user table"], + "owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Item owner"], + "author-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Item author"], + "causer-id" => ["type" => "int unsigned", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the contact that caused the item creation"], + "network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => ""], + "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "received" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "changed" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date that something in the conversation changed, indicating clients should fetch the conversation again"], + "commented" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "Owner id which owns this copy of the item"], + "pinned" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "deprecated"], + "starred" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "ignored" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Ignore updates for this thread"], + "wall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "This item was posted to the wall of uid"], + "mention" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "pubmail" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "forum_mode" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "Deprecated"], + "contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "comment" => "contact.id"], + "unseen" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => "post has not been seen"], + "hidden" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Marker to hide the post from the user"], + "origin" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "item originated at this site"], + "psid" => ["type" => "int unsigned", "foreign" => ["permissionset" => "id", "on delete" => "restrict"], "comment" => "ID of the permission set of this post"], + "post-user-id" => ["type" => "int unsigned", "foreign" => ["post-user" => "id"], "comment" => "Id of the post-user table"], ], "indexes" => [ - "PRIMARY" => ["uid", "uri-id"], - "uri-id" => ["uri-id"], - "context-id" => ["context-id"], - "conversation-id" => ["conversation-id"], - "owner-id" => ["owner-id"], - "author-id" => ["author-id"], - "causer-id" => ["causer-id"], - "uid" => ["uid"], - "contact-id" => ["contact-id"], - "psid" => ["psid"], - "post-user-id" => ["post-user-id"], - "commented" => ["commented"], - "received" => ["received"], - "author-id_created" => ["author-id", "created"], - "owner-id_created" => ["owner-id", "created"], - "uid_received" => ["uid", "received"], - "uid_wall_received" => ["uid", "wall", "received"], - "uid_commented" => ["uid", "commented"], - "uid_created" => ["uid", "created"], - "uid_starred" => ["uid", "starred"], - "uid_mention" => ["uid", "mention"], + "PRIMARY" => ["uid", "uri-id"], + "uri-id" => ["uri-id"], + "context-id" => ["context-id"], + "conversation-id" => ["conversation-id"], + "owner-id" => ["owner-id"], + "author-id" => ["author-id"], + "causer-id" => ["causer-id"], + "uid" => ["uid"], + "contact-id" => ["contact-id"], + "psid" => ["psid"], + "post-user-id" => ["post-user-id"], + "commented" => ["commented"], + "received" => ["received"], + "author-id_created" => ["author-id", "created"], + "owner-id_created" => ["owner-id", "created"], + "uid_received" => ["uid", "received"], + "uid_wall_received" => ["uid", "wall", "received"], + "uid_commented" => ["uid", "commented"], + "uid_created" => ["uid", "created"], + "uid_starred" => ["uid", "starred"], + "uid_mention" => ["uid", "mention"], "contact-id_commented" => ["contact-id", "commented"], - "contact-id_received" => ["contact-id", "received"], - "contact-id_created" => ["contact-id", "created"], - ] + "contact-id_received" => ["contact-id", "received"], + "contact-id_created" => ["contact-id", "created"], + ], ], "post-user-notification" => [ "comment" => "User post notifications", - "fields" => [ - "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "Owner id which owns this copy of the item"], + "fields" => [ + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "Owner id which owns this copy of the item"], "notification-type" => ["type" => "smallint unsigned", "not null" => "1", "default" => "0", "comment" => ""], ], "indexes" => [ "PRIMARY" => ["uid", "uri-id"], - "uri-id" => ["uri-id"], + "uri-id" => ["uri-id"], ], ], "process" => [ "comment" => "Currently running system processes", - "fields" => [ - "pid" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "comment" => "The ID of the process"], + "fields" => [ + "pid" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "comment" => "The ID of the process"], "hostname" => ["type" => "varchar(255)", "not null" => "1", "primary" => "1", "comment" => "The name of the host the process is ran on"], - "command" => ["type" => "varbinary(32)", "not null" => "1", "default" => "", "comment" => ""], - "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "command" => ["type" => "varbinary(32)", "not null" => "1", "default" => "", "comment" => ""], + "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], ], "indexes" => [ "PRIMARY" => ["pid", "hostname"], "command" => ["command"], - ] + ], ], "profile" => [ "comment" => "user profiles data", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], - "profile-name" => ["type" => "varchar(255)", "comment" => "Deprecated"], - "is-default" => ["type" => "boolean", "comment" => "Deprecated"], - "hide-friends" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Hide friend list from viewers of this profile"], - "name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Unused in favor of user.username"], - "pdesc" => ["type" => "varchar(255)", "comment" => "Deprecated"], - "dob" => ["type" => "varchar(32)", "not null" => "1", "default" => "0000-00-00", "comment" => "Day of birth"], - "address" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], - "locality" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], - "region" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], - "postal-code" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => ""], - "country-name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], - "hometown" => ["type" => "varchar(255)", "comment" => "Deprecated"], - "gender" => ["type" => "varchar(32)", "comment" => "Deprecated"], - "marital" => ["type" => "varchar(255)", "comment" => "Deprecated"], - "with" => ["type" => "text", "comment" => "Deprecated"], - "howlong" => ["type" => "datetime", "comment" => "Deprecated"], - "sexual" => ["type" => "varchar(255)", "comment" => "Deprecated"], - "politic" => ["type" => "varchar(255)", "comment" => "Deprecated"], - "religion" => ["type" => "varchar(255)", "comment" => "Deprecated"], - "pub_keywords" => ["type" => "text", "comment" => ""], - "prv_keywords" => ["type" => "text", "comment" => ""], - "likes" => ["type" => "text", "comment" => "Deprecated"], - "dislikes" => ["type" => "text", "comment" => "Deprecated"], - "about" => ["type" => "text", "comment" => "Profile description"], - "summary" => ["type" => "varchar(255)", "comment" => "Deprecated"], - "music" => ["type" => "text", "comment" => "Deprecated"], - "book" => ["type" => "text", "comment" => "Deprecated"], - "tv" => ["type" => "text", "comment" => "Deprecated"], - "film" => ["type" => "text", "comment" => "Deprecated"], - "interest" => ["type" => "text", "comment" => "Deprecated"], - "romance" => ["type" => "text", "comment" => "Deprecated"], - "work" => ["type" => "text", "comment" => "Deprecated"], - "education" => ["type" => "text", "comment" => "Deprecated"], - "contact" => ["type" => "text", "comment" => "Deprecated"], - "homepage" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], + "profile-name" => ["type" => "varchar(255)", "comment" => "Deprecated"], + "is-default" => ["type" => "boolean", "comment" => "Deprecated"], + "hide-friends" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Hide friend list from viewers of this profile"], + "name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Unused in favor of user.username"], + "pdesc" => ["type" => "varchar(255)", "comment" => "Deprecated"], + "dob" => ["type" => "varchar(32)", "not null" => "1", "default" => "0000-00-00", "comment" => "Day of birth"], + "address" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "locality" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "region" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "postal-code" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => ""], + "country-name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "hometown" => ["type" => "varchar(255)", "comment" => "Deprecated"], + "gender" => ["type" => "varchar(32)", "comment" => "Deprecated"], + "marital" => ["type" => "varchar(255)", "comment" => "Deprecated"], + "with" => ["type" => "text", "comment" => "Deprecated"], + "howlong" => ["type" => "datetime", "comment" => "Deprecated"], + "sexual" => ["type" => "varchar(255)", "comment" => "Deprecated"], + "politic" => ["type" => "varchar(255)", "comment" => "Deprecated"], + "religion" => ["type" => "varchar(255)", "comment" => "Deprecated"], + "pub_keywords" => ["type" => "text", "comment" => ""], + "prv_keywords" => ["type" => "text", "comment" => ""], + "likes" => ["type" => "text", "comment" => "Deprecated"], + "dislikes" => ["type" => "text", "comment" => "Deprecated"], + "about" => ["type" => "text", "comment" => "Profile description"], + "summary" => ["type" => "varchar(255)", "comment" => "Deprecated"], + "music" => ["type" => "text", "comment" => "Deprecated"], + "book" => ["type" => "text", "comment" => "Deprecated"], + "tv" => ["type" => "text", "comment" => "Deprecated"], + "film" => ["type" => "text", "comment" => "Deprecated"], + "interest" => ["type" => "text", "comment" => "Deprecated"], + "romance" => ["type" => "text", "comment" => "Deprecated"], + "work" => ["type" => "text", "comment" => "Deprecated"], + "education" => ["type" => "text", "comment" => "Deprecated"], + "contact" => ["type" => "text", "comment" => "Deprecated"], + "homepage" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], "homepage_verified" => ["type" => "boolean", "not null" => 1, "default" => "0", "comment" => "was the homepage verified by a rel-me link back to the profile"], - "xmpp" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "XMPP address"], - "matrix" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Matrix address"], - "photo" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], - "thumb" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], - "publish" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "publish default profile in local directory"], - "net-publish" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "publish profile in global directory"], + "xmpp" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "XMPP address"], + "matrix" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Matrix address"], + "photo" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "thumb" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], + "publish" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "publish default profile in local directory"], + "net-publish" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "publish profile in global directory"], ], "indexes" => [ - "PRIMARY" => ["id"], + "PRIMARY" => ["id"], "uid_is-default" => ["uid", "is-default"], - ] + ], ], "profile_field" => [ "comment" => "Custom profile fields", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner user id"], - "order" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "1", "comment" => "Field ordering per user"], - "psid" => ["type" => "int unsigned", "foreign" => ["permissionset" => "id", "on delete" => "restrict"], "comment" => "ID of the permission set of this profile field - 0 = public"], - "label" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Label of the field"], - "value" => ["type" => "text", "comment" => "Value of the field"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner user id"], + "order" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "1", "comment" => "Field ordering per user"], + "psid" => ["type" => "int unsigned", "foreign" => ["permissionset" => "id", "on delete" => "restrict"], "comment" => "ID of the permission set of this profile field - 0 = public"], + "label" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Label of the field"], + "value" => ["type" => "text", "comment" => "Value of the field"], "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "creation time"], - "edited" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "last edit time"], + "edited" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "last edit time"], ], "indexes" => [ "PRIMARY" => ["id"], - "uid" => ["uid"], - "order" => ["order"], - "psid" => ["psid"], - ] + "uid" => ["uid"], + "order" => ["order"], + "psid" => ["psid"], + ], ], "register" => [ "comment" => "registrations requiring admin approval", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "hash" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => ""], - "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "User id"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "hash" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => ""], + "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "User id"], "password" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], "language" => ["type" => "varchar(16)", "not null" => "1", "default" => "", "comment" => ""], - "note" => ["type" => "text", "comment" => ""], + "note" => ["type" => "text", "comment" => ""], ], "indexes" => [ "PRIMARY" => ["id"], - "uid" => ["uid"], - ] + "uid" => ["uid"], + ], ], "report" => [ "comment" => "", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "uid" => ["type" => "mediumint unsigned", "foreign" => ["user" => "uid"], "comment" => "Reporting user"], - "reporter-id" => ["type" => "int unsigned", "foreign" => ["contact" => "id"], "comment" => "Reporting contact"], - "cid" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["contact" => "id"], "comment" => "Reported contact"], - "gsid" => ["type" => "int unsigned", "foreign" => ["gserver" => "id"], "comment" => "Reported contact server"], - "comment" => ["type" => "text", "comment" => "Report"], - "category-id" => ["type" => "int unsigned", "not null" => 1, "default" => \Friendica\Moderation\Entity\Report::CATEGORY_OTHER, "comment" => "Report category, one of Entity Report::CATEGORY_*"], - "forward" => ["type" => "boolean", "comment" => "Forward the report to the remote server"], - "public-remarks" => ["type" => "text", "comment" => "Remarks shared with the reporter"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "uid" => ["type" => "mediumint unsigned", "foreign" => ["user" => "uid"], "comment" => "Reporting user"], + "reporter-id" => ["type" => "int unsigned", "foreign" => ["contact" => "id"], "comment" => "Reporting contact"], + "cid" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["contact" => "id"], "comment" => "Reported contact"], + "gsid" => ["type" => "int unsigned", "foreign" => ["gserver" => "id"], "comment" => "Reported contact server"], + "comment" => ["type" => "text", "comment" => "Report"], + "category-id" => ["type" => "int unsigned", "not null" => 1, "default" => \Friendica\Moderation\Entity\Report::CATEGORY_OTHER, "comment" => "Report category, one of Entity Report::CATEGORY_*"], + "forward" => ["type" => "boolean", "comment" => "Forward the report to the remote server"], + "public-remarks" => ["type" => "text", "comment" => "Remarks shared with the reporter"], "private-remarks" => ["type" => "text", "comment" => "Remarks shared with the moderation team"], "last-editor-uid" => ["type" => "mediumint unsigned", "foreign" => ["user" => "uid"], "comment" => "Last editor user"], - "assigned-uid" => ["type" => "mediumint unsigned", "foreign" => ["user" => "uid"], "comment" => "Assigned moderator user"], - "status" => ["type" => "tinyint unsigned", "not null" => "1", "comment" => "Status of the report, one of Entity Report::STATUS_*"], - "resolution" => ["type" => "tinyint unsigned", "comment" => "Resolution of the report, one of Entity Report::RESOLUTION_*"], - "created" => ["type" => "datetime(6)", "not null" => "1", "default" => DBA::NULL_DATETIME6, "comment" => ""], - "edited" => ["type" => "datetime(6)", "comment" => "Last time the report has been edited"], + "assigned-uid" => ["type" => "mediumint unsigned", "foreign" => ["user" => "uid"], "comment" => "Assigned moderator user"], + "status" => ["type" => "tinyint unsigned", "not null" => "1", "comment" => "Status of the report, one of Entity Report::STATUS_*"], + "resolution" => ["type" => "tinyint unsigned", "comment" => "Resolution of the report, one of Entity Report::RESOLUTION_*"], + "created" => ["type" => "datetime(6)", "not null" => "1", "default" => DBA::NULL_DATETIME6, "comment" => ""], + "edited" => ["type" => "datetime(6)", "comment" => "Last time the report has been edited"], ], "indexes" => [ - "PRIMARY" => ["id"], - "uid" => ["uid"], - "cid" => ["cid"], - "reporter-id" => ["reporter-id"], - "gsid" => ["gsid"], - "last-editor-uid" => ["last-editor-uid"], - "assigned-uid" => ["assigned-uid"], + "PRIMARY" => ["id"], + "uid" => ["uid"], + "cid" => ["cid"], + "reporter-id" => ["reporter-id"], + "gsid" => ["gsid"], + "last-editor-uid" => ["last-editor-uid"], + "assigned-uid" => ["assigned-uid"], "status-resolution" => ["status", "resolution"], - "created" => ["created"], - "edited" => ["edited"], - ] + "created" => ["created"], + "edited" => ["edited"], + ], ], "report-post" => [ "comment" => "Individual posts attached to a moderation report", - "fields" => [ - "rid" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["report" => "id"], "comment" => "Report id"], + "fields" => [ + "rid" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["report" => "id"], "comment" => "Report id"], "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Uri-id of the reported post"], "status" => ["type" => "tinyint unsigned", "comment" => "Status of the reported post"], ], "indexes" => [ "PRIMARY" => ["rid", "uri-id"], - "uri-id" => ["uri-id"], - ] + "uri-id" => ["uri-id"], + ], ], "report-rule" => [ "comment" => "Terms of service rule lines relevant to a moderation report", - "fields" => [ - "rid" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["report" => "id"], "comment" => "Report id"], + "fields" => [ + "rid" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["report" => "id"], "comment" => "Report id"], "line-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "comment" => "Terms of service rule line number, may become invalid after a TOS change."], - "text" => ["type" => "text", "not null" => "1", "comment" => "Terms of service rule text recorded at the time of the report"], + "text" => ["type" => "text", "not null" => "1", "comment" => "Terms of service rule text recorded at the time of the report"], ], "indexes" => [ "PRIMARY" => ["rid", "line-id"], - ] + ], ], "search" => [ "comment" => "", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "User id"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "User id"], "term" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], ], "indexes" => [ - "PRIMARY" => ["id"], + "PRIMARY" => ["id"], "uid_term" => ["uid", "term(64)"], - "term" => ["term(64)"] - ] + "term" => ["term(64)"], + ], ], "session" => [ "comment" => "web session storage", - "fields" => [ - "id" => ["type" => "bigint unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], - "sid" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => ""], - "data" => ["type" => "text", "comment" => ""], + "fields" => [ + "id" => ["type" => "bigint unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "sid" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => ""], + "data" => ["type" => "text", "comment" => ""], "expire" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => ""], ], "indexes" => [ "PRIMARY" => ["id"], - "sid" => ["sid(64)"], - "expire" => ["expire"], - ] + "sid" => ["sid(64)"], + "expire" => ["expire"], + ], ], "storage" => [ "comment" => "Data stored by Database storage backend", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "Auto incremented image data id"], - "data" => ["type" => "longblob", "not null" => "1", "comment" => "file data"] - ], - "indexes" => [ - "PRIMARY" => ["id"] - ] - ], - "subscription" => [ - "comment" => "Push Subscription for the API", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "Auto incremented image data id"], - "application-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["application" => "id"], "comment" => ""], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], - "endpoint" => ["type" => "varchar(511)", "comment" => "Endpoint URL"], - "pubkey" => ["type" => "varchar(127)", "comment" => "User agent public key"], - "secret" => ["type" => "varchar(32)", "comment" => "Auth secret"], - "follow" => ["type" => "boolean", "comment" => ""], - "favourite" => ["type" => "boolean", "comment" => ""], - "reblog" => ["type" => "boolean", "comment" => ""], - "mention" => ["type" => "boolean", "comment" => ""], - "poll" => ["type" => "boolean", "comment" => ""], - "follow_request" => ["type" => "boolean", "comment" => ""], - "status" => ["type" => "boolean", "comment" => ""], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "Auto incremented image data id"], + "data" => ["type" => "longblob", "not null" => "1", "comment" => "file data"], ], "indexes" => [ "PRIMARY" => ["id"], + ], + ], + "subscription" => [ + "comment" => "Push Subscription for the API", + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "Auto incremented image data id"], + "application-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["application" => "id"], "comment" => ""], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], + "endpoint" => ["type" => "varchar(511)", "comment" => "Endpoint URL"], + "pubkey" => ["type" => "varchar(127)", "comment" => "User agent public key"], + "secret" => ["type" => "varchar(32)", "comment" => "Auth secret"], + "follow" => ["type" => "boolean", "comment" => ""], + "favourite" => ["type" => "boolean", "comment" => ""], + "reblog" => ["type" => "boolean", "comment" => ""], + "mention" => ["type" => "boolean", "comment" => ""], + "poll" => ["type" => "boolean", "comment" => ""], + "follow_request" => ["type" => "boolean", "comment" => ""], + "status" => ["type" => "boolean", "comment" => ""], + ], + "indexes" => [ + "PRIMARY" => ["id"], "application-id_uid" => ["UNIQUE", "application-id", "uid"], "uid_application-id" => ["uid", "application-id"], - ] + ], ], "check-full-text-search" => [ "comment" => "Check for a full text search match in user defined channels before storing the message in the system", - "fields" => [ - "pid" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "comment" => "The ID of the process"], + "fields" => [ + "pid" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "comment" => "The ID of the process"], "searchtext" => ["type" => "mediumtext", "comment" => "Simplified text for the full text search"], ], "indexes" => [ - "PRIMARY" => ["pid"], + "PRIMARY" => ["pid"], "searchtext" => ["FULLTEXT", "searchtext"], ], ], "userd" => [ "comment" => "Deleted usernames", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], + "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], "username" => ["type" => "varchar(255)", "not null" => "1", "comment" => ""], ], "indexes" => [ - "PRIMARY" => ["id"], + "PRIMARY" => ["id"], "username" => ["username(32)"], - ] + ], ], "user-contact" => [ "comment" => "User specific public contact data", - "fields" => [ - "cid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "primary" => "1", "foreign" => ["contact" => "id"], "comment" => "Contact id of the linked public contact"], - "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "User id"], - "uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the contact url"], - "blocked" => ["type" => "boolean", "comment" => "Contact is completely blocked for this user"], - "ignored" => ["type" => "boolean", "comment" => "Posts from this contact are ignored"], - "collapsed" => ["type" => "boolean", "comment" => "Posts from this contact are collapsed"], - "hidden" => ["type" => "boolean", "comment" => "This contact is hidden from the others"], - "channel-only" => ["type" => "boolean", "comment" => "This contact is displayed only in channels, but not in the network stream."], - "is-blocked" => ["type" => "boolean", "comment" => "User is blocked by this contact"], - "channel-frequency" => ["type" => "tinyint unsigned", "comment" => "Controls the frequency of the appearance of this contact in channels"], - "pending" => ["type" => "boolean", "comment" => ""], - "rel" => ["type" => "tinyint unsigned", "comment" => "The kind of the relation between the user and the contact"], - "info" => ["type" => "mediumtext", "comment" => ""], - "notify_new_posts" => ["type" => "boolean", "comment" => ""], - "remote_self" => ["type" => "tinyint unsigned", "comment" => "0 => No mirroring, 1-2 => Mirror as own post, 3 => Mirror as reshare"], + "fields" => [ + "cid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "primary" => "1", "foreign" => ["contact" => "id"], "comment" => "Contact id of the linked public contact"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "User id"], + "uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the contact url"], + "blocked" => ["type" => "boolean", "comment" => "Contact is completely blocked for this user"], + "ignored" => ["type" => "boolean", "comment" => "Posts from this contact are ignored"], + "collapsed" => ["type" => "boolean", "comment" => "Posts from this contact are collapsed"], + "hidden" => ["type" => "boolean", "comment" => "This contact is hidden from the others"], + "channel-only" => ["type" => "boolean", "comment" => "This contact is displayed only in channels, but not in the network stream."], + "is-blocked" => ["type" => "boolean", "comment" => "User is blocked by this contact"], + "channel-frequency" => ["type" => "tinyint unsigned", "comment" => "Controls the frequency of the appearance of this contact in channels"], + "pending" => ["type" => "boolean", "comment" => ""], + "rel" => ["type" => "tinyint unsigned", "comment" => "The kind of the relation between the user and the contact"], + "info" => ["type" => "mediumtext", "comment" => ""], + "notify_new_posts" => ["type" => "boolean", "comment" => ""], + "remote_self" => ["type" => "tinyint unsigned", "comment" => "0 => No mirroring, 1-2 => Mirror as own post, 3 => Mirror as reshare"], "fetch_further_information" => ["type" => "tinyint unsigned", "comment" => "0 => None, 1 => Fetch information, 3 => Fetch keywords, 2 => Fetch both"], - "ffi_keyword_denylist" => ["type" => "text", "comment" => ""], - "hub-verify" => ["type" => "varbinary(383)", "comment" => ""], - "protocol" => ["type" => "char(4)", "comment" => "Protocol of the contact"], - "rating" => ["type" => "tinyint", "comment" => "Automatically detected feed poll frequency"], - "priority" => ["type" => "tinyint unsigned", "comment" => "Feed poll priority"], + "ffi_keyword_denylist" => ["type" => "text", "comment" => ""], + "hub-verify" => ["type" => "varbinary(383)", "comment" => ""], + "protocol" => ["type" => "char(4)", "comment" => "Protocol of the contact"], + "rating" => ["type" => "tinyint", "comment" => "Automatically detected feed poll frequency"], + "priority" => ["type" => "tinyint unsigned", "comment" => "Feed poll priority"], ], "indexes" => [ - "PRIMARY" => ["uid", "cid"], - "cid" => ["cid"], + "PRIMARY" => ["uid", "cid"], + "cid" => ["cid"], "uri-id_uid" => ["UNIQUE", "uri-id", "uid"], - ] + ], ], "arrived-activity" => [ "comment" => "Id of arrived activities", - "fields" => [ + "fields" => [ "object-id" => ["type" => "varbinary(383)", "not null" => "1", "primary" => "1", "comment" => "object id of the incoming activity"], - "received" => ["type" => "datetime", "comment" => "Receiving date"], + "received" => ["type" => "datetime", "comment" => "Receiving date"], ], "indexes" => [ "PRIMARY" => ["object-id"], @@ -2062,9 +2062,9 @@ return [ ], "fetched-activity" => [ "comment" => "Id of fetched activities", - "fields" => [ + "fields" => [ "object-id" => ["type" => "varbinary(383)", "not null" => "1", "primary" => "1", "comment" => "object id of fetched activity"], - "received" => ["type" => "datetime", "comment" => "Receiving date"], + "received" => ["type" => "datetime", "comment" => "Receiving date"], ], "indexes" => [ "PRIMARY" => ["object-id"], @@ -2073,8 +2073,8 @@ return [ ], "worker-ipc" => [ "comment" => "Inter process communication between the frontend and the worker", - "fields" => [ - "key" => ["type" => "int", "not null" => "1", "primary" => "1", "comment" => ""], + "fields" => [ + "key" => ["type" => "int", "not null" => "1", "primary" => "1", "comment" => ""], "jobs" => ["type" => "boolean", "comment" => "Flag for outstanding jobs"], ], "indexes" => [ From 4bf0626d3c3e038ac71f43885e33550395ccfcc4 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 8 Mar 2026 21:19:30 +0000 Subject: [PATCH 184/197] Fix PR #15584 with counts --- src/Model/Post/Counts.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Model/Post/Counts.php b/src/Model/Post/Counts.php index 197395a6d6..487b6e831a 100644 --- a/src/Model/Post/Counts.php +++ b/src/Model/Post/Counts.php @@ -101,7 +101,7 @@ class Counts if (!empty($count['reaction'])) { $count['verb'] = Activity::EMOJIREACT; $count['vid'] = Verb::getID($count['verb']); - } elseif (in_array($count['verb'], $activity_verbs)) { + } elseif (in_array($count['vid'], $activity_verbs)) { $count['reaction'] = $count['verb']; } $counts[] = $count; From 351a6afe44dac92915ef26fa2b955767225a1d5a Mon Sep 17 00:00:00 2001 From: Tealk Date: Wed, 11 Mar 2026 13:46:56 +0100 Subject: [PATCH 185/197] fix moderation/users/pending --- view/theme/frio/scheme/gnome.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/view/theme/frio/scheme/gnome.css b/view/theme/frio/scheme/gnome.css index f06cbe9a82..0c9f252727 100644 --- a/view/theme/frio/scheme/gnome.css +++ b/view/theme/frio/scheme/gnome.css @@ -500,3 +500,8 @@ pre, code { background-color: var(--accent-hover) !important; } } + +.adminpage .table-hover > tbody > tr:hover + tr.details, +.table-hover > tbody > tr:hover { + background-color: var(--bg-tertiary); +} From b0b72d7cade31dc94dd15c054a931a60e37e8247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CRaroun=E2=80=9D?= Date: Wed, 11 Mar 2026 18:46:08 +0100 Subject: [PATCH 186/197] Remove box shadow from action buttons in dark theme mobile view --- view/theme/frio/scheme/dark.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/view/theme/frio/scheme/dark.css b/view/theme/frio/scheme/dark.css index 9f760baaca..06ab486dc8 100644 --- a/view/theme/frio/scheme/dark.css +++ b/view/theme/frio/scheme/dark.css @@ -180,6 +180,11 @@ main .nav-tabs > li.active > a:hover { background: none; color: $font_color_darker; } + +.wall-item-actions .btn { + box-shadow: none; + -webkit-box-shadow: none; +} .btn.focus, .btn:focus, .btn:hover { From 70b4eebc87e44b51bad44fd78dea3c6b876c5d38 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 11 Mar 2026 18:01:49 +0000 Subject: [PATCH 187/197] Fix for country.js: united states is added --- view/js/country.js | 1 + 1 file changed, 1 insertion(+) diff --git a/view/js/country.js b/view/js/country.js index 230ff03120..79444fa242 100644 --- a/view/js/country.js +++ b/view/js/country.js @@ -261,6 +261,7 @@ aStates["Uganda"] = "|Abim|Adjumani|Agago|Alebtong|Amolatar|Amudat|Amuria|Amuru| aStates["Ukraine"] = "|Avtonomna Respublika Krym (Simferopol)|Cherkasy Oblast (Cherkasy)|Chernihiv Oblast (Chernihiv)|Chernivtsi Oblast (Chernivtsi)|Dnipropetrovsk Oblast (Dnipro)|Donetsk Oblast (Donetsk)|Ivano-Frankivsk Oblast (Ivano-Frankivsk)|Kharkiv Oblast (Kharkiv)|Kherson Oblast (Kherson)|Khmelnytskyi Oblast (Khmelnytskyi)|Kirovohrad Oblast (Kropyvnytskyi)|Kyiv|Kyiv Oblast (Kyiv)|Luhansk Oblast (Luhansk)|Lviv Oblast (Lviv)|Mykolaiv Oblast (Mykolaiv)|Odesa Oblast (Odesa)|Poltava Oblast (Poltava)|Rivne Oblast (Rivne)|Sevastopol|Sumy Oblast (Sumy)|Ternopil Oblast (Ternopil)|Vinnytsia Oblast (Vinnytsia)|Volyn Oblast (Lutsk)|Zakarpattia Oblast (Uzhhorod)|Zaporizhzhia Oblast (Zaporizhzhia)|Zhytomyr Oblast (Zhytomyr)" // 27 administrative divisions (24 oblasts + Crimea + Kyiv + Sevastopol, based on 2022 administrative changes) (https://en.wikipedia.org/wiki/Administrative_divisions_of_Ukraine) aStates["United Arab Emirates"] = "|Abu Dhabi|Ajman|Dubai|Fujairah|Ras Al Khaimah|Sharjah|Umm Al Quwain"; // 7 emirates (https://en.wikipedia.org/wiki/Emirates_of_the_United_Arab_Emirates) aStates["United Kingdom"] = "|Aberdeen City|Aberdeenshire|Anglesey|Angus|Argyll and Bute|Bedfordshire|Berkshire|Blaenau Gwent|Bridgend|Bristol|Buckinghamshire|Caerphilly|Cambridgeshire|Cardiff|Carmarthenshire|Ceredigion|Cheshire|Clackmannanshire|Conwy|Cornwall|County Antrim|County Armagh|County Down|County Fermanagh|County Londonderry|County Tyrone|Cumbria|Denbighshire|Derbyshire|Devon|Dorset|Dumfries and Galloway|Dundee|Durham|East Ayrshire|East Dunbartonshire|East Lothian|East Renfrewshire|East Riding of Yorkshire|East Sussex|Edinburgh|Essex|Falkirk|Fife|Flintshire|Glamorgan|Glasgow|Gloucestershire|Greater London|Greater Manchester|Gwynedd|Hampshire|Herefordshire|Hertfordshire|Highland|Inverclyde|Isle of Wight|Kent|Lancashire|Leicestershire|Lincolnshire|Merseyside|Merthyr Tydfil|Middlesex|Midlothian|Monmouthshire|Moray|Neath Port Talbot|Newport|Newport City|Norfolk|North Ayrshire|North Lanarkshire|North Yorkshire|Northamptonshire|Northumberland|Nottinghamshire|Orkney|Oxfordshire|Pembrokeshire|Perth and Kinross|Powys|Renfrewshire|Rhondda Cynon Taff|Rutland|Scottish Borders|Shetland Isles|Shropshire|Somerset|South Ayrshire|South Lanarkshire|South Yorkshire|Staffordshire|Stirlingshire|Suffolk|Surrey|Swansea|Torfaen|Tyne and Wear|Warwickshire|West Dunbartonshire|West Lothian|West Midlands|West Sussex|West Yorkshire|Western Isles|Wiltshire|Worcestershire|Wrexham"; // 109 administrative divisions (48 English counties, 6 Northern Irish counties, 32 Scottish council areas, 23 Welsh principal areas) (https://en.wikipedia.org/wiki/Administrative_geography_of_the_United_Kingdom) +aStates["United States of America"] = "|Alabama|Alaska|Arizona|Arkansas|California|Colorado|Connecticut|Delaware|District of Columbia|Florida|Georgia|Hawaii|Idaho|Illinois|Indiana|Iowa|Kansas|Kentucky|Louisiana|Maine|Maryland|Massachusetts|Michigan|Minnesota|Mississippi|Missouri|Montana|Nebraska|Nevada|New Hampshire|New Jersey|New Mexico|New York|North Carolina|North Dakota|Ohio|Oklahoma|Oregon|Pennsylvania|Rhode Island|South Carolina|South Dakota|Tennessee|Texas|Utah|Vermont|Virginia|Washington|West Virginia|Wisconsin|Wyoming"; // 50 states and 1 federal district (https://en.wikipedia.org/wiki/States_of_the_United_States) aStates["United States Minor Outlying Islands"] = "|Baker Island|Howland Island|Jarvis Island|Johnston Atoll|Kingman Reef|Midway Atoll|Navassa Island|Palmyra Atoll|Wake Island"; // 9 islands and atolls (https://en.wikipedia.org/wiki/United_States_Minor_Outlying_Islands) aStates["Uruguay"] = "|Artigas|Canelones|Cerro Largo|Colonia|Durazno|Flores|Florida|Lavalleja|Maldonado|Montevideo|Paysandu|Rio Negro|Rivera|Rocha|Salto|San Jose|Soriano|Tacuarembo|Treinta y Tres"; // 19 departments (https://en.wikipedia.org/wiki/Departments_of_Uruguay) aStates["Uzbekistan"] = "|Andijon Wiloyati|Bukhoro Wiloyati|Farghona Wiloyati|Jizzakh Wiloyati|Khorazm Wiloyati (Urganch)|Namangan Wiloyati|Nawoiy Wiloyati|Qashqadaryo Wiloyati (Qarshi)|Qoraqalpoghiston (Nukus)|Samarqand Wiloyati|Sirdaryo Wiloyati (Guliston)|Surkhondaryo Wiloyati (Termiz)|Toshkent Shahri|Toshkent Wiloyati"; // 14 regions including autonomous republic and the capital city (https://en.wikipedia.org/wiki/Administrative_divisions_of_Uzbekistan) From ecd432c4138ac0c1c3144bb776756ac80a3ba5bd Mon Sep 17 00:00:00 2001 From: loma-one <44441246+loma-one@users.noreply.github.com> Date: Thu, 12 Mar 2026 09:45:36 +0100 Subject: [PATCH 188/197] Fix link attributes formatting in BBCode.php --- src/Content/Text/BBCode.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index 15e7b0da9d..48c0098443 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -475,7 +475,7 @@ class BBCode $preview_class = in_array($preview_mode, [self::PREVIEW_AUTO, self::PREVIEW_LARGE]) ? 'attachment-image' : 'attachment-preview'; $is_photo = ($data['type'] === 'photo'); - $link_attributes = $is_photo ? 'data-fancybox="gallery" rel="noopener noreferrer"' : 'target="_blank" rel="noopener noreferrer"'; + $link_attributes = $is_photo ? 'data-fancybox="gallery" rel="noopener noreferrer"' : 'target="_blank" rel="noopener noreferrer'; if (!empty($data['image']) && empty($data['text']) && $is_photo) { $return .= sprintf('', $data['url'], $link_attributes, self::proxyUrl($data['image'], $simplehtml, $uriid), $data['title'], $preview_class); From 2ac2000a110eb2193f0c4a273a5c9970bc8ee3ee Mon Sep 17 00:00:00 2001 From: loma-one <44441246+loma-one@users.noreply.github.com> Date: Thu, 12 Mar 2026 10:30:06 +0100 Subject: [PATCH 189/197] Fix link attributes assignment for photo previews --- src/Content/Text/BBCode.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index 48c0098443..15e7b0da9d 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -475,7 +475,7 @@ class BBCode $preview_class = in_array($preview_mode, [self::PREVIEW_AUTO, self::PREVIEW_LARGE]) ? 'attachment-image' : 'attachment-preview'; $is_photo = ($data['type'] === 'photo'); - $link_attributes = $is_photo ? 'data-fancybox="gallery" rel="noopener noreferrer"' : 'target="_blank" rel="noopener noreferrer'; + $link_attributes = $is_photo ? 'data-fancybox="gallery" rel="noopener noreferrer"' : 'target="_blank" rel="noopener noreferrer"'; if (!empty($data['image']) && empty($data['text']) && $is_photo) { $return .= sprintf('', $data['url'], $link_attributes, self::proxyUrl($data['image'], $simplehtml, $uriid), $data['title'], $preview_class); From 1e26082fcc1b9c4d323f0c55b14b084b46bd1b9c Mon Sep 17 00:00:00 2001 From: loma-one <44441246+loma-one@users.noreply.github.com> Date: Thu, 12 Mar 2026 10:37:52 +0100 Subject: [PATCH 190/197] Fix indentation for is_photo variable assignment --- src/Content/Text/BBCode.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index 15e7b0da9d..b7e6f334ab 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -474,7 +474,7 @@ class BBCode if (!empty($data['title']) && !empty($data['url'])) { $preview_class = in_array($preview_mode, [self::PREVIEW_AUTO, self::PREVIEW_LARGE]) ? 'attachment-image' : 'attachment-preview'; - $is_photo = ($data['type'] === 'photo'); + $is_photo = ($data['type'] === 'photo'); $link_attributes = $is_photo ? 'data-fancybox="gallery" rel="noopener noreferrer"' : 'target="_blank" rel="noopener noreferrer"'; if (!empty($data['image']) && empty($data['text']) && $is_photo) { From dab7a606f8f5d5a0821951b948a1b3a129267b37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CRaroun=E2=80=9D?= Date: Thu, 12 Mar 2026 11:10:23 +0100 Subject: [PATCH 191/197] fix coding standards --- src/Module/Admin/Queue.php | 39 +++++++++++++---------- view/templates/admin/queue.tpl | 10 +++++- view/theme/frio/css/style.css | 12 +++++++ view/theme/frio/templates/admin/queue.tpl | 10 +++++- view/theme/vier/style.css | 10 ++++++ 5 files changed, 62 insertions(+), 19 deletions(-) diff --git a/src/Module/Admin/Queue.php b/src/Module/Admin/Queue.php index 50502362c8..d62bccfbd5 100644 --- a/src/Module/Admin/Queue.php +++ b/src/Module/Admin/Queue.php @@ -34,11 +34,11 @@ class Queue extends BaseAdmin if ($status == 'deferred') { $condition = ["NOT `done` AND `retrial` > ?", 0]; $sub_title = DI::l10n()->t('Inspect Deferred Worker Queue'); - $info = DI::l10n()->t("This page lists the deferred worker jobs. This are jobs that couldn't be executed at the first time."); + $info = DI::l10n()->t("This page lists the deferred worker jobs. This are jobs that couldn't be executed at the first time."); } else { $condition = ["NOT `done` AND `retrial` = ?", 0]; $sub_title = DI::l10n()->t('Inspect Worker Queue'); - $info = DI::l10n()->t('This page lists the currently queued worker jobs. These jobs are handled by the worker cronjob you\'ve set up during install.'); + $info = DI::l10n()->t('This page lists the currently queued worker jobs. These jobs are handled by the worker cronjob you\'ve set up during install.'); } // @TODO Move to Model\WorkerQueue::getEntries() @@ -47,27 +47,32 @@ class Queue extends BaseAdmin $r = []; while ($entry = DBA::fetch($entries)) { // fix GH-5469. ref: src/Core/Worker.php:217 - $entry['parameter'] = Arrays::recursiveImplode(json_decode($entry['parameter'], true), ': '); - $entry['created'] = DateTimeFormat::local($entry['created']); - $entry['next_try'] = DateTimeFormat::local($entry['next_try']); - $r[] = $entry; + $param = Arrays::recursiveImplode(json_decode($entry['parameter'], true), ': '); + // Truncate long parameters to prevent text overflow + if (strlen($param) > 300) { + $param = substr($param, 0, 300) . '...'; + } + $entry['parameter'] = $param; + $entry['created'] = DateTimeFormat::local($entry['created']); + $entry['next_try'] = DateTimeFormat::local($entry['next_try']); + $r[] = $entry; } DBA::close($entries); $t = Renderer::getMarkupTemplate('admin/queue.tpl'); return Renderer::replaceMacros($t, [ - '$title' => DI::l10n()->t('Administration'), - '$page' => $sub_title, - '$count' => count($r), - '$id_header' => DI::l10n()->t('ID'), - '$command_header' => DI::l10n()->t('Command'), - '$param_header' => DI::l10n()->t('Job Parameters'), - '$created_header' => DI::l10n()->t('Created'), + '$title' => DI::l10n()->t('Administration'), + '$page' => $sub_title, + '$count' => count($r), + '$id_header' => DI::l10n()->t('ID'), + '$command_header' => DI::l10n()->t('Command'), + '$param_header' => DI::l10n()->t('Job Parameters'), + '$created_header' => DI::l10n()->t('Created'), '$next_try_header' => DI::l10n()->t('Next Try'), - '$prio_header' => DI::l10n()->t('Priority'), - '$info' => $info, - '$status' => $status, - '$entries' => $r, + '$prio_header' => DI::l10n()->t('Priority'), + '$info' => $info, + '$status' => $status, + '$entries' => $r, ]); } } diff --git a/view/templates/admin/queue.tpl b/view/templates/admin/queue.tpl index 7c35edf18c..ad00b12e40 100644 --- a/view/templates/admin/queue.tpl +++ b/view/templates/admin/queue.tpl @@ -4,11 +4,19 @@ * * SPDX-License-Identifier: AGPL-3.0-or-later *}} -
    +

    {{$title}} - {{$page}} ({{$count}})

    {{$info}}

    + + + + + + {{if ($status == "deferred") }}{{/if}} + + diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index d02607685d..c5fdd262c6 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -3642,6 +3642,17 @@ li.addon { width: 60%; } } +#adminpage td, +.adminpage td, +#adminpage .table td, +.adminpage .table td, +#adminpage.table > tbody > tr > td, +.adminpage.table > tbody > tr > td, +.table#adminpage > tbody > tr > td { + word-break: break-all !important; + white-space: normal !important; + vertical-align: top !important; +} #admin-users #users tr.blocked { background-color: #f8efc0; } @@ -4342,3 +4353,4 @@ div.login-form, .login-content-wrapper, padding-left: 3px; } } + diff --git a/view/theme/frio/templates/admin/queue.tpl b/view/theme/frio/templates/admin/queue.tpl index 18470cca43..74db4c8dad 100644 --- a/view/theme/frio/templates/admin/queue.tpl +++ b/view/theme/frio/templates/admin/queue.tpl @@ -4,11 +4,19 @@ * * SPDX-License-Identifier: AGPL-3.0-or-later *}} -
    +

    {{$title}} - {{$page}} ({{$count}})

    {{$info}}

    {{$id_header}} {{$command_header}}
    + + + + + + {{if ($status == "deferred") }}{{/if}} + + diff --git a/view/theme/vier/style.css b/view/theme/vier/style.css index b5554eb4f1..9c5c0a8854 100644 --- a/view/theme/vier/style.css +++ b/view/theme/vier/style.css @@ -25,6 +25,16 @@ img { /* width: 80%; */ } +/* Fix text overflow in admin queue page */ +#adminpage td, +.adminpage td, +#adminpage .table td, +.adminpage .table td { + word-break: break-all !important; + white-space: normal !important; + vertical-align: top !important; +} + #adminpage .screenshot img { width: 640px; } From fd96f4bccd4d72d48d3534428308e83a04e7af4a Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 14 Mar 2026 07:52:23 +0100 Subject: [PATCH 192/197] fix: replace non-existing release 2025.07 with 2026.01 --- bin/daemon.php | 4 +- bin/jetstream.php | 4 +- bin/worker.php | 4 +- doc/en/developer/strategy-hooks.md | 2 +- src/BaseRepository.php | 4 +- src/Content/Conversation.php | 2 +- src/Core/Addon.php | 44 +++++++++---------- src/Core/Addon/Capability/ICanLoadAddons.php | 4 +- src/Core/Addon/Model/AddonLoader.php | 12 ++--- src/Core/Hooks/Util/StrategiesFileManager.php | 6 +-- src/Core/Logger.php | 18 ++++---- .../Factory/AbstractLoggerTypeFactory.php | 4 +- .../Factory/DelegatingLoggerFactory.php | 4 +- src/Core/Logger/Factory/Logger.php | 4 +- src/Core/Logger/Factory/StreamLogger.php | 4 +- src/Core/Logger/Factory/SyslogLogger.php | 4 +- src/DI.php | 6 +-- src/Module/Moderation/Report/Create.php | 2 +- src/Module/Settings/Channels.php | 2 +- static/defaults.config.php | 2 +- 20 files changed, 68 insertions(+), 68 deletions(-) diff --git a/bin/daemon.php b/bin/daemon.php index dfcdc9d27b..d14b6e3eb5 100755 --- a/bin/daemon.php +++ b/bin/daemon.php @@ -6,7 +6,7 @@ * * SPDX-License-Identifier: AGPL-3.0-or-later * - * @deprecated 2025.07 use `bin/console.php daemon` instead + * @deprecated 2026.01 use `bin/console.php daemon` instead */ /** @@ -24,7 +24,7 @@ chdir(dirname(__DIR__)); require dirname(__DIR__) . '/vendor/autoload.php'; -fwrite(STDOUT, '`bin/daemon.php` is deprecated since 2025.07 and will be removed in 5 months, please use `bin/console.php daemon` instead.' . \PHP_EOL); +fwrite(STDOUT, '`bin/daemon.php` is deprecated since 2026.01 and will be removed in 5 months, please use `bin/console.php daemon` instead.' . \PHP_EOL); // BC: Add console command as second argument $argv = $_SERVER['argv'] ?? []; diff --git a/bin/jetstream.php b/bin/jetstream.php index 3c1b603ce2..5ac6958a8c 100755 --- a/bin/jetstream.php +++ b/bin/jetstream.php @@ -6,7 +6,7 @@ * * SPDX-License-Identifier: AGPL-3.0-or-later * - * @deprecated 2025.07 use `bin/console.php jetstream` instead + * @deprecated 2026.01 use `bin/console.php jetstream` instead */ if (php_sapi_name() !== 'cli') { @@ -19,7 +19,7 @@ chdir(dirname(__DIR__)); require dirname(__DIR__) . '/vendor/autoload.php'; -fwrite(STDOUT, '`bin/jetstream.php` is deprecated since 2025.07 and will be removed in 5 months, please use `bin/console.php jetstream` instead.' . \PHP_EOL); +fwrite(STDOUT, '`bin/jetstream.php` is deprecated since 2026.01 and will be removed in 5 months, please use `bin/console.php jetstream` instead.' . \PHP_EOL); // BC: Add console command as second argument $argv = $_SERVER['argv'] ?? []; diff --git a/bin/worker.php b/bin/worker.php index a056c8fd01..c7c8de8adb 100755 --- a/bin/worker.php +++ b/bin/worker.php @@ -8,7 +8,7 @@ * * Starts the background processing * - * @deprecated 2025.07 use `bin/console.php worker` instead + * @deprecated 2026.01 use `bin/console.php worker` instead */ if (php_sapi_name() !== 'cli') { @@ -21,7 +21,7 @@ chdir(dirname(__DIR__)); require dirname(__DIR__) . '/vendor/autoload.php'; -fwrite(STDOUT, '`bin/worker.php` is deprecated since 2025.07 and will be removed in 5 months, please use `bin/console.php worker` instead.' . \PHP_EOL); +fwrite(STDOUT, '`bin/worker.php` is deprecated since 2026.01 and will be removed in 5 months, please use `bin/console.php worker` instead.' . \PHP_EOL); // BC: Add console command as second argument $argv = $_SERVER['argv'] ?? []; diff --git a/doc/en/developer/strategy-hooks.md b/doc/en/developer/strategy-hooks.md index 1e6bf1090b..82bcfe3675 100644 --- a/doc/en/developer/strategy-hooks.md +++ b/doc/en/developer/strategy-hooks.md @@ -80,7 +80,7 @@ return [ ## Addons -> ⚠️ Since Friendica 2025.07 the strategy hooks for addons are deprecated, please use PHP hooks instead. +> ⚠️ Since Friendica 2026.01 the strategy hooks for addons are deprecated, please use PHP hooks instead. The hook logic is useful for decoupling the Friendica core logic, but its primary goal is to modularize Friendica in creating addons. diff --git a/src/BaseRepository.php b/src/BaseRepository.php index 44d4ee90a4..a957769cff 100644 --- a/src/BaseRepository.php +++ b/src/BaseRepository.php @@ -148,13 +148,13 @@ abstract class BaseRepository } /** - * @deprecated 2025.07 Use `\Friendica\BaseRepository::_selectFirstRowAsArray()` instead + * @deprecated 2026.01 Use `\Friendica\BaseRepository::_selectFirstRowAsArray()` instead * * @throws NotFoundException */ protected function _selectOne(array $condition, array $params = []): BaseEntity { - @trigger_error('`' . __METHOD__ . '()` is deprecated since 2025.07 and will be removed after 5 months, use `\Friendica\BaseRepository::_selectFirstRowAsArray()` instead.', E_USER_DEPRECATED); + @trigger_error('`' . __METHOD__ . '()` is deprecated since 2026.01 and will be removed after 5 months, use `\Friendica\BaseRepository::_selectFirstRowAsArray()` instead.', E_USER_DEPRECATED); $fields = $this->_selectFirstRowAsArray($condition, $params); diff --git a/src/Content/Conversation.php b/src/Content/Conversation.php index 9349167c8a..55bed4b75c 100644 --- a/src/Content/Conversation.php +++ b/src/Content/Conversation.php @@ -273,7 +273,7 @@ class Conversation break; case 'dislike': $dislike_translation_plural = ' don\'t like this'; - // @deprecated 2025.07 this translation is scheduled for removal as a new translation has been added without the typo + // @deprecated 2026.01 this translation is scheduled for removal as a new translation has been added without the typo $dislike_translation_plural = ' don\'t like this'; $phrase = $this->l10n->tt(' doesn\'t like this', $dislike_translation_plural, $total, $spanatts); break; diff --git a/src/Core/Addon.php b/src/Core/Addon.php index 596bcab514..47489e89ca 100644 --- a/src/Core/Addon.php +++ b/src/Core/Addon.php @@ -13,14 +13,14 @@ use Friendica\Util\Strings; /** * Some functions to handle addons * - * @deprecated 2025.07 Use implementation of `Friendica\Core\Addon\AddonHelper` instead + * @deprecated 2026.01 Use implementation of `Friendica\Core\Addon\AddonHelper` instead */ class Addon { /** * The addon sub-directory * - * @deprecated 2025.07 Use `Friendica\Core\Addon\AddonHelper::getAddonPath()` instead + * @deprecated 2026.01 Use `Friendica\Core\Addon\AddonHelper::getAddonPath()` instead * * @var string */ @@ -38,14 +38,14 @@ 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.07 Use `Friendica\Core\Addon\AddonHelper::getAvailableAddons()` instead + * @deprecated 2026.01 Use `Friendica\Core\Addon\AddonHelper::getAvailableAddons()` instead * * @return array * @throws \Exception */ public static function getAvailableList(): array { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); $addons = []; $files = glob('addon/*/'); @@ -72,14 +72,14 @@ 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.07 Use `Friendica\Core\Addon\AddonHelper::getEnabledAddonsWithAdminSettings()` instead + * @deprecated 2026.01 Use `Friendica\Core\Addon\AddonHelper::getEnabledAddonsWithAdminSettings()` instead * * @return array * @throws \Exception */ public static function getAdminList(): array { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); $addons_admin = []; $addons = array_filter(DI::config()->get('addons') ?? []); @@ -111,11 +111,11 @@ 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.07 Use `Friendica\Core\Addon\AddonHelper::loadAddons()` instead + * @deprecated 2026.01 Use `Friendica\Core\Addon\AddonHelper::loadAddons()` instead */ public static function loadAddons() { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); self::$addons = array_keys(array_filter(DI::config()->get('addons') ?? [])); } @@ -123,7 +123,7 @@ class Addon /** * uninstalls an addon. * - * @deprecated 2025.07 Use `Friendica\Core\Addon\AddonHelper::uninstallAddon()` instead + * @deprecated 2026.01 Use `Friendica\Core\Addon\AddonHelper::uninstallAddon()` instead * * @param string $addon name of the addon * @return void @@ -131,7 +131,7 @@ class Addon */ public static function uninstall(string $addon) { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); $addon = Strings::sanitizeFilePathItem($addon); @@ -153,7 +153,7 @@ class Addon /** * installs an addon. * - * @deprecated 2025.07 Use `Friendica\Core\Addon\AddonHelper::installAddon()` instead + * @deprecated 2026.01 Use `Friendica\Core\Addon\AddonHelper::installAddon()` instead * * @param string $addon name of the addon * @return bool @@ -161,7 +161,7 @@ class Addon */ public static function install(string $addon): bool { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); $addon = Strings::sanitizeFilePathItem($addon); @@ -195,7 +195,7 @@ class Addon /** * reload all updated addons * - * @deprecated 2025.07 Use `Friendica\Core\Addon\AddonHelper::reloadAddons()` instead + * @deprecated 2026.01 Use `Friendica\Core\Addon\AddonHelper::reloadAddons()` instead * * @return void * @throws \Exception @@ -203,7 +203,7 @@ class Addon */ public static function reload() { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); $addons = array_filter(DI::config()->get('addons') ?? []); @@ -236,7 +236,7 @@ class Addon * * * *\endcode * - * @deprecated 2025.07 Use `Friendica\Core\Addon\AddonHelper::getAddonInfo()` instead + * @deprecated 2026.01 Use `Friendica\Core\Addon\AddonHelper::getAddonInfo()` instead * * @param string $addon the name of the addon * @return array with the addon information @@ -244,7 +244,7 @@ class Addon */ public static function getInfo(string $addon): array { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); $addon = Strings::sanitizeFilePathItem($addon); @@ -300,14 +300,14 @@ class Addon /** * Checks if the provided addon is enabled * - * @deprecated 2025.07 Use `Friendica\Core\Addon\AddonHelper::isAddonEnabled()` instead + * @deprecated 2026.01 Use `Friendica\Core\Addon\AddonHelper::isAddonEnabled()` instead * * @param string $addon * @return boolean */ public static function isEnabled(string $addon): bool { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); return in_array($addon, self::$addons); } @@ -315,13 +315,13 @@ class Addon /** * Returns a list of the enabled addon names * - * @deprecated 2025.07 Use `Friendica\Core\Addon\AddonHelper::getEnabledAddons()` instead + * @deprecated 2026.01 Use `Friendica\Core\Addon\AddonHelper::getEnabledAddons()` instead * * @return array */ public static function getEnabledList(): array { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); return self::$addons; } @@ -329,14 +329,14 @@ class Addon /** * Returns the list of non-hidden enabled addon names * - * @deprecated 2025.07 Use `Friendica\Core\Addon\AddonHelper::getVisibleEnabledAddons()` instead + * @deprecated 2026.01 Use `Friendica\Core\Addon\AddonHelper::getVisibleEnabledAddons()` instead * * @return array * @throws \Exception */ public static function getVisibleList(): array { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); $visible_addons = []; $addons = array_filter(DI::config()->get('addons') ?? []); diff --git a/src/Core/Addon/Capability/ICanLoadAddons.php b/src/Core/Addon/Capability/ICanLoadAddons.php index 6005d0f81e..d3e0faabf2 100644 --- a/src/Core/Addon/Capability/ICanLoadAddons.php +++ b/src/Core/Addon/Capability/ICanLoadAddons.php @@ -10,14 +10,14 @@ namespace Friendica\Core\Addon\Capability; /** * Interface for loading Addons specific content * - * @deprecated 2025.07 Use implementation of `\Friendica\Core\Addon\AddonHelper` instead. + * @deprecated 2026.01 Use implementation of `\Friendica\Core\Addon\AddonHelper` instead. */ interface ICanLoadAddons { /** * Returns a merged config array of all active addons for a given config-name * - * @deprecated 2025.07 Use `\Friendica\Core\Addon\AddonHelper::getAddonDependencyConfig()` instead. + * @deprecated 2026.01 Use `\Friendica\Core\Addon\AddonHelper::getAddonDependencyConfig()` instead. * * @param string $configName The config-name (config-file at the static directory, like 'hooks' => '{addon}/static/hooks.config.php) * diff --git a/src/Core/Addon/Model/AddonLoader.php b/src/Core/Addon/Model/AddonLoader.php index b54c6b25fb..1c4f3f91a7 100644 --- a/src/Core/Addon/Model/AddonLoader.php +++ b/src/Core/Addon/Model/AddonLoader.php @@ -15,7 +15,7 @@ use Friendica\Util\Strings; use Psr\Log\LoggerInterface; /** - * @deprecated 2025.07 Use implementation of `\Friendica\Core\Addon\AddonHelper` instead. + * @deprecated 2026.01 Use implementation of `\Friendica\Core\Addon\AddonHelper` instead. */ class AddonLoader implements ICanLoadAddons { @@ -27,18 +27,18 @@ class AddonLoader implements ICanLoadAddons public function __construct(string $basePath, IManageConfigValues $config) { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, use implementation of `Friendica\Core\Addon\AddonHelper` instead.', E_USER_DEPRECATED); $this->basePath = $basePath; $this->config = $config; } /** - * @deprecated 2025.07 Use `\Friendica\Core\Addon\AddonHelper::getAddonDependencyConfig()` instead. + * @deprecated 2026.01 Use `\Friendica\Core\Addon\AddonHelper::getAddonDependencyConfig()` instead. */ public function getActiveAddonConfig(string $configName): array { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, use `\Friendica\Core\Addon\AddonHelper::getAddonDependencyConfig()` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, use `\Friendica\Core\Addon\AddonHelper::getAddonDependencyConfig()` instead.', E_USER_DEPRECATED); $addons = array_keys(array_filter($this->config->get('addons') ?? [])); $returnConfig = []; @@ -63,14 +63,14 @@ class AddonLoader implements ICanLoadAddons foreach ($config as $classname => $rule) { if ($classname === LoggerInterface::class) { @trigger_error(sprintf( - 'Providing a strategy for `%s` is deprecated since 2025.07 and will stop working in 5 months, please provide an implementation for `%s` via `dependency.config.php` and remove the `strategies.config.php` file in the `%s` addon.', + 'Providing a strategy for `%s` is deprecated since 2026.01 and will stop working in 5 months, please provide an implementation for `%s` via `dependency.config.php` and remove the `strategies.config.php` file in the `%s` addon.', $classname, LoggerFactory::class, $addonName, ), \E_USER_DEPRECATED); } else { @trigger_error(sprintf( - 'Providing strategies for `%s` via addons is deprecated since 2025.07 and will stop working in 5 months, please stop using this and remove the `strategies.config.php` file in the `%s` addon.', + 'Providing strategies for `%s` via addons is deprecated since 2026.01 and will stop working in 5 months, please stop using this and remove the `strategies.config.php` file in the `%s` addon.', $classname, $addonName, ), \E_USER_DEPRECATED); diff --git a/src/Core/Hooks/Util/StrategiesFileManager.php b/src/Core/Hooks/Util/StrategiesFileManager.php index 2ea0e473a4..e7add36974 100644 --- a/src/Core/Hooks/Util/StrategiesFileManager.php +++ b/src/Core/Hooks/Util/StrategiesFileManager.php @@ -84,7 +84,7 @@ class StrategiesFileManager } /** - * @deprecated 2025.07 Providing strategies via addons is deprecated and will be removed in 5 months. + * @deprecated 2026.01 Providing strategies via addons is deprecated and will be removed in 5 months. */ $this->config = array_merge_recursive($config, $this->getActiveAddonConfig()); } @@ -113,14 +113,14 @@ class StrategiesFileManager foreach ($config as $classname => $rule) { if ($classname === LoggerInterface::class) { @trigger_error(sprintf( - 'Providing a strategy for `%s` is deprecated since 2025.07 and will stop working in 5 months, please provide an implementation for `%s` via `dependency.config.php` and remove the `strategies.config.php` file in the `%s` addon.', + 'Providing a strategy for `%s` is deprecated since 2026.01 and will stop working in 5 months, please provide an implementation for `%s` via `dependency.config.php` and remove the `strategies.config.php` file in the `%s` addon.', $classname, LoggerFactory::class, $addonName, ), \E_USER_DEPRECATED); } else { @trigger_error(sprintf( - 'Providing strategies for `%s` via addons is deprecated since 2025.07 and will stop working in 5 months, please stop using this and remove the `strategies.config.php` file in the `%s` addon.', + 'Providing strategies for `%s` via addons is deprecated since 2026.01 and will stop working in 5 months, please stop using this and remove the `strategies.config.php` file in the `%s` addon.', $classname, $addonName, ), \E_USER_DEPRECATED); diff --git a/src/Core/Logger.php b/src/Core/Logger.php index efff3763d5..c0f5483eb1 100644 --- a/src/Core/Logger.php +++ b/src/Core/Logger.php @@ -13,7 +13,7 @@ use Psr\Log\LoggerInterface; /** * Logger functions * - * @deprecated 2025.07 Use constructor injection or `DI::logger()` instead + * @deprecated 2026.01 Use constructor injection or `DI::logger()` instead */ class Logger { @@ -34,7 +34,7 @@ class Logger */ public static function emergency(string $message, array $context = []) { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, use constructor injection or `DI::logger()` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, use constructor injection or `DI::logger()` instead.', E_USER_DEPRECATED); self::getInstance()->emergency($message, $context); } @@ -53,7 +53,7 @@ class Logger */ public static function alert(string $message, array $context = []) { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, use constructor injection or `DI::logger()` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, use constructor injection or `DI::logger()` instead.', E_USER_DEPRECATED); self::getInstance()->alert($message, $context); } @@ -71,7 +71,7 @@ class Logger */ public static function critical(string $message, array $context = []) { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, use constructor injection or `DI::logger()` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, use constructor injection or `DI::logger()` instead.', E_USER_DEPRECATED); self::getInstance()->critical($message, $context); } @@ -88,7 +88,7 @@ class Logger */ public static function error(string $message, array $context = []) { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, use constructor injection or `DI::logger()` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, use constructor injection or `DI::logger()` instead.', E_USER_DEPRECATED); self::getInstance()->error($message, $context); } @@ -107,7 +107,7 @@ class Logger */ public static function warning(string $message, array $context = []) { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, use constructor injection or `DI::logger()` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, use constructor injection or `DI::logger()` instead.', E_USER_DEPRECATED); self::getInstance()->warning($message, $context); } @@ -123,7 +123,7 @@ class Logger */ public static function notice(string $message, array $context = []) { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, use constructor injection or `DI::logger()` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, use constructor injection or `DI::logger()` instead.', E_USER_DEPRECATED); self::getInstance()->notice($message, $context); } @@ -142,7 +142,7 @@ class Logger */ public static function info(string $message, array $context = []) { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, use constructor injection or `DI::logger()` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, use constructor injection or `DI::logger()` instead.', E_USER_DEPRECATED); self::getInstance()->info($message, $context); } @@ -158,7 +158,7 @@ class Logger */ public static function debug(string $message, array $context = []) { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, use constructor injection or `DI::logger()` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, use constructor injection or `DI::logger()` instead.', E_USER_DEPRECATED); self::getInstance()->debug($message, $context); } diff --git a/src/Core/Logger/Factory/AbstractLoggerTypeFactory.php b/src/Core/Logger/Factory/AbstractLoggerTypeFactory.php index d801ad9f14..c5540c2398 100644 --- a/src/Core/Logger/Factory/AbstractLoggerTypeFactory.php +++ b/src/Core/Logger/Factory/AbstractLoggerTypeFactory.php @@ -13,7 +13,7 @@ use Psr\Log\LogLevel; /** * Abstract class for creating logger types, which includes common necessary logic/content * - * @deprecated 2025.07 Implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead + * @deprecated 2026.01 Implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead */ abstract class AbstractLoggerTypeFactory { @@ -27,7 +27,7 @@ abstract class AbstractLoggerTypeFactory */ public function __construct(IHaveCallIntrospections $introspection, string $channel) { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead.', E_USER_DEPRECATED); $this->channel = $channel; $this->introspection = $introspection; diff --git a/src/Core/Logger/Factory/DelegatingLoggerFactory.php b/src/Core/Logger/Factory/DelegatingLoggerFactory.php index 1ee4a88ff3..b218fbf32a 100644 --- a/src/Core/Logger/Factory/DelegatingLoggerFactory.php +++ b/src/Core/Logger/Factory/DelegatingLoggerFactory.php @@ -48,10 +48,10 @@ final class DelegatingLoggerFactory implements LoggerFactory $factoryName = $this->config->get('system', 'logger_config') ?? ''; /** - * @deprecated 2025.07 The value `monolog` for `system.logger_config` inside the `config/local.config.php` file is deprecated, please use `stream` or `syslog` instead. + * @deprecated 2026.01 The value `monolog` for `system.logger_config` inside the `config/local.config.php` file is deprecated, please use `stream` or `syslog` instead. */ if ($factoryName === 'monolog') { - @trigger_error('The config `system.logger_config` with value `monolog` is deprecated since 2025.07 and will stop working in 5 months, please change the value to `stream` or `syslog` in the `config/local.config.php` file.', \E_USER_DEPRECATED); + @trigger_error('The config `system.logger_config` with value `monolog` is deprecated since 2026.01 and will stop working in 5 months, please change the value to `stream` or `syslog` in the `config/local.config.php` file.', \E_USER_DEPRECATED); $factoryName = 'stream'; } diff --git a/src/Core/Logger/Factory/Logger.php b/src/Core/Logger/Factory/Logger.php index 2f968c1767..0d0b5cfd8f 100644 --- a/src/Core/Logger/Factory/Logger.php +++ b/src/Core/Logger/Factory/Logger.php @@ -19,7 +19,7 @@ use Throwable; /** * The logger factory for the core logging instances * - * @deprecated 2025.07 Implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead + * @deprecated 2026.01 Implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead */ class Logger { @@ -28,7 +28,7 @@ class Logger public function __construct(string $channel = LogChannel::DEFAULT) { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead.', E_USER_DEPRECATED); $this->channel = $channel; } diff --git a/src/Core/Logger/Factory/StreamLogger.php b/src/Core/Logger/Factory/StreamLogger.php index abb0af5608..c0e65da364 100644 --- a/src/Core/Logger/Factory/StreamLogger.php +++ b/src/Core/Logger/Factory/StreamLogger.php @@ -20,7 +20,7 @@ use Psr\Log\NullLogger; /** * The logger factory for the StreamLogger instance * - * @deprecated 2025.07 Implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead + * @deprecated 2026.01 Implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead * @see StreamLoggerFactory * @see StreamLoggerClass */ @@ -40,7 +40,7 @@ class StreamLogger extends AbstractLoggerTypeFactory */ public function create(IManageConfigValues $config, string $logfile = null, string $channel = null): LoggerInterface { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead.', E_USER_DEPRECATED); $fileSystem = new FileSystem(); diff --git a/src/Core/Logger/Factory/SyslogLogger.php b/src/Core/Logger/Factory/SyslogLogger.php index efafc93b09..d2a11070c7 100644 --- a/src/Core/Logger/Factory/SyslogLogger.php +++ b/src/Core/Logger/Factory/SyslogLogger.php @@ -16,7 +16,7 @@ use Psr\Log\LoggerInterface; /** * The logger factory for the SyslogLogger instance * - * @deprecated 2025.07 Implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead + * @deprecated 2026.01 Implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead * @see SyslogLoggerFactory * @see SyslogLoggerClass */ @@ -33,7 +33,7 @@ class SyslogLogger extends AbstractLoggerTypeFactory */ public function create(IManageConfigValues $config): LoggerInterface { - @trigger_error('Class `' . self::class . '` is deprecated since 2025.07 and will be removed after 5 months, implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead.', E_USER_DEPRECATED); + @trigger_error('Class `' . self::class . '` is deprecated since 2026.01 and will be removed after 5 months, implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead.', E_USER_DEPRECATED); $logOpts = $config->get('system', 'syslog_flags') ?? SyslogLoggerClass::DEFAULT_FLAGS; $logFacility = $config->get('system', 'syslog_facility') ?? SyslogLoggerClass::DEFAULT_FACILITY; diff --git a/src/DI.php b/src/DI.php index 7112e727b1..4733a185e1 100644 --- a/src/DI.php +++ b/src/DI.php @@ -259,11 +259,11 @@ abstract class DI } /** - * @deprecated 2025.07 Use `DI::loggerManager()` and `DI::logger()` instead + * @deprecated 2026.01 Use `DI::loggerManager()` and `DI::logger()` instead */ public static function workerLogger(): Core\Logger\Type\WorkerLogger { - @trigger_error('`' . __METHOD__ . '()` is deprecated since 2025.07 and will be removed after 5 months, use `DI::logger()` instead.', E_USER_DEPRECATED); + @trigger_error('`' . __METHOD__ . '()` is deprecated since 2026.01 and will be removed after 5 months, use `DI::logger()` instead.', E_USER_DEPRECATED); return self::$dice->create(Core\Logger\Type\WorkerLogger::class); } @@ -632,7 +632,7 @@ abstract class DI /** * @internal The EventDispatcher should never called outside of the core, like in addons or themes - * @deprecated 2025.07 Use constructor injection instead + * @deprecated 2026.01 Use constructor injection instead */ public static function eventDispatcher(): \Psr\EventDispatcher\EventDispatcherInterface { diff --git a/src/Module/Moderation/Report/Create.php b/src/Module/Moderation/Report/Create.php index d75e8e0fab..fb69f2718a 100644 --- a/src/Module/Moderation/Report/Create.php +++ b/src/Module/Moderation/Report/Create.php @@ -273,7 +273,7 @@ class Create extends BaseModule $tpl = Renderer::getMarkupTemplate('moderation/report/create/summary.tpl'); $forward_translation = $this->t('Would you like to forward this report to the remote server?'); - // @deprecated 2025.07 this translation is scheduled for removal as a new translation has been added without the typo + // @deprecated 2026.01 this translation is scheduled for removal as a new translation has been added without the typo $forward_translation = $this->t('Would you ike to forward this report to the remote server?'); return Renderer::replaceMacros($tpl, [ diff --git a/src/Module/Settings/Channels.php b/src/Module/Settings/Channels.php index e7b41eff34..b0ef91982d 100644 --- a/src/Module/Settings/Channels.php +++ b/src/Module/Settings/Channels.php @@ -202,7 +202,7 @@ class Channels extends BaseSettings $t = Renderer::getMarkupTemplate('settings/channels.tpl'); $exclude_tags_translation = $this->t('Comma separated list of tags. If a post contain any of these tags, then it will not be part of this channel.'); - // @deprecated 2025.07 this translation is scheduled for removal as a new translation has been added without the typo + // @deprecated 2026.01 this translation is scheduled for removal as a new translation has been added without the typo $exclude_tags_translation = $this->t('Comma separated list of tags. If a post contain any of these tags, then it will not be part of nthis channel.'); return Renderer::replaceMacros($t, [ diff --git a/static/defaults.config.php b/static/defaults.config.php index 94c00d702a..eb6fcd2227 100644 --- a/static/defaults.config.php +++ b/static/defaults.config.php @@ -361,7 +361,7 @@ return [ // logger_config (String) // Sets the logging adapter of Friendica globally (syslog, stream) - // @deprecated 2025.07 The value `monolog` is deprecated, please use `stream` or `syslog` instead. + // @deprecated 2026.01 The value `monolog` is deprecated, please use `stream` or `syslog` instead. 'logger_config' => 'stream', // syslog_flags (Integer) From da46df0af2a751f928a51fe04efc155080e7aabd Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 14 Mar 2026 15:22:10 +0100 Subject: [PATCH 193/197] chore: fix code style --- bin/daemon.php | 1 + bin/jetstream.php | 1 + bin/worker.php | 1 + src/Core/Hooks/Util/StrategiesFileManager.php | 6 ++--- src/Module/Moderation/Report/Create.php | 14 ++++++------ src/Module/Settings/Channels.php | 22 +++++++++---------- static/defaults.config.php | 2 +- 7 files changed, 25 insertions(+), 22 deletions(-) diff --git a/bin/daemon.php b/bin/daemon.php index d14b6e3eb5..db9ed04028 100755 --- a/bin/daemon.php +++ b/bin/daemon.php @@ -1,5 +1,6 @@ #!/usr/bin/env php it's an empty string to cover empty/missing config values */ - const STRATEGY_DEFAULT_KEY = ''; - const STATIC_DIR = 'static'; - const CONFIG_NAME = 'strategies'; + public const STRATEGY_DEFAULT_KEY = ''; + public const STATIC_DIR = 'static'; + public const CONFIG_NAME = 'strategies'; private IManageConfigValues $configuration; protected array $config = []; diff --git a/src/Module/Moderation/Report/Create.php b/src/Module/Moderation/Report/Create.php index fb69f2718a..5a855698b2 100644 --- a/src/Module/Moderation/Report/Create.php +++ b/src/Module/Moderation/Report/Create.php @@ -32,10 +32,10 @@ use Psr\Log\LoggerInterface; class Create extends BaseModule { - const CONTACT_ACTION_NONE = 0; - const CONTACT_ACTION_COLLAPSE = 1; - const CONTACT_ACTION_IGNORE = 2; - const CONTACT_ACTION_BLOCK = 3; + public const CONTACT_ACTION_NONE = 0; + public const CONTACT_ACTION_COLLAPSE = 1; + public const CONTACT_ACTION_IGNORE = 2; + public const CONTACT_ACTION_BLOCK = 3; /** @var SystemMessages */ private $systemMessages; @@ -99,7 +99,7 @@ class Create extends BaseModule !empty($request['rule-ids']) ? explode(',', $request['rule-ids']) : [], $this->session->get('report_comment') ?? '', !empty($request['uri-ids']) ? explode(',', $request['uri-ids']) : [], - (bool)($request['forward'] ?? false), + (bool) ($request['forward'] ?? false), ); $this->repository->save($report); @@ -228,14 +228,14 @@ class Create extends BaseModule DI::userSession()->getLocalUserId(), 'system', 'itemspage_mobile_network', - DI::config()->get('system', 'itemspage_network_mobile') + DI::config()->get('system', 'itemspage_network_mobile'), ); } else { $itemsPerPage = DI::pConfig()->get( DI::userSession()->getLocalUserId(), 'system', 'itemspage_network', - DI::config()->get('system', 'itemspage_network') + DI::config()->get('system', 'itemspage_network'), ); } diff --git a/src/Module/Settings/Channels.php b/src/Module/Settings/Channels.php index b0ef91982d..2f058ccf3f 100644 --- a/src/Module/Settings/Channels.php +++ b/src/Module/Settings/Channels.php @@ -63,7 +63,7 @@ class Channels extends BaseSettings $channel_languages = User::getWantedLanguages($uid); if (!empty($request['add_channel'])) { - if (!array_diff((array)$request['new_languages'], $channel_languages)) { + if (!array_diff((array) $request['new_languages'], $channel_languages)) { $request['new_languages'] = null; } @@ -72,11 +72,11 @@ class Channels extends BaseSettings 'description' => $request['new_description'], 'access-key' => substr(mb_strtolower($request['new_access_key']), 0, 1), 'uid' => $uid, - 'circle' => (int)$request['new_circle'], + 'circle' => (int) $request['new_circle'], 'include-tags' => Strings::cleanTags($request['new_include_tags']), 'exclude-tags' => Strings::cleanTags($request['new_exclude_tags']), - 'min-size' => $request['new_min_size'] != '' ? (int)$request['new_min_size'] : null, - 'max-size' => $request['new_max_size'] != '' ? (int)$request['new_max_size'] : null, + 'min-size' => $request['new_min_size'] != '' ? (int) $request['new_min_size'] : null, + 'max-size' => $request['new_max_size'] != '' ? (int) $request['new_max_size'] : null, 'full-text-search' => $request['new_text_search'], 'media-type' => ($request['new_image'] ? 1 : 0) | ($request['new_video'] ? 2 : 0) | ($request['new_audio'] ? 4 : 0), 'languages' => $request['new_languages'], @@ -90,14 +90,14 @@ class Channels extends BaseSettings return; } - foreach (array_keys((array)$request['label']) as $id) { + foreach (array_keys((array) $request['label']) as $id) { if ($request['delete'][$id]) { $success = $this->channel->deleteById($id, $uid); $this->logger->debug('Channel deleted', ['id' => $id, 'success' => $success]); continue; } - if (!array_diff((array)$request['languages'][$id], $channel_languages) && (count((array)$request['languages'][$id]) == count($channel_languages))) { + if (!array_diff((array) $request['languages'][$id], $channel_languages) && (count((array) $request['languages'][$id]) == count($channel_languages))) { $request['languages'][$id] = null; } @@ -107,11 +107,11 @@ class Channels extends BaseSettings 'description' => $request['description'][$id], 'access-key' => substr(mb_strtolower($request['access_key'][$id]), 0, 1), 'uid' => $uid, - 'circle' => (int)$request['circle'][$id], + 'circle' => (int) $request['circle'][$id], 'include-tags' => Strings::cleanTags($request['include_tags'][$id]), 'exclude-tags' => Strings::cleanTags($request['exclude_tags'][$id]), - 'min-size' => $request['min_size'][$id] != '' ? (int)$request['min_size'][$id] : null, - 'max-size' => $request['max_size'][$id] != '' ? (int)$request['max_size'][$id] : null, + 'min-size' => $request['min_size'][$id] != '' ? (int) $request['min_size'][$id] : null, + 'max-size' => $request['max_size'][$id] != '' ? (int) $request['max_size'][$id] : null, 'full-text-search' => $request['text_search'][$id], 'media-type' => ($request['image'][$id] ? 1 : 0) | ($request['video'][$id] ? 2 : 0) | ($request['audio'][$id] ? 4 : 0), 'languages' => $request['languages'][$id], @@ -141,7 +141,7 @@ class Channels extends BaseSettings if (in_array($account_type, [User::ACCOUNT_TYPE_COMMUNITY, User::ACCOUNT_TYPE_RELAY])) { $intro = $this->t('This page can be used to define the channels that will automatically be reshared by your account.'); $circles = [ - EntityUserDefinedChannel::CIRCLE_GLOBAL => $this->l10n->t('Global Community') + EntityUserDefinedChannel::CIRCLE_GLOBAL => $this->l10n->t('Global Community'), ]; } else { $intro = $this->t('This page can be used to define your own channels.'); @@ -195,7 +195,7 @@ class Channels extends BaseSettings 'audio' => ["audio[$channel->code]", $this->t("Audio"), $channel->mediaType & 4], 'languages' => ["languages[$channel->code][]", $this->t('Languages'), $channel->languages ?? $channel_languages, $this->t('Select all languages that you want to see in this channel. "Unspecified" describes all posts for which no language information was detected (e.g. posts with just an image or too little text to be sure of the language). If you want to see all languages, you will need to select all items in the list.'), $languages, 'multiple'], 'publish' => $publish, - 'delete' => ["delete[$channel->code]", $this->t("Delete channel") . ' (' . $channel->label . ')', false, $this->t("Check to delete this entry from the channel list")] + 'delete' => ["delete[$channel->code]", $this->t("Delete channel") . ' (' . $channel->label . ')', false, $this->t("Check to delete this entry from the channel list")], ]; } diff --git a/static/defaults.config.php b/static/defaults.config.php index eb6fcd2227..75112c5e2c 100644 --- a/static/defaults.config.php +++ b/static/defaults.config.php @@ -675,7 +675,7 @@ return [ Friendica\Core\Worker::PRIORITY_HIGH => 10, Friendica\Core\Worker::PRIORITY_MEDIUM => 60, Friendica\Core\Worker::PRIORITY_LOW => 180, - Friendica\Core\Worker::PRIORITY_NEGLIGIBLE => 720 + Friendica\Core\Worker::PRIORITY_NEGLIGIBLE => 720, ], // worker_max_idletime (Integer) From fc60c12d6fe7422ece8353f78a3da41dd53c0bbe Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 21 Mar 2026 08:23:26 +0000 Subject: [PATCH 194/197] Issue 15598: Handle missing function "exif_read_data" --- src/Util/Images.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Util/Images.php b/src/Util/Images.php index ec251fee73..f32dd9177d 100644 --- a/src/Util/Images.php +++ b/src/Util/Images.php @@ -378,17 +378,19 @@ class Images } } - try { - $stream = fopen('php://memory', 'r+'); - fwrite($stream, $img_str); - rewind($stream); - $exif = @exif_read_data($stream, 'ANY_TAG, IFD0, EXIF, APP12, GPS, INTEROP'); - fclose($stream); + if (function_exists('exif_read_data')) { + try { + $stream = fopen('php://memory', 'r+'); + fwrite($stream, $img_str); + rewind($stream); + $exif = @exif_read_data($stream, 'ANY_TAG, IFD0, EXIF, APP12, GPS, INTEROP'); + fclose($stream); if (is_array($exif)) { $data['exif'] = self::sanitizeExifArray($exif); + } + } catch (\Exception $e) { + DI::logger()->error('Exception when trying to read EXIF data', ['code' => $e->getCode(), 'message' => $e->getMessage()]); } - } catch (\Exception $e) { - DI::logger()->error('Exception when trying to read EXIF data', ['code' => $e->getCode(), 'message' => $e->getMessage()]); } } From 41a3f2edca46a00690080280b0ce6dea6ce9b34c Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 21 Mar 2026 09:06:31 +0000 Subject: [PATCH 195/197] Fixes: E_WARNING: Undefined array key "register_date" --- src/Model/Profile.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Model/Profile.php b/src/Model/Profile.php index f44e550a5b..a73531c9b6 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -446,7 +446,7 @@ class Profile $network_url = 'contact/' . $cid . '/conversations'; $member_since = null; - if (Feature::isEnabled($p['uid'], Feature::MEMBER_SINCE)) { + if (isset($p['register_date']) && Feature::isEnabled($p['uid'], Feature::MEMBER_SINCE)) { $member_since = [ DI::l10n()->t('Joined:'), DI::l10n()->mediumDate($p['register_date']) ]; } From c98c4957b433d299b92e7501d978a522a0a05616 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 22 Mar 2026 02:52:31 +0000 Subject: [PATCH 196/197] Fix code standards --- src/Util/Images.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Util/Images.php b/src/Util/Images.php index f32dd9177d..0a4d2505cf 100644 --- a/src/Util/Images.php +++ b/src/Util/Images.php @@ -385,8 +385,8 @@ class Images rewind($stream); $exif = @exif_read_data($stream, 'ANY_TAG, IFD0, EXIF, APP12, GPS, INTEROP'); fclose($stream); - if (is_array($exif)) { - $data['exif'] = self::sanitizeExifArray($exif); + if (is_array($exif)) { + $data['exif'] = self::sanitizeExifArray($exif); } } catch (\Exception $e) { DI::logger()->error('Exception when trying to read EXIF data', ['code' => $e->getCode(), 'message' => $e->getMessage()]); From 90b94e955af937095b2c1824184620e2d6030adf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CRaroun=E2=80=9D?= Date: Tue, 24 Mar 2026 10:34:40 +0100 Subject: [PATCH 197/197] Fix file browser mode switch requiring double click --- view/theme/frio/js/module/media/browser.js | 44 ++++++++++++++++------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/view/theme/frio/js/module/media/browser.js b/view/theme/frio/js/module/media/browser.js index 756e4c97e5..294ebaa4ca 100644 --- a/view/theme/frio/js/module/media/browser.js +++ b/view/theme/frio/js/module/media/browser.js @@ -67,6 +67,7 @@ var Browser = { event: '', folder: '', id: null, + currentRequest: null, init: function (nickname, type, hash) { Browser.nickname = nickname; @@ -91,8 +92,12 @@ var Browser = { $('.error').addClass('hidden'); }); - // Click on album link - $('.fbrowser').on('click', '.folders button, .path button', function (e) { + // Remove existing delegated event handlers first to prevent multiple registrations + // when the filebrowser is opened multiple times + $('body').off('click.fbrowser'); + + // Click on album link - use delegated event on body with namespace + $('body').on('click.fbrowser', '.fbrowser .folders button, .fbrowser .path button', function (e) { e.preventDefault(); let url = Browser._getUrl("none", this.dataset.folder); Browser.folder = this.dataset.folder; @@ -100,8 +105,8 @@ var Browser = { Browser.loadContent(url); }); - //Embed on click - $('.fbrowser').on('click', '.photo-album-photo-link', function (e) { + //Embed on click - use delegated event on body with namespace + $('body').on('click.fbrowser', '.fbrowser .photo-album-photo-link', function (e) { e.preventDefault(); let embed = ''; @@ -137,8 +142,8 @@ var Browser = { autosize.update($('.text-autosize')); }); - // EventListener for switching between photo and file mode - $('.fbrowser').on('click', '.fbswitcher .btn', function (e) { + // EventListener for switching between photo and file mode - use delegated event on body with namespace + $('body').on('click.fbrowser', '.fbrowser .fbswitcher .btn', function (e) { e.preventDefault(); Browser.type = this.getAttribute('data-mode'); $('.fbrowser') @@ -217,16 +222,31 @@ var Browser = { // Load new content (e.g. change photo album) loadContent: function (url) { + // Abort any pending request to prevent race conditions + if (Browser.currentRequest) { + Browser.currentRequest.abort(); + } + $('.fbrowser-content').hide(); $('.fbrowser .profile-rotator-wrapper').show(); - // load new content to fbrowser window - $('.fbrowser').load(url, function (responseText, textStatus) { - $('.profile-rotator-wrapper').hide(); - if (textStatus === 'success') { - $(".fbrowser_content").show(); - Browser.postLoad(); + // Use $.ajax instead of .load() to get better control over the request + Browser.currentRequest = $.ajax({ + url: url, + type: 'GET' + }).done(function(data) { + $('.fbrowser').html(data); + Browser.postLoad(); + }).fail(function(xhr, status) { + // Only show error if it's not an abort (abort is intentional when switching quickly) + if (status !== 'abort') { + $('.error span').html('Failed to load content'); + $('.error').removeClass('hidden'); } + }).always(function() { + $('.profile-rotator-wrapper').hide(); + $('.fbrowser-content').show(); + Browser.currentRequest = null; }); },
    {{$id_header}} {{$command_header}}