diff --git a/.env b/.env index f983b7d..be151e5 100644 --- a/.env +++ b/.env @@ -56,6 +56,8 @@ APP_THEME=default APP_THEMES=default APP_SENSITIVE=0 +APP_APPROVED=0 +APP_YGGDRASIL=1 APP_TRACKERS=http://[201:23b4:991a:634d:8359:4521:5576:15b7]:2023/announce|http://[200:1e2f:e608:eb3a:2bf:1e62:87ba:e2f7]/announce|http://[316:c51a:62a3:8b9::5]/announce diff --git a/config/services.yaml b/config/services.yaml index b76b546..65372d7 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -6,12 +6,14 @@ parameters: app.version: '%env(APP_VERSION)%' app.name: '%env(APP_NAME)%' - app.locale: '%env(APP_LOCALE)%' + app.trackers: '%env(APP_TRACKERS)%' app.locales: '%env(APP_LOCALES)%' - app.theme: '%env(APP_THEME)%' app.themes: '%env(APP_THEMES)%' + app.locale: '%env(APP_LOCALE)%' + app.theme: '%env(APP_THEME)%' app.sensitive: '%env(APP_SENSITIVE)%' - app.trackers: '%env(APP_TRACKERS)%' + app.approved: '%env(APP_APPROVED)%' + app.yggdrasil: '%env(APP_YGGDRASIL)%' app.article.title.length.min: '%env(APP_ARTICLE_TITLE_LENGTH_MIN)%' app.article.title.length.max: '%env(APP_ARTICLE_TITLE_LENGTH_MAX)%' app.article.description.length.min: '%env(APP_ARTICLE_DESCRIPTION_LENGTH_MIN)%' diff --git a/public/asset/default/css/common.css b/public/asset/default/css/common.css index f13371c..ab8b9d6 100644 --- a/public/asset/default/css/common.css +++ b/public/asset/default/css/common.css @@ -111,6 +111,7 @@ textarea:hover { td { padding: 2px 0; + vertical-align: top; } header a.logo { diff --git a/public/asset/default/css/framework.css b/public/asset/default/css/framework.css index 395ece6..7349b72 100644 --- a/public/asset/default/css/framework.css +++ b/public/asset/default/css/framework.css @@ -367,6 +367,10 @@ a:visited.background-color-hover-night-light:hover { margin-right: 4px; } +.margin-b-4-px { + margin-bottom: 4px; +} + .margin-r-4-px { margin-right: 4px; } diff --git a/src/Controller/ArticleController.php b/src/Controller/ArticleController.php index 8de58e4..cac30ae 100644 --- a/src/Controller/ArticleController.php +++ b/src/Controller/ArticleController.php @@ -29,7 +29,6 @@ class ArticleController extends AbstractController )] public function info( Request $request, - TranslatorInterface $translator, UserService $userService, ActivityService $activityService ): Response @@ -263,7 +262,11 @@ class ArticleController extends AbstractController time(), $this->getParameter('app.locale'), explode('|', $this->getParameter('app.locales')), - $this->getParameter('app.theme') + $activityService->getEventCodes(), + $this->getParameter('app.theme'), + $this->getParameter('app.sensitive'), + $this->getParameter('app.yggdrasil'), + $this->getParameter('app.approved') ); // Add user join event diff --git a/src/Controller/SearchController.php b/src/Controller/SearchController.php index b8fea89..54e7723 100644 --- a/src/Controller/SearchController.php +++ b/src/Controller/SearchController.php @@ -164,7 +164,11 @@ class SearchController extends AbstractController time(), $this->getParameter('app.locale'), explode('|', $this->getParameter('app.locales')), - $this->getParameter('app.theme') + $activityService->getEventCodes(), + $this->getParameter('app.theme'), + $this->getParameter('app.sensitive'), + $this->getParameter('app.yggdrasil'), + $this->getParameter('app.approved') ); // Add user join event diff --git a/src/Controller/TorrentController.php b/src/Controller/TorrentController.php index 03d882c..db3a941 100644 --- a/src/Controller/TorrentController.php +++ b/src/Controller/TorrentController.php @@ -1155,11 +1155,14 @@ class TorrentController extends AbstractController ); // Filter trackers - $file->setAnnounceList( - [ - explode('|', $this->getParameter('app.trackers')) - ] - ); + if ($user->isYggdrasil()) + { + $file->setAnnounceList( + [ + explode('|', $this->getParameter('app.trackers')) + ] + ); + } $data = $file->dumpToString(); @@ -1260,11 +1263,14 @@ class TorrentController extends AbstractController ); // Filter trackers - $file->setAnnounceList( - [ - explode('|', $this->getParameter('app.trackers')) - ] - ); + if ($user->isYggdrasil()) + { + $file->setAnnounceList( + [ + explode('|', $this->getParameter('app.trackers')) + ] + ); + } // Return magnet link return $this->redirect( @@ -1308,7 +1314,11 @@ class TorrentController extends AbstractController time(), $this->getParameter('app.locale'), explode('|', $this->getParameter('app.locales')), - $this->getParameter('app.theme') + $activityService->getEventCodes(), + $this->getParameter('app.theme'), + $this->getParameter('app.sensitive'), + $this->getParameter('app.yggdrasil'), + $this->getParameter('app.approved') ); // Add user join event diff --git a/src/Controller/UserController.php b/src/Controller/UserController.php index ff080e5..4bb1146 100644 --- a/src/Controller/UserController.php +++ b/src/Controller/UserController.php @@ -63,8 +63,8 @@ class UserController extends AbstractController } #[Route( - '/{_locale}/profile', - name: 'user_profile', + '/{_locale}/settings', + name: 'user_settings', defaults: [ '_locale' => '%app.locale%' ], @@ -72,7 +72,7 @@ class UserController extends AbstractController '_locale' => '%app.locales%', ], )] - public function profile( + public function settings( Request $request, UserService $userService, ActivityService $activityService @@ -121,17 +121,36 @@ class UserController extends AbstractController ); } + // Update events + $events = []; + foreach ((array) $request->get('events') as $event) + { + if (in_array($event, $activityService->getEventCodes())) + { + $events[] = $event; + } + } + + $user->setEvents( + $events + ); + // Update sensitive $user->setSensitive( $request->get('sensitive') === 'true' ); + // Update yggdrasil + $user->setYggdrasil( + $request->get('yggdrasil') === 'true' + ); + // Save changes to DB $userService->save($user); // Redirect user to new locale return $this->redirectToRoute( - 'user_profile', + 'user_settings', [ '_locale' => $user->getLocale() ] @@ -140,38 +159,35 @@ class UserController extends AbstractController // Render template return $this->render( - 'default/user/profile.html.twig', + 'default/user/settings.html.twig', [ 'user' => [ 'id' => $user->getId(), - 'address' => $request->getClientIp() == $user->getAddress() ? $user->getAddress() : false, - 'moderator' => $user->isModerator(), - 'approved' => $user->isApproved(), - 'status' => $user->isStatus(), 'sensitive' => $user->isSensitive(), + 'yggdrasil' => $user->isYggdrasil(), 'locale' => $user->getLocale(), 'locales' => $user->getLocales(), + 'events' => $user->getEvents(), 'theme' => $user->getTheme(), - 'added' => $user->getAdded(), - 'identicon' => $userService->identicon( - $user->getAddress(), - 48 - ), + 'added' => $user->getAdded() ], 'locales' => explode('|', $this->getParameter('app.locales')), - 'themes' => explode('|', $this->getParameter('app.themes')) + 'themes' => explode('|', $this->getParameter('app.themes')), + 'events' => $activityService->getEventsTree() ] ); } #[Route( - '/{_locale}/user/{userId}', + '/{_locale}/profile/{userId}', name: 'user_info', defaults: [ - '_locale' => '%app.locale%' + '_locale' => '%app.locale%', + 'userId' => null ], requirements: [ '_locale' => '%app.locales%', + 'userId' => '\d+', ], )] public function info( @@ -197,7 +213,9 @@ class UserController extends AbstractController } // Init target user - if (!$userTarget = $userService->getUser($request->get('userId'))) + if (!$userTarget = $userService->getUser( + $request->get('userId') ? $request->get('userId') : $user->getId() + )) { throw $this->createNotFoundException(); } @@ -208,13 +226,15 @@ class UserController extends AbstractController [ 'user' => [ 'id' => $userTarget->getId(), - 'address' => $request->getClientIp() == $userTarget->getAddress() ? $userTarget->getAddress() : false, + 'address' => $userTarget->getId() === $user->getId() ? $userTarget->getAddress() : false, 'moderator' => $userTarget->isModerator(), 'approved' => $userTarget->isApproved(), 'status' => $userTarget->isStatus(), 'sensitive' => $userTarget->isSensitive(), + 'yggdrasil' => $userTarget->isYggdrasil(), 'locale' => $userTarget->getLocale(), 'locales' => $userTarget->getLocales(), + 'events' => $userTarget->getEvents(), 'theme' => $userTarget->getTheme(), 'added' => $userTarget->getAdded(), 'identicon' => $userService->identicon( @@ -232,7 +252,8 @@ class UserController extends AbstractController $userTarget->getId() ) ], - ] + ], + 'events' => $activityService->getEventsTree() ] ); } @@ -587,7 +608,11 @@ class UserController extends AbstractController time(), $this->getParameter('app.locale'), explode('|', $this->getParameter('app.locales')), - $this->getParameter('app.theme') + $activityService->getEventCodes(), + $this->getParameter('app.theme'), + $this->getParameter('app.sensitive'), + $this->getParameter('app.yggdrasil'), + $this->getParameter('app.approved') ); // Add user join event diff --git a/src/Entity/User.php b/src/Entity/User.php index f727c8f..56246d5 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -35,12 +35,18 @@ class User #[ORM\Column(type: Types::ARRAY)] private array $locales = []; + #[ORM\Column(type: Types::ARRAY)] + private array $events = []; + #[ORM\Column(length: 255)] private ?string $theme = null; #[ORM\Column] private ?bool $sensitive = null; + #[ORM\Column] + private ?bool $yggdrasil = null; + public function getId(): ?int { return $this->id; @@ -137,6 +143,18 @@ class User return $this; } + public function getEvents(): array + { + return $this->events; + } + + public function setEvents(array $events): static + { + $this->events = $events; + + return $this; + } + public function getTheme(): ?string { return $this->theme; @@ -160,4 +178,16 @@ class User return $this; } + + public function isYggdrasil(): ?bool + { + return $this->yggdrasil; + } + + public function setYggdrasil(bool $yggdrasil): static + { + $this->yggdrasil = $yggdrasil; + + return $this; + } } diff --git a/src/Service/ActivityService.php b/src/Service/ActivityService.php index 44dd9bf..e0f48f3 100644 --- a/src/Service/ActivityService.php +++ b/src/Service/ActivityService.php @@ -5,16 +5,359 @@ namespace App\Service; use App\Entity\Activity; use App\Repository\ActivityRepository; use Doctrine\ORM\EntityManagerInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class ActivityService { private EntityManagerInterface $entityManagerInterface; + private TranslatorInterface $translatorInterface; public function __construct( - EntityManagerInterface $entityManagerInterface + EntityManagerInterface $entityManagerInterface, + TranslatorInterface $translatorInterface ) { $this->entityManagerInterface = $entityManagerInterface; + $this->translatorInterface = $translatorInterface; + } + + public function getEventCodes(): array + { + return + [ + // User + Activity::EVENT_USER_ADD, + + Activity::EVENT_USER_APPROVE_ADD, + Activity::EVENT_USER_APPROVE_DELETE, + + Activity::EVENT_USER_MODERATOR_ADD, + Activity::EVENT_USER_MODERATOR_DELETE, + + Activity::EVENT_USER_STATUS_ADD, + Activity::EVENT_USER_STATUS_DELETE, + + Activity::EVENT_USER_STAR_ADD, + Activity::EVENT_USER_STAR_DELETE, + + // Torrents + Activity::EVENT_TORRENT_ADD, + + Activity::EVENT_TORRENT_LOCALES_ADD, + Activity::EVENT_TORRENT_LOCALES_DELETE, + Activity::EVENT_TORRENT_LOCALES_APPROVE_ADD, + Activity::EVENT_TORRENT_LOCALES_APPROVE_DELETE, + + Activity::EVENT_TORRENT_SENSITIVE_ADD, + Activity::EVENT_TORRENT_SENSITIVE_DELETE, + Activity::EVENT_TORRENT_SENSITIVE_APPROVE_ADD, + Activity::EVENT_TORRENT_SENSITIVE_APPROVE_DELETE, + + Activity::EVENT_TORRENT_STAR_ADD, + Activity::EVENT_TORRENT_STAR_DELETE, + + Activity::EVENT_TORRENT_DOWNLOAD_FILE_ADD, + Activity::EVENT_TORRENT_DOWNLOAD_MAGNET_ADD, + + // Articles + Activity::EVENT_ARTICLE_ADD, + ]; + } + + public function getEventsTree(): array + { + $events = []; + + foreach ($this->getEventCodes() as $code) + { + switch ($code) + { + // User + case Activity::EVENT_USER_ADD: + + $events + [ + $this->translatorInterface->trans('Users') + ] + [ + $this->translatorInterface->trans('Joined') + ] = $code; + + break; + + /// User approve + case Activity::EVENT_USER_APPROVE_ADD: + + $events + [ + $this->translatorInterface->trans('Users') + ] + [ + $this->translatorInterface->trans('Approved') + ] = $code; + + break; + + case Activity::EVENT_USER_APPROVE_DELETE: + + $events + [ + $this->translatorInterface->trans('Users') + ] + [ + $this->translatorInterface->trans('Disapproved') + ] = $code; + break; + + /// User status + case Activity::EVENT_USER_STATUS_ADD: + + $events + [ + $this->translatorInterface->trans('User statuses') + ] + [ + $this->translatorInterface->trans('Enabled') + ] = $code; + + break; + + case Activity::EVENT_USER_STATUS_DELETE: + + $events + [ + $this->translatorInterface->trans('User statuses') + ] + [ + $this->translatorInterface->trans('Disabled') + ] = $code; + break; + + /// User moderator + case Activity::EVENT_USER_MODERATOR_ADD: + + $events + [ + $this->translatorInterface->trans('User moderators') + ] + [ + $this->translatorInterface->trans('Added') + ] = $code; + + break; + + case Activity::EVENT_USER_MODERATOR_DELETE: + + $events + [ + $this->translatorInterface->trans('User moderators') + ] + [ + $this->translatorInterface->trans('Removed') + ] = $code; + break; + + /// User star + case Activity::EVENT_USER_STAR_ADD: + + $events + [ + $this->translatorInterface->trans('User stars') + ] + [ + $this->translatorInterface->trans('Added') + ] = $code; + + break; + + case Activity::EVENT_USER_STAR_DELETE: + + $events + [ + $this->translatorInterface->trans('User stars') + ] + [ + $this->translatorInterface->trans('Removed') + ] = $code; + break; + + // Torrent + case Activity::EVENT_TORRENT_ADD: + + $events + [ + $this->translatorInterface->trans('Torrents') + ] + [ + $this->translatorInterface->trans('Added') + ] = $code; + + break; + + /// Torrent locales + case Activity::EVENT_TORRENT_LOCALES_ADD: + + $events + [ + $this->translatorInterface->trans('Torrent locales') + ] + [ + $this->translatorInterface->trans('Added') + ] = $code; + + break; + + case Activity::EVENT_TORRENT_LOCALES_DELETE: + + $events + [ + $this->translatorInterface->trans('Torrent locales') + ] + [ + $this->translatorInterface->trans('Deleted') + ] = $code; + + break; + + case Activity::EVENT_TORRENT_LOCALES_APPROVE_ADD: + + $events + [ + $this->translatorInterface->trans('Torrent locales') + ] + [ + $this->translatorInterface->trans('Approved') + ] = $code; + + break; + + case Activity::EVENT_TORRENT_LOCALES_APPROVE_DELETE: + + $events + [ + $this->translatorInterface->trans('Torrent locales') + ] + [ + $this->translatorInterface->trans('Disapproved') + ] = $code; + + break; + + /// Torrent sensitive + case Activity::EVENT_TORRENT_SENSITIVE_ADD: + + $events + [ + $this->translatorInterface->trans('Torrent sensitive') + ] + [ + $this->translatorInterface->trans('Added') + ] = $code; + + break; + + case Activity::EVENT_TORRENT_SENSITIVE_DELETE: + + $events + [ + $this->translatorInterface->trans('Torrent sensitive') + ] + [ + $this->translatorInterface->trans('Deleted') + ] = $code; + + break; + + case Activity::EVENT_TORRENT_SENSITIVE_APPROVE_ADD: + + $events + [ + $this->translatorInterface->trans('Torrent sensitive') + ] + [ + $this->translatorInterface->trans('Approved') + ] = $code; + + break; + + case Activity::EVENT_TORRENT_SENSITIVE_APPROVE_DELETE: + + $events + [ + $this->translatorInterface->trans('Torrent sensitive') + ] + [ + $this->translatorInterface->trans('Disapproved') + ] = $code; + + break; + + /// Torrent stars + case Activity::EVENT_TORRENT_STAR_ADD: + + $events + [ + $this->translatorInterface->trans('Torrent stars') + ] + [ + $this->translatorInterface->trans('Added') + ] = $code; + + break; + + case Activity::EVENT_TORRENT_STAR_DELETE: + + $events + [ + $this->translatorInterface->trans('Torrent stars') + ] + [ + $this->translatorInterface->trans('Removed') + ] = $code; + + break; + + /// Torrent downloads + case Activity::EVENT_TORRENT_DOWNLOAD_FILE_ADD: + + $events + [ + $this->translatorInterface->trans('Torrent downloads') + ] + [ + $this->translatorInterface->trans('Files') + ] = $code; + + break; + + case Activity::EVENT_TORRENT_DOWNLOAD_MAGNET_ADD: + + $events + [ + $this->translatorInterface->trans('Torrent downloads') + ] + [ + $this->translatorInterface->trans('Magnet links') + ] = $code; + + break; + + // Article + case Activity::EVENT_TORRENT_ADD: + + $events + [ + $this->translatorInterface->trans('Articles') + ] + [ + $this->translatorInterface->trans('Added') + ] = $code; + + break; + } + } + + return $events; } public function findLastActivities(): array diff --git a/src/Service/UserService.php b/src/Service/UserService.php index 179f358..2459d5d 100644 --- a/src/Service/UserService.php +++ b/src/Service/UserService.php @@ -28,8 +28,10 @@ class UserService string $added, string $locale, array $locales, + array $events, string $theme, bool $sensitive = true, + bool $yggdrasil = true, bool $approved = false, bool $moderator = false, bool $status = true @@ -70,10 +72,18 @@ class UserService $theme ); + $user->setEvents( + $events + ); + $user->setSensitive( $sensitive ); + $user->setYggdrasil( + $yggdrasil + ); + $this->entityManagerInterface->persist($user); $this->entityManagerInterface->flush(); diff --git a/templates/default/user/info.html.twig b/templates/default/user/info.html.twig index 70897e1..93dceea 100644 --- a/templates/default/user/info.html.twig +++ b/templates/default/user/info.html.twig @@ -33,12 +33,33 @@ {{ 'Common'|trans }} + {% if user.address %} + + {{ 'Address' | trans }} + + {{ user.address }} + + + + + + + + + + + + {{ 'Joined' | trans }} + {{ user.added | format_ago }} + + {% else %} + + {{ 'Joined' | trans }} + {{ user.added | format_ago }} + + {% endif %} - {{ 'Joined'|trans }} - {{ user.added | format_ago }} - - - {{ 'Access'|trans }} + {{ 'Access' | trans }} @@ -121,7 +142,7 @@ {% if user.owner %} - + @@ -132,37 +153,66 @@ - {{ 'Interface' | trans }} + {{ 'Theme' | trans }} + {{ user.theme | u.title }} + + + + + {{ 'Interface' | trans }} + + {{ user.locale | locale_name(user.locale) | u.title }} - {{ 'Content'|trans }} + + {{ 'Languages' | trans }} + {% for i, locale in user.locales %}{% if i > 0 %},{% endif %} {{ locale|locale_name(locale)|u.title }}{% endfor %} - {# - {% for locale in user.locales %} -
- {{ locale|locale_name(locale)|u.title }} -
- {% endfor %} - #} - {{ 'Theme'|trans }} - {{ user.theme | u.title }} + + {{ 'Sensitive' | trans }} + + + {% if user.sensitive %} + {{ 'Yes' | trans }} + {% else %} + {{ 'No' | trans }} + {% endif %} + - {{ 'Sensitive'|trans }} - {% if user.sensitive %} - {{ 'Yes'|trans }} - {% else %} - {{ 'No'|trans }} - {% endif %} + {{ 'Events subscribed' | trans }} + + + {% for group, event in events %} +
+ + {{ group }}: + + {% set i = 0 %} + {% for key, value in event %}{% if value in user.events %}{% if i > 0 %}, {% endif %}{{ key | lower }}{% set i = i + 1 %}{% endif %}{% endfor %} +
+ {% endfor %} + + + + + {{ 'Yggdrasil filter' | trans }} + + + {% if user.yggdrasil %} + {{ 'Yes'|trans }} + {% else %} + {{ 'No'|trans }} + {% endif %} diff --git a/templates/default/user/module.html.twig b/templates/default/user/module.html.twig index d3a9cf8..7b023c5 100644 --- a/templates/default/user/module.html.twig +++ b/templates/default/user/module.html.twig @@ -6,25 +6,38 @@ {% else %} -
+ {% endif %} - {% if route == 'user_profile' %} + {% if route == 'user_info' %} {% else %} - + {% endif %} + {% if route == 'user_settings' %} + + + + + + {% else %} + + + + + + {% endif %} {% if route == 'article_submit' or route == 'torrent_submit' %} @@ -32,7 +45,7 @@ {% else %} - + diff --git a/templates/default/user/profile.html.twig b/templates/default/user/settings.html.twig similarity index 57% rename from templates/default/user/profile.html.twig rename to templates/default/user/settings.html.twig index 49d3dd4..74b6082 100644 --- a/templates/default/user/profile.html.twig +++ b/templates/default/user/settings.html.twig @@ -1,77 +1,38 @@ {% extends 'default/layout.html.twig' %} -{% block title %}{{ 'Profile'|trans }} - {{ name }}{% endblock %} +{% block title %}{{ 'Settings' | trans }} - {{ name }}{% endblock %} {% block main_content %}
-
- -

{{ 'Profile'|trans }}

+ +

{{ 'Settings' | trans }}

- - - - - - - - - - - - - - - - - - - - - - - - - + - - + + + - - - - - + + + + {% for group, event in events %} + + + + + {% endfor %} + + + + + + +
{{ 'Common'|trans }}
{{ 'Address'|trans }} - {{ user.address }} - - - - - - - - + + {{ 'Interface' | trans }}
{{ 'Joined' | trans }}{{ user.added | format_ago }}
{{ 'Access'|trans }}
{{ 'Status'|trans }} - {% if user.status %} - {{ 'Aactive' | trans }} - {% else %} - {{ 'Disabled' | trans }} - {% endif %} -
{{ 'Approved'|trans }} - {% if user.approved %} - {{ 'Yes' | trans }} - {% else %} - {{ 'No' | trans }} - {% endif %} -
{{ 'Moderator' | trans }} - {% if user.moderator %} - {{ 'Yes' | trans }} - {% else %} - {{ 'No' | trans }} - {% endif %} + {{ 'Theme' | trans }}
- {{ 'Settings' | trans }} + +
{{ 'Interface'|trans }}{{ 'Language' | trans }}
- {{ 'Content language' | trans }} + + {{ 'Search' | trans }} +
+ {{ 'Languages' | trans }} + {% for locale in locales %}
{% if locale in user.locales %} @@ -108,31 +74,11 @@
- {{ 'Theme' | trans }} - - -
- {{ 'Sensitive filter'|trans }} + + {{ 'Sensitive' | trans }} -
+
{% if user.sensitive %} {% else %} @@ -141,6 +87,49 @@
+ {{ 'Events' | trans }} +
+ {{ group }} + + {% for key, value in event %} + + {% if value in user.events %} + + {% else %} + + {% endif %} + + + {% endfor %} +
+ {{ 'Downloads' | trans }} +
+ {{ 'Yggdrasil filter' | trans }} + + {% if user.yggdrasil %} + + {% else %} + + {% endif %} +