diff --git a/src/Content/Conversation/Entity/Timeline.php b/src/Content/Conversation/Entity/Timeline.php index 8b8a2bc064..34d2a3534a 100644 --- a/src/Content/Conversation/Entity/Timeline.php +++ b/src/Content/Conversation/Entity/Timeline.php @@ -32,6 +32,7 @@ namespace Friendica\Content\Conversation\Entity; * @property-read string $excludeTags The tags to exclude in the channel * @property-read string $fullTextSearch full text search pattern * @property-read int $mediaType Media types that are included in the channel + * @property-read array $languages Channel languages * @property-read int $circle Circle or timeline this channel is based on */ class Timeline extends \Friendica\BaseEntity @@ -58,8 +59,10 @@ class Timeline extends \Friendica\BaseEntity protected $fullTextSearch; /** @var int */ protected $mediaType; + /** @var array */ + protected $languages; - public function __construct(string $code = null, string $label = null, string $description = null, string $accessKey = null, string $path = null, int $uid = null, string $includeTags = null, string $excludeTags = null, string $fullTextSearch = null, int $mediaType = null, int $circle = null) + public function __construct(string $code = null, string $label = null, string $description = null, string $accessKey = null, string $path = null, int $uid = null, string $includeTags = null, string $excludeTags = null, string $fullTextSearch = null, int $mediaType = null, int $circle = null, array $languages = null) { $this->code = $code; $this->label = $label; @@ -72,5 +75,6 @@ class Timeline extends \Friendica\BaseEntity $this->fullTextSearch = $fullTextSearch; $this->mediaType = $mediaType; $this->circle = $circle; + $this->languages = $languages; } } diff --git a/src/Content/Conversation/Factory/UserDefinedChannel.php b/src/Content/Conversation/Factory/UserDefinedChannel.php index 43622641d3..98e10b4fbf 100644 --- a/src/Content/Conversation/Factory/UserDefinedChannel.php +++ b/src/Content/Conversation/Factory/UserDefinedChannel.php @@ -22,7 +22,6 @@ namespace Friendica\Content\Conversation\Factory; use Friendica\Capabilities\ICanCreateFromTableRow; -use Friendica\Content\Conversation\Collection\Timelines; use Friendica\Content\Conversation\Entity; final class UserDefinedChannel extends Timeline implements ICanCreateFromTableRow @@ -34,6 +33,10 @@ final class UserDefinedChannel extends Timeline implements ICanCreateFromTableRo public function createFromTableRow(array $row): Entity\UserDefinedChannel { + if (is_string($row['languages'])) { + $row['languages'] = unserialize($row['languages']); + } + return new Entity\UserDefinedChannel( $row['id'] ?? null, $row['label'], @@ -46,6 +49,7 @@ final class UserDefinedChannel extends Timeline implements ICanCreateFromTableRo $row['full-text-search'] ?? null, $row['media-type'] ?? null, $row['circle'] ?? null, + $row['languages'] ?? null, ); } } diff --git a/src/Content/Conversation/Repository/UserDefinedChannel.php b/src/Content/Conversation/Repository/UserDefinedChannel.php index e9fa365e51..7815acdd8a 100644 --- a/src/Content/Conversation/Repository/UserDefinedChannel.php +++ b/src/Content/Conversation/Repository/UserDefinedChannel.php @@ -124,6 +124,7 @@ class UserDefinedChannel extends \Friendica\BaseRepository 'exclude-tags' => $Channel->excludeTags, 'full-text-search' => $Channel->fullTextSearch, 'media-type' => $Channel->mediaType, + 'languages' => serialize($Channel->languages), ]; if ($Channel->code) { diff --git a/src/Module/Conversation/Timeline.php b/src/Module/Conversation/Timeline.php index bc4c87ce55..1fdc9e0603 100644 --- a/src/Module/Conversation/Timeline.php +++ b/src/Module/Conversation/Timeline.php @@ -312,10 +312,10 @@ class Timeline extends BaseModule } elseif ($this->selectedTab == ChannelEntity::LANGUAGE) { $condition = ["JSON_EXTRACT(JSON_KEYS(language), '$[0]') = ?", User::getLanguageCode($uid)]; } elseif (is_numeric($this->selectedTab)) { - $condition = $this->getUserChannelConditions($this->selectedTab, $this->session->getLocalUserId()); + $condition = $this->getUserChannelConditions($this->selectedTab, $uid); } - if ($this->selectedTab != ChannelEntity::LANGUAGE) { + if (($this->selectedTab != ChannelEntity::LANGUAGE) && !is_numeric($this->selectedTab)) { $condition = $this->addLanguageCondition($uid, $condition); } @@ -422,13 +422,15 @@ class Timeline extends BaseModule } // For "addLanguageCondition" to work, the condition must not be empty - return $condition ?: ["true"]; + $condition = $this->addLanguageCondition($uid, $condition ?: ["true"], $channel->languages); + + return $condition; } - private function addLanguageCondition(int $uid, array $condition): array + private function addLanguageCondition(int $uid, array $condition, $languages = null): array { $conditions = []; - $languages = User::getWantedLanguages($uid); + $languages = $languages ?: User::getWantedLanguages($uid); foreach ($languages as $language) { $conditions[] = "JSON_EXTRACT(JSON_KEYS(language), '$[0]') = ?"; $condition[] = $language; diff --git a/src/Module/Settings/Channels.php b/src/Module/Settings/Channels.php index 47074d3e09..aef8527775 100644 --- a/src/Module/Settings/Channels.php +++ b/src/Module/Settings/Channels.php @@ -28,6 +28,7 @@ use Friendica\Core\L10n; use Friendica\Core\Renderer; use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Model\Circle; +use Friendica\Model\User; use Friendica\Module\BaseSettings; use Friendica\Module\Response; use Friendica\Network\HTTPException; @@ -62,7 +63,13 @@ class Channels extends BaseSettings self::checkFormSecurityTokenRedirectOnError('/settings/channels', 'settings_channels'); + $channel_languages = User::getWantedLanguages($uid); + if (!empty($request['add_channel'])) { + if (!array_diff((array)$request['new_languages'], $channel_languages)) { + $request['new_languages'] = null; + } + $channel = $this->userDefinedChannel->createFromTableRow([ 'label' => $request['new_label'], 'description' => $request['new_description'], @@ -73,6 +80,7 @@ class Channels extends BaseSettings 'exclude-tags' => $this->cleanTags($request['new_exclude_tags']), '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'], ]); $saved = $this->channel->save($channel); $this->logger->debug('New channel added', ['saved' => $saved]); @@ -86,6 +94,10 @@ class Channels extends BaseSettings continue; } + if (!array_diff((array)$request['languages'][$id], $channel_languages)) { + $request['languages'][$id] = null; + } + $channel = $this->userDefinedChannel->createFromTableRow([ 'id' => $id, 'label' => $request['label'][$id], @@ -97,6 +109,7 @@ class Channels extends BaseSettings 'exclude-tags' => $this->cleanTags($request['exclude_tags'][$id]), '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], ]); $saved = $this->channel->save($channel); $this->logger->debug('Save channel', ['id' => $id, 'saved' => $saved]); @@ -123,6 +136,9 @@ class Channels extends BaseSettings $circles[$circle['id']] = $circle['name']; } + $languages = $this->l10n->getLanguageCodes(true); + $channel_languages = User::getWantedLanguages($uid); + $channels = []; foreach ($this->channel->selectByUid($uid) as $channel) { if (!empty($request['id'])) { @@ -146,6 +162,7 @@ class Channels extends BaseSettings 'image' => ["image[$channel->code]", $this->t("Images"), $channel->mediaType & 1], 'video' => ["video[$channel->code]", $this->t("Videos"), $channel->mediaType & 2], '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.'), $languages, 'multiple'], 'delete' => ["delete[$channel->code]", $this->t("Delete channel") . ' (' . $channel->label . ')', false, $this->t("Check to delete this entry from the channel list")] ]; } @@ -163,6 +180,7 @@ class Channels extends BaseSettings 'image' => ['new_image', $this->t("Images"), false, $this->t("Check to display images in the channel.")], 'video' => ["new_video", $this->t("Videos"), false, $this->t("Check to display videos in the channel.")], 'audio' => ["new_audio", $this->t("Audio"), false, $this->t("Check to display audio in the channel.")], + 'languages' => ["new_languages[]", $this->t('Languages'), $channel_languages, $this->t('Select all languages that you want to see in this channel.'), $languages, 'multiple'], '$l10n' => [ 'title' => $this->t('Channels'), 'intro' => $this->t('This page can be used to define your own channels.'), diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index 31a9dcd85b..5265232366 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -56,7 +56,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', 1544); + define('DB_UPDATE_VERSION', 1545); } return [ @@ -564,6 +564,7 @@ return [ "exclude-tags" => ["type" => "varchar(1023)", "comment" => "Comma separated list of tags that aren't allowed in the channel"], "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"], ], "indexes" => [ "PRIMARY" => ["id"], diff --git a/view/templates/settings/channels.tpl b/view/templates/settings/channels.tpl index 27defffdb0..2af3f67fdb 100644 --- a/view/templates/settings/channels.tpl +++ b/view/templates/settings/channels.tpl @@ -14,7 +14,8 @@ {{include file="field_checkbox.tpl" field=$image}} {{include file="field_checkbox.tpl" field=$video}} {{include file="field_checkbox.tpl" field=$audio}} -