From b720ade440f12087ca2987f28196145759492bb2 Mon Sep 17 00:00:00 2001 From: Yi-Jyun Pan Date: Mon, 11 Nov 2024 23:33:54 +0800 Subject: [PATCH 01/18] feat(profile): Implement editable-feature feature flag --- config/services.yaml | 2 ++ src/Controller/ProfileController.php | 17 +++++++++++++++++ templates/profile/index.html.twig | 2 ++ 3 files changed, 21 insertions(+) diff --git a/config/services.yaml b/config/services.yaml index b4f0f26..28e72d6 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -8,6 +8,8 @@ parameters: app.redis_uri: "%env(REDIS_URI)%" app.openai_api_key: "%env(OPENAI_API_KEY)%" + app.features.editable-profile: true + services: # default configuration for services in *this* file _defaults: diff --git a/src/Controller/ProfileController.php b/src/Controller/ProfileController.php index e007028..ffc4b97 100644 --- a/src/Controller/ProfileController.php +++ b/src/Controller/ProfileController.php @@ -19,11 +19,20 @@ class ProfileController extends AbstractController { + public function isProfileEditable(): bool + { + $isProfileEditable = $this->getParameter('app.features.editable-profile'); + \assert(\is_bool($isProfileEditable)); + + return $isProfileEditable; + } + #[Route('/profile', name: 'app_profile')] public function index(#[CurrentUser] User $user): Response { return $this->render('profile/index.html.twig', [ 'user' => $user, + 'isProfileEditable' => $this->isProfileEditable(), ]); } @@ -35,6 +44,10 @@ public function editPassword( Request $request, #[CurrentUser] User $user, ): Response { + if (!$this->isProfileEditable()) { + throw $this->createNotFoundException('Feature "Editable Profile" is disabled.'); + } + $passwordChangeModel = new PasswordChangeModel(); $passwordChangeForm = $formFactory->createBuilder(PasswordChangeFormType::class, $passwordChangeModel) ->setAction($this->generateUrl('app_profile_edit_password')) @@ -66,6 +79,10 @@ public function editUsername( Request $request, #[CurrentUser] User $user, ): Response { + if (!$this->isProfileEditable()) { + throw $this->createNotFoundException('Feature "Editable Profile" is disabled.'); + } + $usernameChangeForm = $formFactory->createBuilder(NameChangeFormType::class, $user) ->setAction($this->generateUrl('app_profile_edit_username')) ->getForm(); diff --git a/templates/profile/index.html.twig b/templates/profile/index.html.twig index f05a4ae..3f00154 100644 --- a/templates/profile/index.html.twig +++ b/templates/profile/index.html.twig @@ -47,6 +47,7 @@ + {% if isProfileEditable %}

更新帳號資訊

@@ -64,5 +65,6 @@
+ {% endif %} {% endblock %} From 386dd17b13d1651f74b0569fdc0fd155aafa5e88 Mon Sep 17 00:00:00 2001 From: Yi-Jyun Pan Date: Mon, 11 Nov 2024 23:45:22 +0800 Subject: [PATCH 02/18] feat(challenge): Implement "Hint" feature flag --- config/packages/twig.yaml | 2 ++ config/services.yaml | 1 + src/Twig/Components/Challenge/Instruction/Modal.php | 10 ++++++++++ templates/components/Challenge/Ui.html.twig | 8 ++++++-- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/config/packages/twig.yaml b/config/packages/twig.yaml index a058436..253f984 100644 --- a/config/packages/twig.yaml +++ b/config/packages/twig.yaml @@ -4,6 +4,8 @@ twig: globals: umami_domain: "%env(UMAMI_DOMAIN)%" umami_website_id: "%env(UMAMI_WEBSITE_ID)%" + appfeatures: + hint: "%app.features.hint%" when@test: twig: diff --git a/config/services.yaml b/config/services.yaml index 28e72d6..30100c0 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -8,6 +8,7 @@ parameters: app.redis_uri: "%env(REDIS_URI)%" app.openai_api_key: "%env(OPENAI_API_KEY)%" + app.features.hint: true app.features.editable-profile: true services: diff --git a/src/Twig/Components/Challenge/Instruction/Modal.php b/src/Twig/Components/Challenge/Instruction/Modal.php index d91f420..b2c91a2 100644 --- a/src/Twig/Components/Challenge/Instruction/Modal.php +++ b/src/Twig/Components/Challenge/Instruction/Modal.php @@ -11,6 +11,8 @@ use App\Service\PointCalculationService; use App\Service\PromptService; use Doctrine\ORM\EntityManagerInterface; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; +use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\Serializer\SerializerInterface; use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\UX\LiveComponent\Attribute\AsLiveComponent; @@ -51,7 +53,15 @@ public function instruct( TranslatorInterface $translator, SerializerInterface $serializer, EntityManagerInterface $entityManager, + ParameterBagInterface $parameterBag, ): void { + $appFeatureHint = $parameterBag->get('app.features.hint'); + \assert(\is_bool($appFeatureHint)); + + if (!$appFeatureHint) { + throw new BadRequestHttpException('Hint feature is disabled.'); + } + if ('' === $this->query) { return; } diff --git a/templates/components/Challenge/Ui.html.twig b/templates/components/Challenge/Ui.html.twig index 33ced52..6e82e24 100644 --- a/templates/components/Challenge/Ui.html.twig +++ b/templates/components/Challenge/Ui.html.twig @@ -3,7 +3,9 @@ {% if question.solutionVideo %} {% endif %} - + {% if appfeatures.hint %} + + {% endif %}
@@ -13,7 +15,9 @@
- + {% if appfeatures.hint %} + + {% endif %} {% if question.solutionVideo %} {% endif %} From 512262bce74a92d2403394a834dc1d1367e4ae59 Mon Sep 17 00:00:00 2001 From: Yi-Jyun Pan Date: Mon, 11 Nov 2024 23:59:13 +0800 Subject: [PATCH 03/18] feat(challenge): Implement "Comment" feature flag --- config/packages/twig.yaml | 1 + config/services.yaml | 1 + .../Challenge/CommentModule/CommentForm.php | 11 ++++++++- .../components/Challenge/Comment.html.twig | 24 ++++++++++--------- templates/components/Challenge/Ui.html.twig | 10 ++++---- 5 files changed, 31 insertions(+), 16 deletions(-) diff --git a/config/packages/twig.yaml b/config/packages/twig.yaml index 253f984..4af147b 100644 --- a/config/packages/twig.yaml +++ b/config/packages/twig.yaml @@ -6,6 +6,7 @@ twig: umami_website_id: "%env(UMAMI_WEBSITE_ID)%" appfeatures: hint: "%app.features.hint%" + comment: "%app.features.comment%" when@test: twig: diff --git a/config/services.yaml b/config/services.yaml index 30100c0..f8450f0 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -10,6 +10,7 @@ parameters: app.features.hint: true app.features.editable-profile: true + app.features.comment: true services: # default configuration for services in *this* file diff --git a/src/Twig/Components/Challenge/CommentModule/CommentForm.php b/src/Twig/Components/Challenge/CommentModule/CommentForm.php index ae99741..ab3e2bf 100644 --- a/src/Twig/Components/Challenge/CommentModule/CommentForm.php +++ b/src/Twig/Components/Challenge/CommentModule/CommentForm.php @@ -9,8 +9,10 @@ use App\Entity\User as UserEntity; use App\Form\CommentCreateFormType; use Doctrine\ORM\EntityManagerInterface; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\Form\FormInterface; +use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\UX\LiveComponent\Attribute\AsLiveComponent; use Symfony\UX\LiveComponent\Attribute\LiveAction; use Symfony\UX\LiveComponent\Attribute\LiveProp; @@ -52,8 +54,15 @@ protected function instantiateForm(): FormInterface } #[LiveAction] - public function save(EntityManagerInterface $entityManager): void + public function save(EntityManagerInterface $entityManager, ParameterBagInterface $parameterBag): void { + $appFeatureComment = $parameterBag->get('app.features.comment'); + \assert(\is_bool($appFeatureComment)); + + if (!$appFeatureComment) { + throw new BadRequestHttpException('Comment feature is disabled.'); + } + $this->submitForm(); $comment = $this->getForm()->getData(); diff --git a/templates/components/Challenge/Comment.html.twig b/templates/components/Challenge/Comment.html.twig index 2dc225a..247b677 100644 --- a/templates/components/Challenge/Comment.html.twig +++ b/templates/components/Challenge/Comment.html.twig @@ -1,13 +1,15 @@ -
-
- -
+
+ {% if appfeatures.comment %} +
+ +
-
- {% for comment in this.comments %} - - {% else %} -
尚無留言。成為第一個留言者吧!
- {% endfor %} -
+
+ {% for comment in this.comments %} + + {% else %} +
尚無留言。成為第一個留言者吧!
+ {% endfor %} +
+ {% endif %}
diff --git a/templates/components/Challenge/Ui.html.twig b/templates/components/Challenge/Ui.html.twig index 6e82e24..bad595c 100644 --- a/templates/components/Challenge/Ui.html.twig +++ b/templates/components/Challenge/Ui.html.twig @@ -35,9 +35,11 @@
-
-

留言區

- -
+ {% if appfeatures.comment %} +
+

留言區

+ +
+ {% endif %}
From f3c6a32dd14990e42ed07af7885cea403f448fd6 Mon Sep 17 00:00:00 2001 From: Yi-Jyun Pan Date: Mon, 11 Nov 2024 23:33:54 +0800 Subject: [PATCH 04/18] feat(profile): Implement "Editable Profile" feature flag --- config/services.yaml | 2 ++ src/Controller/ProfileController.php | 17 +++++++++++++++++ templates/profile/index.html.twig | 2 ++ 3 files changed, 21 insertions(+) diff --git a/config/services.yaml b/config/services.yaml index b4f0f26..28e72d6 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -8,6 +8,8 @@ parameters: app.redis_uri: "%env(REDIS_URI)%" app.openai_api_key: "%env(OPENAI_API_KEY)%" + app.features.editable-profile: true + services: # default configuration for services in *this* file _defaults: diff --git a/src/Controller/ProfileController.php b/src/Controller/ProfileController.php index e007028..ffc4b97 100644 --- a/src/Controller/ProfileController.php +++ b/src/Controller/ProfileController.php @@ -19,11 +19,20 @@ class ProfileController extends AbstractController { + public function isProfileEditable(): bool + { + $isProfileEditable = $this->getParameter('app.features.editable-profile'); + \assert(\is_bool($isProfileEditable)); + + return $isProfileEditable; + } + #[Route('/profile', name: 'app_profile')] public function index(#[CurrentUser] User $user): Response { return $this->render('profile/index.html.twig', [ 'user' => $user, + 'isProfileEditable' => $this->isProfileEditable(), ]); } @@ -35,6 +44,10 @@ public function editPassword( Request $request, #[CurrentUser] User $user, ): Response { + if (!$this->isProfileEditable()) { + throw $this->createNotFoundException('Feature "Editable Profile" is disabled.'); + } + $passwordChangeModel = new PasswordChangeModel(); $passwordChangeForm = $formFactory->createBuilder(PasswordChangeFormType::class, $passwordChangeModel) ->setAction($this->generateUrl('app_profile_edit_password')) @@ -66,6 +79,10 @@ public function editUsername( Request $request, #[CurrentUser] User $user, ): Response { + if (!$this->isProfileEditable()) { + throw $this->createNotFoundException('Feature "Editable Profile" is disabled.'); + } + $usernameChangeForm = $formFactory->createBuilder(NameChangeFormType::class, $user) ->setAction($this->generateUrl('app_profile_edit_username')) ->getForm(); diff --git a/templates/profile/index.html.twig b/templates/profile/index.html.twig index f05a4ae..3f00154 100644 --- a/templates/profile/index.html.twig +++ b/templates/profile/index.html.twig @@ -47,6 +47,7 @@ + {% if isProfileEditable %}

更新帳號資訊

@@ -64,5 +65,6 @@
+ {% endif %} {% endblock %} From c6e3edf46a1932e4e0e37da2cd189f4f4aacd998 Mon Sep 17 00:00:00 2001 From: Yi-Jyun Pan Date: Mon, 11 Nov 2024 23:45:22 +0800 Subject: [PATCH 05/18] feat(challenge): Implement "Hint" feature flag --- config/packages/twig.yaml | 2 ++ config/services.yaml | 1 + src/Twig/Components/Challenge/Instruction/Modal.php | 10 ++++++++++ templates/components/Challenge/Ui.html.twig | 8 ++++++-- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/config/packages/twig.yaml b/config/packages/twig.yaml index a058436..253f984 100644 --- a/config/packages/twig.yaml +++ b/config/packages/twig.yaml @@ -4,6 +4,8 @@ twig: globals: umami_domain: "%env(UMAMI_DOMAIN)%" umami_website_id: "%env(UMAMI_WEBSITE_ID)%" + appfeatures: + hint: "%app.features.hint%" when@test: twig: diff --git a/config/services.yaml b/config/services.yaml index 28e72d6..30100c0 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -8,6 +8,7 @@ parameters: app.redis_uri: "%env(REDIS_URI)%" app.openai_api_key: "%env(OPENAI_API_KEY)%" + app.features.hint: true app.features.editable-profile: true services: diff --git a/src/Twig/Components/Challenge/Instruction/Modal.php b/src/Twig/Components/Challenge/Instruction/Modal.php index d91f420..b2c91a2 100644 --- a/src/Twig/Components/Challenge/Instruction/Modal.php +++ b/src/Twig/Components/Challenge/Instruction/Modal.php @@ -11,6 +11,8 @@ use App\Service\PointCalculationService; use App\Service\PromptService; use Doctrine\ORM\EntityManagerInterface; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; +use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\Serializer\SerializerInterface; use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\UX\LiveComponent\Attribute\AsLiveComponent; @@ -51,7 +53,15 @@ public function instruct( TranslatorInterface $translator, SerializerInterface $serializer, EntityManagerInterface $entityManager, + ParameterBagInterface $parameterBag, ): void { + $appFeatureHint = $parameterBag->get('app.features.hint'); + \assert(\is_bool($appFeatureHint)); + + if (!$appFeatureHint) { + throw new BadRequestHttpException('Hint feature is disabled.'); + } + if ('' === $this->query) { return; } diff --git a/templates/components/Challenge/Ui.html.twig b/templates/components/Challenge/Ui.html.twig index 33ced52..6e82e24 100644 --- a/templates/components/Challenge/Ui.html.twig +++ b/templates/components/Challenge/Ui.html.twig @@ -3,7 +3,9 @@ {% if question.solutionVideo %} {% endif %} - + {% if appfeatures.hint %} + + {% endif %}
@@ -13,7 +15,9 @@
- + {% if appfeatures.hint %} + + {% endif %} {% if question.solutionVideo %} {% endif %} From ed45df5a5bd1345c49dd5bff44dbd096efe9ab97 Mon Sep 17 00:00:00 2001 From: Yi-Jyun Pan Date: Mon, 11 Nov 2024 23:59:13 +0800 Subject: [PATCH 06/18] feat(challenge): Implement "Comment" feature flag --- config/packages/twig.yaml | 1 + config/services.yaml | 1 + .../Challenge/CommentModule/CommentForm.php | 11 ++++++++- .../components/Challenge/Comment.html.twig | 24 ++++++++++--------- templates/components/Challenge/Ui.html.twig | 10 ++++---- 5 files changed, 31 insertions(+), 16 deletions(-) diff --git a/config/packages/twig.yaml b/config/packages/twig.yaml index 253f984..4af147b 100644 --- a/config/packages/twig.yaml +++ b/config/packages/twig.yaml @@ -6,6 +6,7 @@ twig: umami_website_id: "%env(UMAMI_WEBSITE_ID)%" appfeatures: hint: "%app.features.hint%" + comment: "%app.features.comment%" when@test: twig: diff --git a/config/services.yaml b/config/services.yaml index 30100c0..f8450f0 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -10,6 +10,7 @@ parameters: app.features.hint: true app.features.editable-profile: true + app.features.comment: true services: # default configuration for services in *this* file diff --git a/src/Twig/Components/Challenge/CommentModule/CommentForm.php b/src/Twig/Components/Challenge/CommentModule/CommentForm.php index ae99741..ab3e2bf 100644 --- a/src/Twig/Components/Challenge/CommentModule/CommentForm.php +++ b/src/Twig/Components/Challenge/CommentModule/CommentForm.php @@ -9,8 +9,10 @@ use App\Entity\User as UserEntity; use App\Form\CommentCreateFormType; use Doctrine\ORM\EntityManagerInterface; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\Form\FormInterface; +use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\UX\LiveComponent\Attribute\AsLiveComponent; use Symfony\UX\LiveComponent\Attribute\LiveAction; use Symfony\UX\LiveComponent\Attribute\LiveProp; @@ -52,8 +54,15 @@ protected function instantiateForm(): FormInterface } #[LiveAction] - public function save(EntityManagerInterface $entityManager): void + public function save(EntityManagerInterface $entityManager, ParameterBagInterface $parameterBag): void { + $appFeatureComment = $parameterBag->get('app.features.comment'); + \assert(\is_bool($appFeatureComment)); + + if (!$appFeatureComment) { + throw new BadRequestHttpException('Comment feature is disabled.'); + } + $this->submitForm(); $comment = $this->getForm()->getData(); diff --git a/templates/components/Challenge/Comment.html.twig b/templates/components/Challenge/Comment.html.twig index 2dc225a..247b677 100644 --- a/templates/components/Challenge/Comment.html.twig +++ b/templates/components/Challenge/Comment.html.twig @@ -1,13 +1,15 @@ -
-
- -
+
+ {% if appfeatures.comment %} +
+ +
-
- {% for comment in this.comments %} - - {% else %} -
尚無留言。成為第一個留言者吧!
- {% endfor %} -
+
+ {% for comment in this.comments %} + + {% else %} +
尚無留言。成為第一個留言者吧!
+ {% endfor %} +
+ {% endif %}
diff --git a/templates/components/Challenge/Ui.html.twig b/templates/components/Challenge/Ui.html.twig index 6e82e24..bad595c 100644 --- a/templates/components/Challenge/Ui.html.twig +++ b/templates/components/Challenge/Ui.html.twig @@ -35,9 +35,11 @@
-
-

留言區

- -
+ {% if appfeatures.comment %} +
+

留言區

+ +
+ {% endif %}
From 790353caf1fd00365b1013cea32f6b9b134823f7 Mon Sep 17 00:00:00 2001 From: Yi-Jyun Pan Date: Tue, 12 Nov 2024 00:10:53 +0800 Subject: [PATCH 07/18] feat(comments): Disable the overview page if comment is disabled --- src/Controller/CommentsController.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Controller/CommentsController.php b/src/Controller/CommentsController.php index c249c9e..8cee2a1 100644 --- a/src/Controller/CommentsController.php +++ b/src/Controller/CommentsController.php @@ -28,6 +28,10 @@ class CommentsController extends AbstractController #[Route('/', name: '')] public function index(#[CurrentUser] User $user, CommentRepository $commentRepository): Response { + if (!$this->isCommentFeatureEnabled()) { + throw $this->createNotFoundException('"Comment" feature is disabled.'); + } + $comments = $commentRepository->findUserComments($user); $likes = array_reduce($comments, fn (int $carry, Comment $comment) => $carry + $comment->getCommentLikeEvents()->count(), 0); @@ -47,6 +51,10 @@ public function likes( ChartBuilderInterface $chartBuilder, TranslatorInterface $translator, ): Response { + if (!$this->isCommentFeatureEnabled()) { + throw $this->createNotFoundException('"Comment" feature is disabled.'); + } + $q = $commentRepository->createQueryBuilder('c') ->select('c.id AS id, COUNT(cle.id) AS count') ->leftJoin('c.commentLikeEvents', 'cle') @@ -88,4 +96,14 @@ public function likes( 'chart' => $chart, ]); } + + private function isCommentFeatureEnabled(): bool + { + $comment = $this->getParameter('app.features.comment'); + if (!\is_bool($comment)) { + throw new \RuntimeException('The "app.features.comment" parameter must be a boolean.'); + } + + return $comment; + } } From 383d78fa0b2bf4b905e4dcfba5dee5b7d8d51f21 Mon Sep 17 00:00:00 2001 From: Yi-Jyun Pan Date: Tue, 12 Nov 2024 00:11:22 +0800 Subject: [PATCH 08/18] feat(navbar): Hide comment page if "Comment" feature is disabled --- templates/components/Navbar.html.twig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/templates/components/Navbar.html.twig b/templates/components/Navbar.html.twig index 612aa68..0d9bc31 100644 --- a/templates/components/Navbar.html.twig +++ b/templates/components/Navbar.html.twig @@ -6,26 +6,30 @@ name: '學習概況', icon: 'bi bi-bar-chart-fill', path: path('app_overview'), + disabled: false, }, { pageId: 'questions', name: '練習題目', icon: 'bi bi-pencil-fill', path: path('app_questions'), + disabled: false, }, { pageId: 'comments', name: '留言一覽', icon: 'bi bi-chat-left-text-fill', path: path('app_comments'), + disabled: not appfeatures.comment, }, { pageId: 'complementary', name: '補充資料', icon: 'bi bi-book-fill', path: path('app_complementary'), + disabled: false, }, -] %} +]|filter(el => not el.disabled) %}
From d4f069a062a6d894d66ba05b23c774d377a604b0 Mon Sep 17 00:00:00 2001 From: Yi-Jyun Pan Date: Tue, 12 Nov 2024 00:13:00 +0800 Subject: [PATCH 09/18] feat(challenge): Do not instruct users to comment if "Comment" is disabled --- .../Challenge/ResultPresenterModule/AnswerPresenter.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/components/Challenge/ResultPresenterModule/AnswerPresenter.html.twig b/templates/components/Challenge/ResultPresenterModule/AnswerPresenter.html.twig index c3e7cf1..bbe3335 100644 --- a/templates/components/Challenge/ResultPresenterModule/AnswerPresenter.html.twig +++ b/templates/components/Challenge/ResultPresenterModule/AnswerPresenter.html.twig @@ -3,7 +3,7 @@ {% if not this.result.answer %} {% if this.result.same %} {% else %}