controllers/MotionActionsTrait.php
Rama main · réplica de lectura del repositorio original.
<?php
namespace app\controllers;
use app\models\consultationLog\{ProposedProcedureAgreement, ProposedProcedureChange, ProposedProcedureUserNotification};
use app\models\api\imotion\SupportRequest;
use app\models\forms\ProposedChangeForm;
use app\models\settings\{AntragsgruenApp, PrivilegeQueryContext, Privileges};
use app\models\sectionTypes\ISectionType;
use app\models\sectionTypes\TextEditorial;
use app\models\http\{HtmlErrorResponse,
HtmlResponse,
JsonResponse,
RedirectResponse,
ResponseInterface,
RestApiExceptionResponse};
use app\models\notifications\MotionProposedProcedure;
use app\components\{Tools, UrlHelper};
use app\models\db\{Amendment,
ConsultationLog,
ConsultationSettingsTag,
IComment,
IMotion,
Motion,
MotionAdminComment,
MotionComment,
MotionSupporter,
User,
Consultation};
use app\models\exceptions\{Access, DB, FormError, Internal, MailNotSent, ResponseException};
use app\models\forms\CommentForm;
use app\models\events\MotionEvent;
use app\models\supportTypes\SupportBase;
use yii\web\{Request, Response, Session};
/**
* @property Consultation $consultation
* @method Session getHttpSession()
* @method Request getHttpRequest()
* @method Response getHttpResponse()
*/
trait MotionActionsTrait
{
/**
* @throws Internal
*/
private function getComment(Motion $motion, int $commentId, bool $needsScreeningRights): MotionComment
{
$comment = MotionComment::findOne($commentId);
if (!$comment || $comment->motionId != $motion->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(Motion $motion, array &$viewParameters): void
{
$postComment = $this->getHttpRequest()->post('comment');
$replyTo = null;
if (isset($postComment['parentCommentId']) && $postComment['parentCommentId']) {
$replyTo = MotionComment::findOne([
'id' => $postComment['parentCommentId'],
'motionId' => $motion->id,
'parentCommentId' => null,
]);
if ($replyTo && $replyTo->status === IComment::STATUS_DELETED) {
$replyTo = null;
}
}
$commentForm = new CommentForm($motion, $replyTo);
$commentForm->setAttributes($postComment, $motion->getActiveSections());
$redirectUrl = null;
try {
$commentForm->saveNotificationSettings();
$comment = $commentForm->saveMotionCommentWithChecks($motion);
if ($comment->status === MotionComment::STATUS_SCREENING) {
$this->getHttpSession()->setFlash('screening', \Yii::t('comment', 'created_needs_screening'));
} else {
$this->getHttpSession()->setFlash('screening', \Yii::t('comment', 'created'));
}
$redirectUrl = UrlHelper::createMotionCommentUrl($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 DB
* @throws Internal
*/
private function deleteComment(Motion $motion, int $commentId): void
{
$comment = $this->getComment($motion, $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());
}
ConsultationLog::logCurrUser(
$motion->getMyConsultation(),
ConsultationLog::MOTION_COMMENT_DELETE,
$comment->id
);
$this->getHttpSession()->setFlash('success', \Yii::t('comment', 'del_done'));
}
/**
* @throws Internal
*/
private function screenCommentAccept(Motion $motion, int $commentId): void
{
$comment = MotionComment::findOne($commentId);
if (!$comment || $comment->motionId !== $motion->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_VISIBLE;
$comment->save();
$motion->refresh();
ConsultationLog::logCurrUser(
$motion->getMyConsultation(),
ConsultationLog::MOTION_COMMENT_SCREEN,
$comment->id
);
$comment->trigger(IComment::EVENT_PUBLISHED);
}
/**
* @throws Internal
*/
private function screenCommentReject(Motion $motion, int $commentId): void
{
$comment = MotionComment::findOne($commentId);
if (!$comment || $comment->motionId !== $motion->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();
$motion->refresh();
ConsultationLog::logCurrUser(
$motion->getMyConsultation(),
ConsultationLog::MOTION_COMMENT_DELETE,
$comment->id
);
}
/**
* @throws FormError
* @throws Internal
*/
private function motionLikeDislike(Motion $motion, string $role, string $string, string $name, string $orga = '', string $gender = '', bool $nonPublic = false): void
{
$currentUser = User::getCurrentUser();
if (!$motion->motionType->getMotionSupportPolicy()->checkCurrUser(allowAdmins: false)) {
throw new FormError('Supporting this motion is not possible');
}
MotionSupporter::createSupport($motion, $currentUser, $name, $orga, $role, $gender, $nonPublic);
$this->getHttpSession()->setFlash('success', $string);
}
/**
* @throws FormError
* @throws Internal
*/
private function motionLike(Motion $motion): void
{
if (!($motion->getLikeDislikeSettings() & SupportBase::LIKEDISLIKE_LIKE)) {
throw new FormError('Not supported');
}
$name = (User::getCurrentUser() ? '' : $this->getHttpRequest()->post('likeName', ''));
$this->motionLikeDislike($motion, MotionSupporter::ROLE_LIKE, \Yii::t('motion', 'like_done'), $name);
ConsultationLog::logCurrUser($motion->getMyConsultation(), ConsultationLog::MOTION_LIKE, $motion->id);
}
/**
* @throws Access
* @throws FormError
*/
private function motionSupport(Motion $motion): void
{
$user = User::getCurrentUser();
$supportType = $motion->getMyMotionType()->getMotionSupportTypeClass();
$dto = SupportRequest::fromWebRequest($this->getPostValues(), $user, $supportType);
if (!MotionSupporter::createSupportFromRequest($motion, $user, $dto)) {
$this->getHttpSession()->setFlash('success', \Yii::t('motion', 'support_already'));
return;
}
$this->getHttpSession()->set('user_gender', $dto->gender ?? '');
$this->getHttpSession()->setFlash('success', \Yii::t('motion', 'support_done'));
}
/**
* @throws FormError
* @throws Internal
*/
private function motionDislike(Motion $motion): void
{
if (!($motion->getLikeDislikeSettings() & SupportBase::LIKEDISLIKE_DISLIKE)) {
throw new FormError('Not supported');
}
$name = (User::getCurrentUser() ? '' : $this->getHttpRequest()->post('likeName', ''));
$this->motionLikeDislike($motion, MotionSupporter::ROLE_DISLIKE, \Yii::t('motion', 'dislike_done'), $name);
ConsultationLog::logCurrUser($motion->getMyConsultation(), ConsultationLog::MOTION_DISLIKE, $motion->id);
}
/**
* @throws Access
*/
private function motionSupportRevoke(Motion $motion): void
{
$currentUser = User::getCurrentUser();
MotionSupporter::revokeSupportFromRequest($motion, $currentUser, MotionSupporter::getMyLoginlessSupportIds());
$this->getHttpSession()->setFlash('success', \Yii::t('motion', 'neutral_done'));
}
private function motionSupportFinish(Motion $motion): void
{
if (!$motion->canFinishSupportCollection()) {
$this->getHttpSession()->setFlash('error', \Yii::t('motion', 'support_finish_err'));
return;
}
$motion->trigger(Motion::EVENT_CREATED, new MotionEvent($motion));
if ($motion->status == Motion::STATUS_SUBMITTED_SCREENED) {
$motion->trigger(Motion::EVENT_PUBLISHED, new MotionEvent($motion));
}
ConsultationLog::logCurrUser($motion->getMyConsultation(), ConsultationLog::MOTION_SUPPORT_FINISH, $motion->id);
$this->getHttpSession()->setFlash('success', \Yii::t('motion', 'support_finish_done'));
}
/**
* @throws Internal
*/
private function motionAddTag(Motion $motion): void
{
if (!$this->consultation->havePrivilege(Privileges::PRIVILEGE_MOTION_STATUS_EDIT, PrivilegeQueryContext::motion($motion))) {
throw new Internal(\Yii::t('comment', 'err_no_screening'));
}
foreach ($motion->getMyConsultation()->getSortedTags(ConsultationSettingsTag::TYPE_PUBLIC_TOPIC) as $tag) {
if ($tag->id === intval($this->getHttpRequest()->post('tagId'))) {
$motion->link('tags', $tag);
}
}
}
/**
* @throws Internal
*/
private function motionDelTag(Motion $motion): void
{
if (!$this->consultation->havePrivilege(Privileges::PRIVILEGE_MOTION_STATUS_EDIT, PrivilegeQueryContext::motion($motion))) {
throw new Internal(\Yii::t('comment', 'err_no_screening'));
}
foreach ($motion->getMyConsultation()->getSortedTags(ConsultationSettingsTag::TYPE_PUBLIC_TOPIC) as $tag) {
if ($tag->id === intval($this->getHttpRequest()->post('tagId'))) {
$motion->unlink('tags', $tag, true);
}
}
}
private function setProposalAgreement(Motion $motion, int $status, ?string $comment): void
{
$procedureToken = $this->getHttpRequest()->post('procedureToken');
$proposal = $motion->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;
}
$proposal->userStatus = $status;
$proposal->save();
$data = ProposedProcedureAgreement::create(true, $proposal->version, $proposal->id, $comment)->jsonSerialize();
if ($status === Motion::STATUS_ACCEPTED) {
ConsultationLog::logCurrUser($motion->getMyConsultation(), ConsultationLog::MOTION_ACCEPT_PROPOSAL, $motion->id, $data);
}
if ($status === Motion::STATUS_REJECTED) {
ConsultationLog::logCurrUser($motion->getMyConsultation(), ConsultationLog::MOTION_REJECT_PROPOSAL, $motion->id, $data);
}
$this->getHttpSession()->setFlash('success', \Yii::t('amend', 'proposal_user_saved'));
}
/**
* @throws \Throwable
*/
private function savePrivateNote(Motion $motion): void
{
$user = User::getCurrentUser();
if (!$user || !$user->getSettingsObj()->allowPrivateComments) {
return;
}
$noteText = trim($this->getHttpRequest()->post('noteText', ''));
$paragraph = IntVal($this->getHttpRequest()->post('paragraphNo', -1));
if ($this->getHttpRequest()->post('sectionId', 0) > 0) {
$section = IntVal($this->getHttpRequest()->post('sectionId', 0));
} else {
$section = null;
}
$comment = $motion->getPrivateComment($section, $paragraph);
if ($comment && $noteText === '') {
$comment->delete();
$motion->refresh();
return;
}
if (!$comment) {
$comment = new MotionComment();
}
$comment->motionId = $motion->id;
$comment->userId = $user->id;
$comment->text = $noteText;
$comment->status = IComment::STATUS_PRIVATE;
$comment->paragraph = $paragraph;
$comment->sectionId = $section;
$comment->dateCreation = date('Y-m-d H:i:s');
$comment->name = ($user->name ? $user->name : '-');
$comment->save();
$motion->refresh();
throw new ResponseException(new RedirectResponse(UrlHelper::createMotionCommentUrl($comment)));
}
/**
* @throws \Throwable
*/
private function performShowActions(Motion $motion, int $commentId, array &$viewParameters): void
{
$post = $this->getPostValues();
if ($commentId === 0 && isset($post['commentId'])) {
$commentId = intval($post['commentId']);
}
if (isset($post['deleteComment'])) {
$this->deleteComment($motion, $commentId);
} elseif (isset($post['commentScreeningAccept'])) {
$this->screenCommentAccept($motion, $commentId);
} elseif (isset($post['commentScreeningReject'])) {
$this->screenCommentReject($motion, $commentId);
} elseif (isset($post['motionLike'])) {
$this->motionLike($motion);
} elseif (isset($post['motionDislike'])) {
$this->motionDislike($motion);
} elseif (isset($post['motionSupport'])) {
$this->motionSupport($motion);
} elseif (isset($post['motionSupportRevoke'])) {
$this->motionSupportRevoke($motion);
} elseif (isset($post['motionSupportFinish'])) {
$this->motionSupportFinish($motion);
} elseif (isset($post['addTag'])) {
$this->motionAddTag($motion);
} elseif (isset($post['delTag'])) {
$this->motionDelTag($motion);
} elseif (isset($post['writeComment'])) {
$this->writeComment($motion, $viewParameters);
} elseif (isset($post['setProposalAgree'])) {
$this->setProposalAgreement($motion, Motion::STATUS_ACCEPTED, $post['comment'] ?? null);
} elseif (isset($post['setProposalDisagree'])) {
$this->setProposalAgreement($motion, Motion::STATUS_REJECTED, $post['comment'] ?? null);
} elseif (isset($post['savePrivateNote'])) {
$this->savePrivateNote($motion);
}
}
public function actionDelProposalComment(string $motionSlug): ResponseInterface
{
$motion = $this->getMotionWithCheck($motionSlug);
$commentId = $this->getHttpRequest()->post('id');
$comment = MotionAdminComment::findOne(['id' => $commentId, 'motionId' => $motion->id]);
if ($comment && User::isCurrentUser($comment->getMyUser())) {
$comment->delete();
return new JsonResponse(['success' => true]);
} else {
return new RestApiExceptionResponse(403, 'No permission to delete this comment');
}
}
public function actionSaveProposalStatus(string $motionSlug): ResponseInterface
{
$motion = $this->consultation->getMotion($motionSlug);
if (!$motion) {
return new RestApiExceptionResponse(404, 'Motion not found');
}
$post = $this->getPostValues();
if (!in_array('version', array_keys($post))) {
return new RestApiExceptionResponse(400, 'No version provided');
}
$proposal = $motion->getProposalById($post['version']);
if (!$proposal->canEditLimitedProposedProcedure()) {
return new RestApiExceptionResponse(403, 'Not permitted to change the status');
}
$proposalIsNew = $proposal->isNewRecord;
$proposal->save(); // Make sure we know the ID
$canChangeProposalUnlimitedly = $proposal->canEditProposedProcedure();
$response = [];
$msgAlert = null;
$ppChanges = ProposedProcedureChange::create($proposalIsNew, $proposal->id, $proposal->version);
if ($this->getHttpRequest()->post('setStatus', null) !== null) {
$originalMotionId = $motion->id;
$originalProposalStatus = $proposal->proposalStatus;
foreach (AntragsgruenApp::getActivePlugins() as $plugin) {
/** @var Motion $motion */
$motion = $plugin::onBeforeProposedProcedureStatusSave($motion);
}
if ($canChangeProposalUnlimitedly) {
$setStatus = intval($this->getHttpRequest()->post('setStatus'));
if ($proposal->proposalStatus !== $setStatus) {
$ppChanges->setProposalStatusChanges($proposal->proposalStatus, $setStatus);
if ($proposal->userStatus !== null) {
$msgAlert = \Yii::t('amend', 'proposal_user_change_reset');
}
$proposal->userStatus = null;
}
$proposal->proposalStatus = $setStatus;
$ppChanges->setProposalCommentChanges($proposal->comment, $this->getHttpRequest()->post('proposalComment', ''));
$proposal->comment = $this->getHttpRequest()->post('proposalComment', '');
}
$motion->setProposedProcedureTags($this->getHttpRequest()->post('tags', []), $ppChanges);
if ($canChangeProposalUnlimitedly) {
$proposalExplanationPre = $proposal->explanation;
if ($this->getHttpRequest()->post('proposalExplanation', null) !== null) {
if (trim($this->getHttpRequest()->post('proposalExplanation', '')) === '') {
$proposal->explanation = null;
} else {
$proposal->explanation = $this->getHttpRequest()->post('proposalExplanation', '');
}
} else {
$proposal->explanation = null;
}
$ppChanges->setProposalExplanationChanges($proposalExplanationPre, $proposal->explanation);
if ($this->getHttpRequest()->post('visible', 0)) {
if ($proposal->visibleFrom === null) {
// Reload the page, to update section titles and permissions to edit the proposed procedure
$response['redirectToUrl'] = UrlHelper::createMotionUrl($motion, 'view');
}
$proposal->setPublished();
} else {
$proposal->visibleFrom = null;
}
}
try {
$motion->setProposalVotingPropertiesFromRequest(
$this->getHttpRequest()->post('votingStatus', null),
$this->getHttpRequest()->post('votingBlockId', null),
$this->getHttpRequest()->post('votingItemBlockId', []),
$this->getHttpRequest()->post('votingItemBlockName', ''),
$this->getHttpRequest()->post('votingBlockTitle', ''),
true,
$ppChanges
);
} catch (FormError $e) {
return new RestApiExceptionResponse(400, $e->getMessage());
}
if ($ppChanges->hasChanges()) {
ConsultationLog::logCurrUser($motion->getMyConsultation(), ConsultationLog::MOTION_SET_PROPOSAL, $motion->id, $ppChanges->jsonSerialize());
}
$response['success'] = false;
if ($proposal->save()) {
$response['success'] = true;
}
$this->consultation->refresh();
$motion->refresh();
$response['html'] = $this->renderPartial('_set_proposed_procedure', [
'motion' => $motion,
'proposal' => $proposal,
'msgAlert' => $msgAlert,
'context' => $this->getHttpRequest()->post('context', 'view'),
]);
$response['proposalStr'] = $proposal->getFormattedProposalStatus(true);
if ($proposal->proposalStatus === IMotion::STATUS_MODIFIED_ACCEPTED && $originalProposalStatus !== $proposal->proposalStatus) {
$response['redirectToUrl'] = UrlHelper::createMotionUrl($motion, 'edit-proposed-change', ['proposalVersion' => $proposal->version]);
} elseif ($motion->id !== $originalMotionId) {
// This can happen if a plugin enforces the creation of a new motion when saving
$response['redirectToUrl'] = UrlHelper::createMotionUrl($motion, 'view');
}
}
if ($this->getHttpRequest()->post('notifyProposer', false)) {
try {
new MotionProposedProcedure(
$proposal,
$this->getHttpRequest()->post('text'),
$this->getHttpRequest()->post('fromName'),
$this->getHttpRequest()->post('replyTo')
);
$proposal->notifiedAt = date('Y-m-d H:i:s');
$proposal->save();
$data = ProposedProcedureUserNotification::create($this->getHttpRequest()->post('text'), $proposal->version, $proposal->id)->jsonSerialize();
ConsultationLog::logCurrUser($motion->getMyConsultation(), ConsultationLog::MOTION_NOTIFY_PROPOSAL, $motion->id, $data);
$response['success'] = true;
$response['html'] = $this->renderPartial('_set_proposed_procedure', [
'motion' => $motion,
'proposal' => $proposal,
'msgAlert' => $msgAlert,
'context' => $this->getHttpRequest()->post('context', 'view'),
]);
} catch (MailNotSent $e) {
$response['success'] = false;
$response['error'] = 'The mail could not be sent: ' . $e->getMessage();
}
}
if ($this->getHttpRequest()->post('setProposerHasAccepted')) {
$proposal->userStatus = Motion::STATUS_ACCEPTED;
$proposal->save();
$data = ProposedProcedureAgreement::create(false, $proposal->version, $proposal->id, null)->jsonSerialize();
ConsultationLog::logCurrUser($motion->getMyConsultation(), ConsultationLog::MOTION_ACCEPT_PROPOSAL, $motion->id, $data);
$response['success'] = true;
$response['html'] = $this->renderPartial('_set_proposed_procedure', [
'motion' => $motion,
'proposal' => $proposal,
'msgAlert' => $msgAlert,
'context' => $this->getHttpRequest()->post('context', 'view'),
]);
}
if ($this->getHttpRequest()->post('writeComment')) {
$adminComment = new MotionAdminComment();
$adminComment->userId = User::getCurrentUser()->id;
$adminComment->text = $this->getHttpRequest()->post('writeComment');
$adminComment->status = MotionAdminComment::TYPE_PROPOSED_PROCEDURE;
$adminComment->dateCreation = date('Y-m-d H:i:s');
$adminComment->motionId = $motion->id;
if (!$adminComment->save()) {
return new RestApiExceptionResponse(500, 'could not save the comment');
}
$response['success'] = true;
$response['proposalId'] = $proposal->id;
$response['comment'] = [
'username' => $adminComment->getMyUser()->name,
'id' => $adminComment->id,
'text' => $adminComment->text,
'delLink' => UrlHelper::createMotionUrl($motion, 'del-proposal-comment'),
'dateFormatted' => Tools::formatMysqlDateTime($adminComment->dateCreation),
];
}
if ($this->getHttpRequest()->post('deleteProposal')) {
if ($proposal->isNewRecord) {
return new RestApiExceptionResponse(400, 'This proposal version has not been saved yet');
}
if (!$proposal->canEditProposedProcedure()) {
return new RestApiExceptionResponse(403, 'Not permitted to delete this proposal version');
}
$proposal->softDelete();
$response['success'] = true;
$response['redirectToUrl'] = UrlHelper::createMotionUrl($motion, 'view');
}
return new JsonResponse($response);
}
public function actionEditProposedChange(string $motionSlug, int $proposalVersion): ResponseInterface
{
$motion = $this->consultation->getMotion($motionSlug);
if (!$motion) {
return new HtmlErrorResponse(404, 'Motion not found');
}
if ($this->getHttpRequest()->post('newVersion', null) === 'new') {
$oldProposal = $motion->getProposalByVersion($proposalVersion);
$proposal = $motion->getProposalById(null); // Create a new one
$proposal->proposalStatus = $oldProposal->proposalStatus;
} else {
$proposal = $motion->getProposalByVersion($proposalVersion);
}
if (!$proposal->canEditProposedProcedure()) {
return new HtmlErrorResponse(403, 'Not permitted to edit the proposed procedure');
}
$isNewProposal = $proposal->isNewRecord;
$proposal->save();
if ($this->getHttpRequest()->post('reset', null) !== null) {
$reference = $proposal->getMyProposalReference();
if ($reference && $reference->status === Amendment::STATUS_PROPOSED_MODIFIED_MOTION) {
foreach ($reference->sections as $section) {
$section->delete();
}
$proposal->proposalReferenceId = null;
$proposal->save();
$reference->delete();
$ppChanges = ProposedProcedureChange::create($isNewProposal, $proposal->id, $proposal->version);
$ppChanges->setProposalTextChanged();
ConsultationLog::logCurrUser($motion->getMyConsultation(), ConsultationLog::MOTION_SET_PROPOSAL, $motion->id, $ppChanges->jsonSerialize());
}
$motion->flushCacheItems(['procedure']);
}
$form = new ProposedChangeForm($motion, $proposal);
$msgSuccess = null;
$msgAlert = null;
if ($this->getHttpRequest()->post('save', null) !== null) {
$form->save($this->getPostValues(), $_FILES);
$this->getHttpSession()->setFlash('success', \Yii::t('base', 'saved'));
if ($proposal->userStatus !== null) {
$this->getHttpSession()->setFlash('info', \Yii::t('amend', 'proposal_user_change_reset'));
}
$proposal->userStatus = null;
$proposal->save();
$proposal->flushViewCaches();
$ppChanges = ProposedProcedureChange::create($isNewProposal, $proposal->id, $proposal->version);
$ppChanges->setProposalTextChanged();
ConsultationLog::logCurrUser($motion->getMyConsultation(), ConsultationLog::MOTION_SET_PROPOSAL, $motion->id, $ppChanges->jsonSerialize());
return new RedirectResponse(UrlHelper::createMotionUrl($motion, 'view', ['proposalVersion' => $proposal->version]));
}
return new HtmlResponse($this->render('edit_proposed_change', [
'msgSuccess' => $msgSuccess,
'msgAlert' => $msgAlert,
'motion' => $motion,
'proposal' => $proposal,
'form' => $form,
]));
}
public function actionSaveEditorial(string $motionSlug, int $sectionId): ResponseInterface
{
$motion = $this->consultation->getMotion($motionSlug);
if (!$motion) {
return new RestApiExceptionResponse(404, 'Motion not found');
}
if (!User::havePrivilege($this->consultation, Privileges::PRIVILEGE_CHANGE_EDITORIAL, PrivilegeQueryContext::motion($motion))) {
return new RestApiExceptionResponse(403, 'Not permitted to change the editorial');
}
$section = null;
foreach ($motion->getActiveSections(ISectionType::TYPE_TEXT_EDITORIAL) as $searchSection) {
if ($searchSection->sectionId === $sectionId) {
$section = $searchSection;
}
}
if (!$section) {
return new RestApiExceptionResponse(404, 'Section not found');
}
/** @var TextEditorial $sectionType */
$sectionType = $section->getSectionType();
$sectionType->setEditorialData(
$this->getPostValue('data'),
$this->getPostValue('author'),
$this->getPostValue('updateDate') ? new \DateTime() : $sectionType->getSectionMetadata()['lastUpdate']
);
$section->save();
return new JsonResponse([
'success' => true,
'html' => $section->getData(),
'metadataFormatted' => $sectionType->getFormattedSectionMetadata(true),
]);
}
}