amendmentId !== $amendment->id || $comment->status !== IComment::STATUS_VISIBLE) { throw new Internal(\Yii::t('comment', 'err_not_found')); } if ($needsScreeningRights) { if (!$this->consultation->havePrivilege(Privileges::PRIVILEGE_SCREENING, null)) { throw new Internal(\Yii::t('comment', 'err_no_screening')); } } return $comment; } private function writeComment(Amendment $amendment, array &$viewParameters): void { $postComment = $this->getPostValue('comment'); $replyTo = null; if (isset($postComment['parentCommentId']) && $postComment['parentCommentId']) { $replyTo = AmendmentComment::findOne([ 'id' => $postComment['parentCommentId'], 'amendmentId' => $amendment->id, 'parentCommentId' => null, ]); if ($replyTo && $replyTo->status === IComment::STATUS_DELETED) { $replyTo = null; } } $commentForm = new CommentForm($amendment, $replyTo); $commentForm->setAttributes($this->getPostValue('comment')); $redirectUrl = null; try { $commentForm->saveNotificationSettings(); $comment = $commentForm->saveAmendmentCommentWithChecks($amendment); if ($comment->status === AmendmentComment::STATUS_SCREENING) { $this->getHttpSession()->setFlash('screening', \Yii::t('comment', 'created_needs_screening')); } else { $this->getHttpSession()->setFlash('screening', \Yii::t('comment', 'created')); } $redirectUrl = UrlHelper::createAmendmentCommentUrl($comment); } catch (\Exception $e) { $viewParameters['commentForm'] = $commentForm; if (!isset($viewParameters['openedComments'][$commentForm->sectionId])) { $viewParameters['openedComments'][$commentForm->sectionId] = []; } $viewParameters['openedComments'][$commentForm->sectionId][] = $commentForm->paragraphNo; $this->getHttpSession()->setFlash('error', $e->getMessage()); } if ($redirectUrl) { throw new ResponseException(new RedirectResponse($redirectUrl)); } } /** * @throws Internal */ private function amendmentAddTag(Amendment $amendment): void { if (!$this->consultation->havePrivilege(Privileges::PRIVILEGE_MOTION_STATUS_EDIT, PrivilegeQueryContext::amendment($amendment))) { throw new Internal(\Yii::t('comment', 'err_no_screening')); } foreach ($amendment->getMyConsultation()->getSortedTags(ConsultationSettingsTag::TYPE_PUBLIC_AMENDMENT) as $tag) { if ($tag->id === intval($this->getHttpRequest()->post('tagId'))) { $amendment->link('tags', $tag); } } } /** * @throws Internal */ private function amendmentDelTag(Amendment $amendment): void { if (!$this->consultation->havePrivilege(Privileges::PRIVILEGE_MOTION_STATUS_EDIT, PrivilegeQueryContext::amendment($amendment))) { throw new Internal(\Yii::t('comment', 'err_no_screening')); } foreach ($amendment->getMyConsultation()->getSortedTags(ConsultationSettingsTag::TYPE_PUBLIC_AMENDMENT) as $tag) { if ($tag->id === intval($this->getHttpRequest()->post('tagId'))) { $amendment->unlink('tags', $tag, true); } } } /** * @throws DB * @throws Internal */ private function deleteComment(Amendment $amendment, int $commentId): void { $comment = $this->getComment($amendment, $commentId, false); if (!$comment->canDelete(User::getCurrentUser())) { throw new Internal(\Yii::t('comment', 'err_no_del')); } $comment->status = IComment::STATUS_DELETED; if (!$comment->save(false)) { throw new DB($comment->getErrors()); } $consultation = $amendment->getMyConsultation(); ConsultationLog::logCurrUser($consultation, ConsultationLog::AMENDMENT_COMMENT_DELETE, $comment->id); $this->getHttpSession()->setFlash('success', \Yii::t('comment', 'del_done')); } /** * @throws Internal */ private function screenCommentAccept(Amendment $amendment, int $commentId): void { /** @var AmendmentComment|null $comment */ $comment = AmendmentComment::findOne($commentId); if (!$comment || $comment->amendmentId !== $amendment->id) { throw new Internal(\Yii::t('comment', 'err_not_found')); } if (!$this->consultation->havePrivilege(Privileges::PRIVILEGE_SCREENING, PrivilegeQueryContext::amendment($amendment))) { throw new Internal(\Yii::t('comment', 'err_no_screening')); } $comment->status = IComment::STATUS_VISIBLE; $comment->save(); $amendment->refresh(); $comment->trigger(IComment::EVENT_PUBLISHED); } /** * @throws Internal */ private function screenCommentReject(Amendment $amendment, int $commentId): void { /** @var AmendmentComment|null $comment */ $comment = AmendmentComment::findOne($commentId); if (!$comment || $comment->amendmentId !== $amendment->id) { throw new Internal(\Yii::t('comment', 'err_not_found')); } if (!$this->consultation->havePrivilege(Privileges::PRIVILEGE_SCREENING, null)) { throw new Internal(\Yii::t('comment', 'err_no_screening')); } $comment->status = IComment::STATUS_DELETED; $comment->save(); $amendment->refresh(); $consultation = $amendment->getMyConsultation(); ConsultationLog::logCurrUser($consultation, ConsultationLog::MOTION_COMMENT_DELETE, $comment->id); } /** * @throws Access * @throws FormError */ private function amendmentSupport(Amendment $amendment): void { $user = User::getCurrentUser(); $supportType = $amendment->getMyMotion()->motionType->getAmendmentSupportTypeClass(); $dto = SupportRequest::fromWebRequest($this->getPostValues(), $user, $supportType); if (!AmendmentSupporter::createSupportFromRequest($amendment, $user, $dto)) { $this->getHttpSession()->setFlash('success', \Yii::t('amend', 'support_already')); return; } $this->getHttpSession()->set('user_gender', $dto->gender ?? ''); $this->getHttpSession()->setFlash('success', \Yii::t('amend', 'support_done')); } /** * @throws FormError * @throws Internal */ private function amendmentLikeDislike(Amendment $amendment, string $role, string $string, string $name, string $orga = '', string $gender = '', bool $nonPublic = false): void { $currentUser = User::getCurrentUser(); if (!$amendment->getMyMotion()->motionType->getAmendmentSupportPolicy()->checkCurrUser(allowAdmins: false)) { throw new FormError('Supporting this amendment is not possible'); } AmendmentSupporter::createSupport($amendment, $currentUser, $name, $orga, $role, $gender, $nonPublic); $this->getHttpSession()->setFlash('success', $string); } /** * @throws FormError */ private function amendmentLike(Amendment $amendment): void { if (!($amendment->getLikeDislikeSettings() & SupportBase::LIKEDISLIKE_LIKE)) { throw new FormError('Not supported'); } $msg = \Yii::t('amend', 'like_done'); $name = (User::getCurrentUser() ? '' : $this->getHttpRequest()->post('likeName', '')); $this->amendmentLikeDislike($amendment, AmendmentSupporter::ROLE_LIKE, $msg, $name); ConsultationLog::logCurrUser($amendment->getMyConsultation(), ConsultationLog::AMENDMENT_LIKE, $amendment->id); } /** * @throws FormError */ private function amendmentDislike(Amendment $amendment): void { if (!($amendment->getLikeDislikeSettings() & SupportBase::LIKEDISLIKE_DISLIKE)) { throw new FormError('Not supported'); } $msg = \Yii::t('amend', 'dislike_done'); $consultation = $amendment->getMyConsultation(); $name = (User::getCurrentUser() ? '' : $this->getHttpRequest()->post('likeName', '')); $this->amendmentLikeDislike($amendment, AmendmentSupporter::ROLE_DISLIKE, $msg, $name); ConsultationLog::logCurrUser($consultation, ConsultationLog::AMENDMENT_DISLIKE, $amendment->id); } /** * @throws Access */ private function amendmentSupportRevoke(Amendment $amendment): void { $currentUser = User::getCurrentUser(); AmendmentSupporter::revokeSupportFromRequest($amendment, $currentUser, AmendmentSupporter::getMyLoginlessSupportIds()); $this->getHttpSession()->setFlash('success', \Yii::t('amend', 'neutral_done')); } /** * @throws Internal */ private function amendmentSupportFinish(Amendment $amendment): void { if (!$amendment->canFinishSupportCollection()) { $this->getHttpSession()->setFlash('error', \Yii::t('amend', 'support_finish_err')); return; } $amendment->trigger(Amendment::EVENT_CREATED, new AmendmentEvent($amendment)); if ($amendment->status === Amendment::STATUS_SUBMITTED_SCREENED) { $amendment->trigger(Amendment::EVENT_PUBLISHED, new AmendmentEvent($amendment)); } $consultation = $amendment->getMyConsultation(); ConsultationLog::logCurrUser($consultation, ConsultationLog::AMENDMENT_SUPPORT_FINISH, $amendment->id); $this->getHttpSession()->setFlash('success', \Yii::t('amend', 'support_finish_done')); } private function setProposalAgreement(Amendment $amendment, int $status, ?string $comment): void { $consultation = $amendment->getMyConsultation(); $procedureToken = $this->getHttpRequest()->post('procedureToken'); $proposal = $amendment->getProposalByToken($procedureToken); if (!$proposal->canAgreeToProposedProcedure($procedureToken) || !$proposal->proposalFeedbackHasBeenRequested()) { $this->getHttpSession()->setFlash('error', 'Not allowed to perform this action'); return; } if ($proposal->userStatus === Amendment::STATUS_ACCEPTED) { // No changing once accepted return; } $data = ProposedProcedureAgreement::create(true, $proposal->version, $proposal->id, $comment)->jsonSerialize(); if ($status === Amendment::STATUS_ACCEPTED) { ConsultationLog::logCurrUser($consultation, ConsultationLog::AMENDMENT_ACCEPT_PROPOSAL, $amendment->id, $data); } if ($status === Amendment::STATUS_REJECTED) { ConsultationLog::logCurrUser($consultation, ConsultationLog::AMENDMENT_REJECT_PROPOSAL, $amendment->id, $data); } $proposal->userStatus = $status; $proposal->save(); $this->getHttpSession()->setFlash('success', \Yii::t('amend', 'proposal_user_saved')); } /** * @throws \Throwable */ private function savePrivateNote(Amendment $amendment): void { $user = User::getCurrentUser(); if (!$user || !$user->getSettingsObj()->allowPrivateComments) { return; } $noteText = trim(RequestContext::getWebRequest()->post('noteText', '')); $comment = $amendment->getPrivateComment(); if ($comment && $noteText === '') { $comment->delete(); $amendment->refresh(); return; } if (!$comment) { $comment = new AmendmentComment(); } $comment->amendmentId = $amendment->id; $comment->userId = $user->id; $comment->text = $noteText; $comment->status = IComment::STATUS_PRIVATE; $comment->paragraph = 0; $comment->dateCreation = date('Y-m-d H:i:s'); $comment->name = ($user->name ? $user->name : '-'); $comment->save(); $amendment->refresh(); } /** * @throws \Throwable */ private function performShowActions(Amendment $amendment, int $commentId, array &$viewParameters): void { $post = $this->getPostValues(); if ($commentId === 0 && isset($post['commentId'])) { $commentId = intval($post['commentId']); } if (isset($post['deleteComment'])) { $this->deleteComment($amendment, $commentId); } elseif (isset($post['commentScreeningAccept'])) { $this->screenCommentAccept($amendment, $commentId); } elseif (isset($post['commentScreeningReject'])) { $this->screenCommentReject($amendment, $commentId); } elseif (isset($post['motionLike'])) { $this->amendmentLike($amendment); } elseif (isset($post['motionDislike'])) { $this->amendmentDislike($amendment); } elseif (isset($post['motionSupport'])) { $this->amendmentSupport($amendment); } elseif (isset($post['motionSupportRevoke'])) { $this->amendmentSupportRevoke($amendment); } elseif (isset($post['amendmentSupportFinish'])) { $this->amendmentSupportFinish($amendment); } elseif (isset($post['addTag'])) { $this->amendmentAddTag($amendment); } elseif (isset($post['delTag'])) { $this->amendmentDelTag($amendment); } elseif (isset($post['writeComment'])) { $this->writeComment($amendment, $viewParameters); } elseif (isset($post['setProposalAgree'])) { $this->setProposalAgreement($amendment, Amendment::STATUS_ACCEPTED, $post['comment'] ?? null); } elseif (isset($post['setProposalDisagree'])) { $this->setProposalAgreement($amendment, Amendment::STATUS_REJECTED, $post['comment'] ?? null); } elseif (isset($post['savePrivateNote'])) { $this->savePrivateNote($amendment); } } public function actionDelProposalComment(string $motionSlug, int $amendmentId): JsonResponse { $amendment = $this->getAmendmentWithCheck($motionSlug, $amendmentId); $commentId = (int)$this->getPostValue('id'); $comment = AmendmentAdminComment::findOne(['id' => $commentId, 'amendmentId' => $amendment->id]); if ($comment && User::isCurrentUser($comment->getMyUser())) { $comment->delete(); return new JsonResponse(['success' => true]); } else { return new JsonResponse(['success' => false, 'error' => 'No permission to delete this comment']); } } }