feat: stores user's media preferences
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
"ext-iconv": "*",
|
"ext-iconv": "*",
|
||||||
"1tomany/rich-bundle": "^1.8",
|
"1tomany/rich-bundle": "^1.8",
|
||||||
|
"aimeos/map": "^3.12",
|
||||||
"doctrine/dbal": "^3",
|
"doctrine/dbal": "^3",
|
||||||
"doctrine/doctrine-bundle": "^2.14",
|
"doctrine/doctrine-bundle": "^2.14",
|
||||||
"doctrine/doctrine-migrations-bundle": "^3.4",
|
"doctrine/doctrine-migrations-bundle": "^3.4",
|
||||||
|
|||||||
55
composer.lock
generated
55
composer.lock
generated
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "1b5e4263ced36558032c50f1d8f7f4fb",
|
"content-hash": "e0322cfec0023bee458190f38b4cab8c",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "1tomany/data-uri",
|
"name": "1tomany/data-uri",
|
||||||
@@ -122,6 +122,59 @@
|
|||||||
},
|
},
|
||||||
"time": "2025-04-14T20:49:47+00:00"
|
"time": "2025-04-14T20:49:47+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "aimeos/map",
|
||||||
|
"version": "3.12.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/aimeos/map.git",
|
||||||
|
"reference": "3cb4aff05a92cc47a45a7488094b945370b83381"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/aimeos/map/zipball/3cb4aff05a92cc47a45a7488094b945370b83381",
|
||||||
|
"reference": "3cb4aff05a92cc47a45a7488094b945370b83381",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"ext-pcre": "*",
|
||||||
|
"php": "^7.1||^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"php-coveralls/php-coveralls": "~2.0",
|
||||||
|
"phpunit/phpunit": "~7.0||~8.0||~9.0",
|
||||||
|
"squizlabs/php_codesniffer": "^3.5"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"src/function.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Aimeos\\": "src/"
|
||||||
|
},
|
||||||
|
"classmap": [
|
||||||
|
"src/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"description": "Easy and elegant handling of PHP arrays as array-like collection objects similar to jQuery and Laravel Collections",
|
||||||
|
"keywords": [
|
||||||
|
"array",
|
||||||
|
"collection",
|
||||||
|
"map",
|
||||||
|
"php"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/aimeos/map/issues",
|
||||||
|
"source": "https://github.com/aimeos/map/tree/3.12.0"
|
||||||
|
},
|
||||||
|
"time": "2025-03-05T09:16:18+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "composer/semver",
|
"name": "composer/semver",
|
||||||
"version": "3.4.3",
|
"version": "3.4.3",
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ security:
|
|||||||
# Easy way to control access for large sections of your site
|
# Easy way to control access for large sections of your site
|
||||||
# Note: Only the *first* access control that matches will be used
|
# Note: Only the *first* access control that matches will be used
|
||||||
access_control:
|
access_control:
|
||||||
|
- { path: ^/register, roles: PUBLIC_ACCESS }
|
||||||
- { path: ^/login, roles: PUBLIC_ACCESS }
|
- { path: ^/login, roles: PUBLIC_ACCESS }
|
||||||
- { path: ^/, roles: ROLE_USER } # Or ROLE_ADMIN, ROLE_SUPER_ADMIN,
|
- { path: ^/, roles: ROLE_USER } # Or ROLE_ADMIN, ROLE_SUPER_ADMIN,
|
||||||
|
|
||||||
|
|||||||
47
migrations/Version20250429032311.php
Normal file
47
migrations/Version20250429032311.php
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20250429032311 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
CREATE TABLE user_preference (id INT AUTO_INCREMENT NOT NULL, user_id INT NOT NULL, preference_id VARCHAR(255) NOT NULL, preference_value VARCHAR(255) DEFAULT NULL, INDEX IDX_FA0E76BFA76ED395 (user_id), INDEX IDX_FA0E76BFD81022C0 (preference_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB
|
||||||
|
SQL);
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
ALTER TABLE user_preference ADD CONSTRAINT FK_FA0E76BFA76ED395 FOREIGN KEY (user_id) REFERENCES user (id)
|
||||||
|
SQL);
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
ALTER TABLE user_preference ADD CONSTRAINT FK_FA0E76BFD81022C0 FOREIGN KEY (preference_id) REFERENCES preference (id)
|
||||||
|
SQL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
ALTER TABLE user_preference DROP FOREIGN KEY FK_FA0E76BFA76ED395
|
||||||
|
SQL);
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
ALTER TABLE user_preference DROP FOREIGN KEY FK_FA0E76BFD81022C0
|
||||||
|
SQL);
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
DROP TABLE user_preference
|
||||||
|
SQL);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,15 +4,47 @@ namespace App\User\Action\Handler;
|
|||||||
|
|
||||||
use App\User\Action\Command\SaveUserMediaPreferencesCommand;
|
use App\User\Action\Command\SaveUserMediaPreferencesCommand;
|
||||||
use App\User\Action\Result\SaveUserMediaPreferencesResult;
|
use App\User\Action\Result\SaveUserMediaPreferencesResult;
|
||||||
|
use App\User\Framework\Entity\User;
|
||||||
|
use App\User\Framework\Entity\UserPreference;
|
||||||
|
use App\User\Framework\Repository\PreferencesRepository;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use OneToMany\RichBundle\Contract\CommandInterface as C;
|
use OneToMany\RichBundle\Contract\CommandInterface as C;
|
||||||
use OneToMany\RichBundle\Contract\HandlerInterface;
|
use OneToMany\RichBundle\Contract\HandlerInterface;
|
||||||
use OneToMany\RichBundle\Contract\ResultInterface as R;
|
use OneToMany\RichBundle\Contract\ResultInterface as R;
|
||||||
|
use Symfony\Bundle\SecurityBundle\Security;
|
||||||
|
|
||||||
/** @implements HandlerInterface<SaveUserMediaPreferencesCommand> */
|
/** @implements HandlerInterface<SaveUserMediaPreferencesCommand> */
|
||||||
class SaveUserMediaPreferencesHandler implements HandlerInterface
|
class SaveUserMediaPreferencesHandler implements HandlerInterface
|
||||||
{
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly EntityManagerInterface $entityManager,
|
||||||
|
private readonly PreferencesRepository $preferenceRepository,
|
||||||
|
private readonly Security $token,
|
||||||
|
) {}
|
||||||
|
|
||||||
public function handle(C $command): R
|
public function handle(C $command): R
|
||||||
{
|
{
|
||||||
return new SaveUserMediaPreferencesResult('Success');
|
/** @var User $user */
|
||||||
|
$user = $this->token->getUser();
|
||||||
|
|
||||||
|
foreach ($command as $preference => $value) {
|
||||||
|
if ($user->hasUserPreference($preference)) {
|
||||||
|
$user->updateUserPreference($preference, $value);
|
||||||
|
$this->entityManager->flush();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$preference = $this->preferenceRepository->find($preference);
|
||||||
|
$user->addUserPreference(
|
||||||
|
(new UserPreference())
|
||||||
|
->setUser($user)
|
||||||
|
->setPreference($preference)
|
||||||
|
->setPreferenceValue($value)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
return new SaveUserMediaPreferencesResult($user->getUserPreferences());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ namespace App\User\Action\Input;
|
|||||||
|
|
||||||
use App\User\Action\Command\SaveUserMediaPreferencesCommand;
|
use App\User\Action\Command\SaveUserMediaPreferencesCommand;
|
||||||
use OneToMany\RichBundle\Attribute\SourceRequest;
|
use OneToMany\RichBundle\Attribute\SourceRequest;
|
||||||
|
use OneToMany\RichBundle\Attribute\SourceSecurity;
|
||||||
use OneToMany\RichBundle\Contract\CommandInterface as C;
|
use OneToMany\RichBundle\Contract\CommandInterface as C;
|
||||||
use OneToMany\RichBundle\Contract\InputInterface;
|
use OneToMany\RichBundle\Contract\InputInterface;
|
||||||
|
|
||||||
@@ -11,6 +12,9 @@ use OneToMany\RichBundle\Contract\InputInterface;
|
|||||||
class SaveUserMediaPreferencesInput implements InputInterface
|
class SaveUserMediaPreferencesInput implements InputInterface
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
#[SourceSecurity]
|
||||||
|
public mixed $userId,
|
||||||
|
|
||||||
#[SourceRequest('resolution')]
|
#[SourceRequest('resolution')]
|
||||||
public string $resolution,
|
public string $resolution,
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,13 @@
|
|||||||
|
|
||||||
namespace App\User\Action\Result;
|
namespace App\User\Action\Result;
|
||||||
|
|
||||||
|
use Doctrine\Common\Collections\Collection;
|
||||||
use OneToMany\RichBundle\Contract\ResultInterface;
|
use OneToMany\RichBundle\Contract\ResultInterface;
|
||||||
|
|
||||||
/** @implements ResultInterface */
|
/** @implements ResultInterface */
|
||||||
class SaveUserMediaPreferencesResult implements ResultInterface
|
class SaveUserMediaPreferencesResult implements ResultInterface
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public string $status,
|
public Collection $userPreferences,
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
@@ -4,10 +4,15 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\User\Framework\Controller\Web;
|
namespace App\User\Framework\Controller\Web;
|
||||||
|
|
||||||
|
use Aimeos\Map;
|
||||||
|
use App\User\Action\Handler\SaveUserMediaPreferencesHandler;
|
||||||
use App\User\Action\Input\SaveUserMediaPreferencesInput;
|
use App\User\Action\Input\SaveUserMediaPreferencesInput;
|
||||||
|
use App\User\Framework\Entity\User;
|
||||||
|
use App\User\Framework\Entity\UserPreference;
|
||||||
use App\User\Framework\Repository\PreferencesRepository;
|
use App\User\Framework\Repository\PreferencesRepository;
|
||||||
use App\Util\CountryCodes;
|
use App\Util\CountryCodes;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Bundle\SecurityBundle\Security;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Routing\Attribute\Route;
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
|
|
||||||
@@ -15,16 +20,29 @@ class PreferencesController extends AbstractController
|
|||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly PreferencesRepository $preferencesRepository,
|
private readonly PreferencesRepository $preferencesRepository,
|
||||||
|
private readonly SaveUserMediaPreferencesHandler $saveUserMediaPreferencesHandler,
|
||||||
|
private readonly Security $security,
|
||||||
) {}
|
) {}
|
||||||
#[Route('/media/preferences', 'app_media_preferences', methods: ['GET'])]
|
#[Route('/media/preferences', 'app_media_preferences', methods: ['GET'])]
|
||||||
public function mediaPreferences(): Response
|
public function mediaPreferences(): Response
|
||||||
{
|
{
|
||||||
|
$enabledPreferences = $this->preferencesRepository->findEnabled();
|
||||||
|
|
||||||
|
if ($this->security->getUser()->getUserPreferences()->count() !== count($enabledPreferences)) {
|
||||||
|
$this->setUserPreferences($this->security->getUser(), $enabledPreferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
$userPreferences = $this->security->getUser()->getUserPreferences()->toArray();
|
||||||
|
$userPreferences = Map::from($userPreferences)
|
||||||
|
->rekey(fn($preference) => $preference->getPreference()->getId());
|
||||||
|
|
||||||
return $this->render(
|
return $this->render(
|
||||||
'user/preferences.html.twig',
|
'user/preferences.html.twig',
|
||||||
[
|
[
|
||||||
'preferences' => $this->preferencesRepository->findEnabled(),
|
'preferences' => $this->preferencesRepository->findEnabled(),
|
||||||
'languages' => CountryCodes::$countries,
|
'languages' => CountryCodes::$countries,
|
||||||
'providers' => ['test' => 'Test'],
|
'providers' => ['test' => 'Test'],
|
||||||
|
'userPreferences' => $userPreferences->toArray(),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -34,12 +52,31 @@ class PreferencesController extends AbstractController
|
|||||||
SaveUserMediaPreferencesInput $input,
|
SaveUserMediaPreferencesInput $input,
|
||||||
): Response
|
): Response
|
||||||
{
|
{
|
||||||
dd($input);
|
$userPreferences = $this->saveUserMediaPreferencesHandler->handle($input->toCommand())->userPreferences;
|
||||||
|
$userPreferences = Map::from($userPreferences)->rekey(fn($preference) => $preference->getPreference()->getId());
|
||||||
|
|
||||||
return $this->render(
|
return $this->render(
|
||||||
'user/preferences.html.twig',
|
'user/preferences.html.twig',
|
||||||
[
|
[
|
||||||
'preferences' => $this->preferencesRepository->findEnabled(),
|
'preferences' => $this->preferencesRepository->findEnabled(),
|
||||||
|
'languages' => CountryCodes::$countries,
|
||||||
|
'providers' => ['test' => 'Test'],
|
||||||
|
'userPreferences' => $userPreferences->toArray(),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function setUserPreferences(User $user, array $preferences): void
|
||||||
|
{
|
||||||
|
foreach ($preferences as $preference) {
|
||||||
|
if (false === $user->hasUserPreference($preference->getId())) {
|
||||||
|
$user->addUserPreference((new UserPreference())
|
||||||
|
->setUser($user)
|
||||||
|
->setPreference($preference)
|
||||||
|
->setPreferenceValue(null)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->preferencesRepository->getEntityManager()->flush();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,9 @@
|
|||||||
namespace App\User\Framework\Controller\Web;
|
namespace App\User\Framework\Controller\Web;
|
||||||
|
|
||||||
use App\User\Framework\Entity\User;
|
use App\User\Framework\Entity\User;
|
||||||
|
use App\User\Framework\Entity\UserPreference;
|
||||||
use App\User\Framework\Form\RegistrationFormType;
|
use App\User\Framework\Form\RegistrationFormType;
|
||||||
|
use App\User\Framework\Repository\PreferencesRepository;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
@@ -14,8 +16,12 @@ use Symfony\Component\Routing\Attribute\Route;
|
|||||||
class RegistrationController extends AbstractController
|
class RegistrationController extends AbstractController
|
||||||
{
|
{
|
||||||
#[Route('/register', name: 'app_register')]
|
#[Route('/register', name: 'app_register')]
|
||||||
public function register(Request $request, UserPasswordHasherInterface $userPasswordHasher, EntityManagerInterface $entityManager): Response
|
public function register(
|
||||||
{
|
Request $request,
|
||||||
|
UserPasswordHasherInterface $userPasswordHasher,
|
||||||
|
EntityManagerInterface $entityManager,
|
||||||
|
PreferencesRepository $preferencesRepository,
|
||||||
|
): Response {
|
||||||
$user = new User();
|
$user = new User();
|
||||||
$form = $this->createForm(RegistrationFormType::class, $user);
|
$form = $this->createForm(RegistrationFormType::class, $user);
|
||||||
$form->handleRequest($request);
|
$form->handleRequest($request);
|
||||||
@@ -30,7 +36,9 @@ class RegistrationController extends AbstractController
|
|||||||
$entityManager->persist($user);
|
$entityManager->persist($user);
|
||||||
$entityManager->flush();
|
$entityManager->flush();
|
||||||
|
|
||||||
// do anything else you need here, like send an email
|
$this->setUserPreferences($user, $preferencesRepository->findEnabled());
|
||||||
|
|
||||||
|
$preferencesRepository->getEntityManager()->flush();
|
||||||
|
|
||||||
return $this->redirectToRoute('app_index');
|
return $this->redirectToRoute('app_index');
|
||||||
}
|
}
|
||||||
@@ -39,4 +47,15 @@ class RegistrationController extends AbstractController
|
|||||||
'registrationForm' => $form,
|
'registrationForm' => $form,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function setUserPreferences(User $user, array $preferences): void
|
||||||
|
{
|
||||||
|
foreach ($preferences as $preference) {
|
||||||
|
$user->addUserPreference((new UserPreference())
|
||||||
|
->setUser($user)
|
||||||
|
->setPreference($preference)
|
||||||
|
->setPreferenceValue(null)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class Preference
|
|||||||
/**
|
/**
|
||||||
* @var Collection<int, PreferenceOption>
|
* @var Collection<int, PreferenceOption>
|
||||||
*/
|
*/
|
||||||
#[ORM\OneToMany(targetEntity: PreferenceOption::class, mappedBy: 'preference')]
|
#[ORM\OneToMany(targetEntity: PreferenceOption::class, mappedBy: 'preference', fetch: 'EAGER')]
|
||||||
private Collection $preferenceOptions;
|
private Collection $preferenceOptions;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
|
|||||||
@@ -2,13 +2,17 @@
|
|||||||
|
|
||||||
namespace App\User\Framework\Entity;
|
namespace App\User\Framework\Entity;
|
||||||
|
|
||||||
|
use App\User\Framework\Repository\PreferencesRepository;
|
||||||
use App\User\Framework\Repository\UserRepository;
|
use App\User\Framework\Repository\UserRepository;
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
use Doctrine\Common\Collections\Collection;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||||
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
|
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
|
||||||
use Symfony\Component\Security\Core\User\UserInterface;
|
use Symfony\Component\Security\Core\User\UserInterface;
|
||||||
|
|
||||||
#[ORM\Entity(repositoryClass: UserRepository::class)]
|
#[ORM\Entity(repositoryClass: UserRepository::class)]
|
||||||
|
#[ORM\HasLifecycleCallbacks]
|
||||||
#[UniqueEntity(fields: ['email'], message: 'There is already an account with this email')]
|
#[UniqueEntity(fields: ['email'], message: 'There is already an account with this email')]
|
||||||
class User implements UserInterface, PasswordAuthenticatedUserInterface
|
class User implements UserInterface, PasswordAuthenticatedUserInterface
|
||||||
{
|
{
|
||||||
@@ -29,6 +33,17 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
|||||||
#[ORM\Column(type: 'string')]
|
#[ORM\Column(type: 'string')]
|
||||||
private string $password;
|
private string $password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Collection<int, UserPreference>
|
||||||
|
*/
|
||||||
|
#[ORM\OneToMany(targetEntity: UserPreference::class, mappedBy: 'user', cascade: ['persist', 'remove'])]
|
||||||
|
private Collection $userPreferences;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->userPreferences = new ArrayCollection();
|
||||||
|
}
|
||||||
|
|
||||||
public function getId(): ?int
|
public function getId(): ?int
|
||||||
{
|
{
|
||||||
return $this->id;
|
return $this->id;
|
||||||
@@ -110,4 +125,63 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
|||||||
// If you store any temporary, sensitive data on the user, clear it here
|
// If you store any temporary, sensitive data on the user, clear it here
|
||||||
// $this->plainPassword = null;
|
// $this->plainPassword = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Collection<int, UserPreference>
|
||||||
|
*/
|
||||||
|
public function getUserPreferences(): Collection
|
||||||
|
{
|
||||||
|
return $this->userPreferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUserPreference(string $preferenceName)
|
||||||
|
{
|
||||||
|
foreach ($this->userPreferences as $userPreference) {
|
||||||
|
if ($userPreference->getPreference()->getName() === $preferenceName) {
|
||||||
|
return $userPreference->getPreference();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasUserPreference(string $preferenceName): bool
|
||||||
|
{
|
||||||
|
foreach ($this->userPreferences as $userPreference) {
|
||||||
|
if ($userPreference->getPreference()->getId() === $preferenceName) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updateUserPreference(string $preferenceName, mixed $preferenceValue): static
|
||||||
|
{
|
||||||
|
foreach ($this->userPreferences as $userPreference) {
|
||||||
|
if ($userPreference->getPreference()->getId() === $preferenceName) {
|
||||||
|
$userPreference->setPreferenceValue($preferenceValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addUserPreference(UserPreference $userPreference): static
|
||||||
|
{
|
||||||
|
if (!$this->userPreferences->contains($userPreference)) {
|
||||||
|
$this->userPreferences->add($userPreference);
|
||||||
|
$userPreference->setUser($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function removeUserPreference(UserPreference $userPreference): static
|
||||||
|
{
|
||||||
|
if ($this->userPreferences->removeElement($userPreference)) {
|
||||||
|
// set the owning side to null (unless already changed)
|
||||||
|
if ($userPreference->getUser() === $this) {
|
||||||
|
$userPreference->setUser(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
67
src/User/Framework/Entity/UserPreference.php
Normal file
67
src/User/Framework/Entity/UserPreference.php
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\User\Framework\Entity;
|
||||||
|
|
||||||
|
use App\User\Framework\Repository\UserPreferenceRepository;
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
|
#[ORM\Entity(repositoryClass: UserPreferenceRepository::class)]
|
||||||
|
class UserPreference
|
||||||
|
{
|
||||||
|
#[ORM\Id]
|
||||||
|
#[ORM\GeneratedValue]
|
||||||
|
#[ORM\Column]
|
||||||
|
private ?int $id = null;
|
||||||
|
|
||||||
|
#[ORM\ManyToOne(inversedBy: 'userPreferences')]
|
||||||
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
|
private ?User $user = null;
|
||||||
|
|
||||||
|
#[ORM\ManyToOne(fetch: 'EAGER')]
|
||||||
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
|
private ?Preference $preference = null;
|
||||||
|
|
||||||
|
#[ORM\Column(length: 255, nullable: true)]
|
||||||
|
private ?string $preference_value = null;
|
||||||
|
|
||||||
|
public function getId(): ?int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUser(): ?User
|
||||||
|
{
|
||||||
|
return $this->user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUser(?User $user): static
|
||||||
|
{
|
||||||
|
$this->user = $user;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPreference(): ?Preference
|
||||||
|
{
|
||||||
|
return $this->preference;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPreference(?Preference $preference): static
|
||||||
|
{
|
||||||
|
$this->preference = $preference;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPreferenceValue(): ?string
|
||||||
|
{
|
||||||
|
return $this->preference_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPreferenceValue(?string $preference_value): static
|
||||||
|
{
|
||||||
|
$this->preference_value = $preference_value;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
||||||
43
src/User/Framework/Repository/UserPreferenceRepository.php
Normal file
43
src/User/Framework/Repository/UserPreferenceRepository.php
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\User\Framework\Repository;
|
||||||
|
|
||||||
|
use App\User\Framework\Entity\UserPreference;
|
||||||
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||||
|
use Doctrine\Persistence\ManagerRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends ServiceEntityRepository<UserPreference>
|
||||||
|
*/
|
||||||
|
class UserPreferenceRepository extends ServiceEntityRepository
|
||||||
|
{
|
||||||
|
public function __construct(ManagerRegistry $registry)
|
||||||
|
{
|
||||||
|
parent::__construct($registry, UserPreference::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findUserPreferences(int $userId): array
|
||||||
|
{
|
||||||
|
return $this->findBy(['userId' => $userId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findUserResolution(int $userId): ?UserPreference
|
||||||
|
{
|
||||||
|
return $this->findOneBy(['userId' => $userId, 'preference' => 'resolution']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findUserCodec(int $userId): ?UserPreference
|
||||||
|
{
|
||||||
|
return $this->findOneBy(['userId' => $userId, 'preference' => 'codec']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findUserLanguage(int $userId): ?UserPreference
|
||||||
|
{
|
||||||
|
return $this->findOneBy(['userId' => $userId, 'preference' => 'language']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findUserProvider(int $userId): ?UserPreference
|
||||||
|
{
|
||||||
|
return $this->findOneBy(['userId' => $userId, 'preference' => 'resolution']);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
href="#"
|
href="{{ path('app_media_preferences') }}"
|
||||||
class="block rounded-lg px-4 py-2 text-sm font-medium text-gray-50 hover:bg-gray-100 hover:text-stone-700"
|
class="block rounded-lg px-4 py-2 text-sm font-medium text-gray-50 hover:bg-gray-100 hover:text-stone-700"
|
||||||
>
|
>
|
||||||
Preferences
|
Preferences
|
||||||
|
|||||||
@@ -7,29 +7,48 @@
|
|||||||
<twig:Card title="Choose your preferences">
|
<twig:Card title="Choose your preferences">
|
||||||
<p class="text-gray-50 mb-2">Define a set of filters to apply to your media download option results.</p>
|
<p class="text-gray-50 mb-2">Define a set of filters to apply to your media download option results.</p>
|
||||||
<form id="media_preferences" class="flex flex-col max-w-64" name="media_preferences" method="post" action="{{ path('app_media_preferences') }}">
|
<form id="media_preferences" class="flex flex-col max-w-64" name="media_preferences" method="post" action="{{ path('app_media_preferences') }}">
|
||||||
{% for preference in preferences %}
|
|
||||||
<label class="text-gray-50" for="{{ preference.name }}">{{ preference.name }}</label>
|
|
||||||
|
|
||||||
{% if preference.name|lower == "language" %}
|
<label class="text-gray-50" for="resolution">Resolution</label>
|
||||||
<select class="p-1.5 rounded-md mb-2" name="{{ preference.name|lower }}" id="{{ preference.name }}">
|
<select class="p-1.5 rounded-md mb-2" name="resolution" id="resolution" value="{{ userPreferences['resolution'].getPreferenceValue() }}">
|
||||||
{% for key, value in languages %}
|
{% for pref in userPreferences['resolution'].getPreference().getPreferenceOptions() %}
|
||||||
<option class="text-gray-800" value="{{ key }}">{{ value }}</option>
|
<option class="text-gray-800"
|
||||||
{% endfor %}
|
value="{{ pref.id }}"
|
||||||
</select>
|
{{ pref.id == userPreferences['resolution'].getPreferenceValue() ? "selected" }}
|
||||||
{% elseif preference.name|lower == "provider" %}
|
>{{ pref.name }}</option>
|
||||||
<select class="p-1.5 rounded-md mb-2" name="{{ preference.name|lower }}" id="{{ preference.name }}">
|
{% endfor %}
|
||||||
{% for key, value in providers %}
|
</select>
|
||||||
<option class="text-gray-800" value="{{ key }}">{{ value }}</option>
|
|
||||||
{% endfor %}
|
<label class="text-gray-50" for="codec">Codec</label>
|
||||||
</select>
|
<select class="p-1.5 rounded-md mb-2" name="codec" id="codec" value="{{ userPreferences['codec'].getPreferenceValue() }}">
|
||||||
{% else %}
|
{% for pref in userPreferences['codec'].getPreference().getPreferenceOptions() %}
|
||||||
<select class="p-1.5 rounded-md mb-2" name="{{ preference.name|lower }}" id="{{ preference.name }}">
|
<option class="text-gray-800"
|
||||||
{% for option in preference.preferenceOptions %}
|
value="{{ pref.id }}"
|
||||||
<option class="text-gray-800" value="{{ option.id }}">{{ option.name }}</option>
|
{{ pref.id == userPreferences['codec'].getPreferenceValue() ? "selected" }}
|
||||||
{% endfor %}
|
>{{ pref.name }}</option>
|
||||||
</select>
|
{% endfor %}
|
||||||
{% endif %}
|
</select>
|
||||||
{% endfor %}
|
|
||||||
|
<label class="text-gray-50" for="provider">Provider</label>
|
||||||
|
<select class="p-1.5 rounded-md mb-2" name="provider" id="provider" value="{{ userPreferences['provider'].getPreferenceValue() }}">
|
||||||
|
{% for key, value in providers %}
|
||||||
|
<option class="text-gray-800"
|
||||||
|
value="{{ key }}"
|
||||||
|
{{ key == userPreferences['provider'].getPreferenceValue() ? "selected" }}
|
||||||
|
>{{ value }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<label class="text-gray-50" for="language">Language</label>
|
||||||
|
<select class="p-1.5 rounded-md mb-2" name="language" id="language" value="{{ userPreferences['language'].getPreferenceValue() }}">
|
||||||
|
{% for key, value in languages %}
|
||||||
|
<option class="text-gray-800"
|
||||||
|
value="{{ key }}"
|
||||||
|
{{ key == userPreferences['language'].getPreferenceValue() ? "selected" }}
|
||||||
|
>{{ value }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
<button class="px-1.5 py-1 max-w-20 rounded-md bg-green-600 text-white" type="submit">Submit</button>
|
<button class="px-1.5 py-1 max-w-20 rounded-md bg-green-600 text-white" type="submit">Submit</button>
|
||||||
</form>
|
</form>
|
||||||
</twig:Card>
|
</twig:Card>
|
||||||
|
|||||||
Reference in New Issue
Block a user