diff --git a/CHANGELOG.md b/CHANGELOG.md index 13bbca2456..8cd535b1ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## [v1.2](https://github.com/GEWIS/gewisweb/tree/v1.2) (2017-01-09) +* External participants can now be subscribed to activites through the activity admin * Images on committee/fraternity pages now look normal * Activities can now be edited :tada: (#594) * Improved the activity administrator interface (#642) diff --git a/module/Activity/Module.php b/module/Activity/Module.php index a85f094c9f..c582db4add 100644 --- a/module/Activity/Module.php +++ b/module/Activity/Module.php @@ -148,14 +148,20 @@ public function getServiceConfig() $acl->addResource('activity_calendar_option'); $acl->allow('guest', 'activity', 'view'); - $acl->allow('guest', 'activitySignup', ['view', 'signup']); + + $acl->allow('guest', 'activitySignup', ['view', 'externalSignup']); $acl->allow('user', 'activity', 'create'); $acl->allow('user', 'activitySignup', ['signup', 'signoff', 'checkUserSignedUp']); - $acl->allow('admin', 'activity', ['update', 'viewDetails']); - $acl->allow('user', 'activity', ['update', 'viewDetails'], new IsCreator()); - $acl->allow('active_member', 'activity', ['update', 'viewDetails'], new IsOrganMember()); + $acl->allow('admin', 'activity', ['update', 'viewDetails', 'adminSignup']); + $acl->allow('user', 'activity', ['update', 'viewDetails', 'adminSignup'], new IsCreator()); + $acl->allow( + 'active_member', + 'activity', + ['update', 'viewDetails', 'adminSignup'], + new IsOrganMember() + ); $acl->allow('sosuser', 'activitySignup', ['signup', 'signoff', 'checkUserSignedUp']); diff --git a/module/Activity/config/module.config.php b/module/Activity/config/module.config.php index 650ac296db..4ad8993c91 100644 --- a/module/Activity/config/module.config.php +++ b/module/Activity/config/module.config.php @@ -107,6 +107,26 @@ ] ] ], + 'adminSignup' => [ + 'type' => 'Segment', + 'options' => [ + 'route' => '/:id/adminSignup', + 'defaults' => [ + 'controller' => 'admin', + 'action' => 'externalSignup', + ] + ] + ], + 'externalSignoff' => [ + 'type' => 'Segment', + 'options' => [ + 'route' => '/:id/externalSignoff', + 'defaults' => [ + 'controller' => 'admin', + 'action' => 'externalSignoff', + ] + ] + ], 'exportpdf' => [ 'type' => 'Segment', 'options' => [ diff --git a/module/Activity/src/Activity/Controller/AdminController.php b/module/Activity/src/Activity/Controller/AdminController.php index 8e607dc9e8..a30c444b76 100644 --- a/module/Activity/src/Activity/Controller/AdminController.php +++ b/module/Activity/src/Activity/Controller/AdminController.php @@ -30,7 +30,8 @@ public function participantsAction() $queryService = $this->getServiceLocator()->get('activity_service_activityQuery'); $translatorService = $this->getServiceLocator()->get('activity_service_activityTranslator'); $langSession = new SessionContainer('lang'); - + $translator = $this->getServiceLocator()->get('activity_service_activity')->getTranslator(); + $signupRequestSession = new SessionContainer('signupRequest'); /** @var $activity Activity */ $activity = $queryService->getActivityWithDetails($id); @@ -40,10 +41,23 @@ public function participantsAction() return $this->notFoundAction(); } - return [ + $signupService = $this->getServiceLocator()->get('activity_service_signup'); + $externalSignupForm = $signupService->getExternalForm($activity->getFields()); + + $result = [ 'activity' => $translatedActivity, 'signupData' => $translatorService->getTranslatedSignedUpData($activity, $langSession->lang), + 'externalSignupForm' => $externalSignupForm, + 'externalSignoffForm' => new RequestForm('activityExternalSignoff', $translator->translate('Remove')), ]; + //Retrieve and clear the request status from the session, if it exists. + if (isset($signupRequestSession->success)) { + $result['success'] = $signupRequestSession->success; + unset($signupRequestSession->success); + $result['message'] = $signupRequestSession->message; + unset($signupRequestSession->message); + } + return $result; } public function updateAction() @@ -105,6 +119,101 @@ public function exportPdfAction() return $pdf; } + public function externalSignupAction() + { + $id = (int) $this->params('id'); + $activityService = $this->getServiceLocator()->get('activity_service_activity'); + $queryService = $this->getServiceLocator()->get('activity_service_activityQuery'); + $signupService = $this->getServiceLocator()->get('activity_service_signup'); + + $activity = $queryService->getActivity($id); + + $translator = $activityService->getTranslator(); + + //Assure the form is used + if (!$this->getRequest()->isPost()) { + $error = $translator->translate('Use the form to subscribe'); + $this->redirectSignupRequest($id, false, $error); + return; + } + + $form = $signupService->getExternalForm($activity->getFields()); + $form->setData($this->getRequest()->getPost()); + + //Assure the form is valid + if (!$form->isValid()) { + $error = $translator->translate('Invalid form'); + $this->redirectSignupRequest($id, false, $error); + return; + } + + $formData = $form->getData(\Zend\Form\FormInterface::VALUES_AS_ARRAY); + $fullName = $formData['fullName']; + unset($formData['fullName']); + $email = $formData['email']; + unset($formData['email']); + $signupService->adminSignUp($activity, $fullName, $email, $formData); + $message = $translator->translate('Successfully subscribed external participant'); + $this->redirectSignupRequest($id, true, $message); + } + + public function externalSignoffAction() + { + $id = (int) $this->params('id'); + + $activityService = $this->getServiceLocator()->get('activity_service_activity'); + $signupService = $this->getServiceLocator()->get('activity_service_signup'); + $signupMapper = $this->getServiceLocator()->get('activity_mapper_signup'); + + $signup = $signupMapper->getSignupById($id); + + if (is_null($signup)) { + return $this->notFoundAction(); + } + $activity = $signup->getActivity(); + $translator = $activityService->getTranslator(); + + //Assure a form is used + if (!$this->getRequest()->isPost()) { + $message = $translator->translate('Use the form to unsubscribe an external participant'); + $this->redirectSignupRequest($activity->getId(), false, $message); + return; + } + + $form = new RequestForm('activityExternalSignoff', $translator->translate('Remove')); + $form->setData($this->getRequest()->getPost()); + + //Assure the form is valid + if (!$form->isValid()) { + $message = $translator->translate('Invalid form'); + $this->redirectSignupRequest($activity->getId(), false, $message); + return; + } + + $signupService->externalSignOff($signup); + $message = $translator->translate('Successfully removed external participant'); + $this->redirectSignupRequest($activity->getId(), true, $message); + } + + /** + * Redirects to the view of the activity with the given $id, where the + * $error message can be displayed if the request was unsuccesful (i.e. + * $success was false) + * + * @param int $id + * @param boolean $success Whether the request was successful + * @param string $message + */ + protected function redirectSignupRequest($id, $success, $message) + { + $signupRequestSession = new SessionContainer('signupRequest'); + $signupRequestSession->success = $success; + $signupRequestSession->message = $message; + $this->redirect()->toRoute('activity_admin/participants', [ + 'id' => $id, + ]); + } + /** * Show a list of all activities this user can manage. */ diff --git a/module/Activity/src/Activity/Form/ActivitySignup.php b/module/Activity/src/Activity/Form/ActivitySignup.php index 55368131e0..7dcab24475 100644 --- a/module/Activity/src/Activity/Form/ActivitySignup.php +++ b/module/Activity/src/Activity/Form/ActivitySignup.php @@ -18,6 +18,11 @@ public function __construct() $this->setHydrator(new ClassMethodsHydrator(false)) ->setObject(new \Activity\Model\UserActivitySignup()); + $this->add([ + 'name' => 'security', + 'type' => 'Zend\Form\Element\Csrf' + ]); + $this->add([ 'name' => 'submit', 'attributes' => [ @@ -28,18 +33,31 @@ public function __construct() } /** - * Initilialise the form, i.e. set the language and the fields + * Initialize the form, i.e. set the language and the fields * Add every field in $fields to the form. - * + * * @param ActivityField $fields */ public function initialiseForm($fields) { - foreach($fields as $field){ + foreach($fields as $field) { $this->add($this->createFieldElementArray($field)); } } + public function initialiseExternalForm($fields) + { + $this->add([ + 'name' => 'fullName', + 'type' => 'Text' + ]); + $this->add([ + 'name' => 'email', + 'type' => 'Text' + ]); + $this->initialiseForm($fields); + } + /** * Apparently, validators are automatically added, so this works. * diff --git a/module/Activity/src/Activity/Form/ModifyRequest.php b/module/Activity/src/Activity/Form/ModifyRequest.php index 39e8854c83..cda8719eec 100644 --- a/module/Activity/src/Activity/Form/ModifyRequest.php +++ b/module/Activity/src/Activity/Form/ModifyRequest.php @@ -7,7 +7,7 @@ /** * Specifies a form that is used to let an user do a modification request that * does not require any other data, such as signing off for activities or - * approving or dissapproving them. + * approving or disapproving them. */ class ModifyRequest extends Form implements InputFilterProviderInterface { diff --git a/module/Activity/src/Activity/Mapper/Signup.php b/module/Activity/src/Activity/Mapper/Signup.php index e11849b3d9..b487a49944 100644 --- a/module/Activity/src/Activity/Mapper/Signup.php +++ b/module/Activity/src/Activity/Mapper/Signup.php @@ -23,6 +23,23 @@ public function __construct(EntityManager $em) $this->em = $em; } + /** + * @param int $id + * @return \Activity\Model\ActivitySignup + */ + public function getSignupById($id) + { + $qb = $this->em->createQueryBuilder(); + $qb->select('a') + ->from('Activity\Model\ActivitySignup', 'a') + ->where('a.id = :id') + ->setParameter('id', $id); + $result = $qb->getQuery()->getResult(); + + return count($result) > 0 ? $result[0] : null; + } + + /** * Check if a user is signed up for an activity. * diff --git a/module/Activity/src/Activity/Model/ExternalActivitySignup.php b/module/Activity/src/Activity/Model/ExternalActivitySignup.php index c48c50771a..7e9dd282a8 100644 --- a/module/Activity/src/Activity/Model/ExternalActivitySignup.php +++ b/module/Activity/src/Activity/Model/ExternalActivitySignup.php @@ -44,4 +44,14 @@ public function getEmail() { return $this->email; } + + public function setFullName($fullName) + { + $this->fullName = $fullName; + } + + public function setEmail($email) + { + $this->email = $email; + } } diff --git a/module/Activity/src/Activity/Service/Signup.php b/module/Activity/src/Activity/Service/Signup.php index 5e4833da7d..ada92a1977 100644 --- a/module/Activity/src/Activity/Service/Signup.php +++ b/module/Activity/src/Activity/Service/Signup.php @@ -3,7 +3,9 @@ namespace Activity\Service; use Activity\Model\Activity as ActivityModel; +use Activity\Model\ActivitySignup; use Activity\Model\UserActivitySignup; +use Activity\Model\ExternalActivitySignup; use Application\Service\AbstractAclService; use Decision\Model\Member; @@ -36,6 +38,7 @@ protected function getDefaultResourceId() * Otherwise, it returns it in the available language. * * @param type $fields + * @param bool $external Whether the signup is external. * @return type * @throws \User\Permissions\NotAllowedException */ @@ -52,6 +55,13 @@ public function getForm($fields) return $form; } + public function getExternalForm($fields) + { + $form = new \Activity\Form\ActivitySignup(); + $form->initialiseExternalForm($fields); + return $form; + } + /** * Get a list of all the members that are signed up for an activity. * @@ -150,7 +160,7 @@ public function getSignedUpActivityIds() } /** - * Sign up an activity with the specified field values. + * Sign a User up for an activity with the specified field values. * * @param ActivityModel $activity * @param array $fieldResults @@ -163,16 +173,82 @@ public function signUp(ActivityModel $activity, array $fieldResults) $translator->translate('You need to be logged in to sign up for this activity') ); } + $user = $this->getServiceManager()->get('user_service_user')->getIdentity(); + $signup = new UserActivitySignup(); + $signup->setUser($user); + $this->createSignup($signup, $activity, $fieldResults); + } - $em = $this->getServiceManager()->get('Doctrine\ORM\EntityManager'); + /** + * Sign an external user up for an activity, which the current user may admin. + * + * @param \Activity\Service\AcitivityModel $activity + * @param type $fullName + * @param type $email + * @param array $fieldResults + * @throws \User\Permissions\NotAllowedException + */ + public function adminSignUp(ActivityModel $activity, $fullName, $email, array $fieldResults) + { + if (!($this->isAllowed('adminSignup', 'activity') || + $this->isAllowed('adminSignup', $activity))) { + $translator = $this->getTranslator(); + throw new \User\Permissions\NotAllowedException( + $translator->translate('You are not allowed to create signups for this activity') + ); + } + $this->manualSignUp($activity, $fullName, $email, $fieldResults); + } - // Find the current user - $user = $this->getServiceManager()->get('user_service_user')->getIdentity(); + /** + * Sign an external user up for an activity, allowed by a guest. + * + * @param \Activity\Service\AcitivityModel $activity + * @param type $fullName + * @param type $email + * @param array $fieldResults + * @throws \User\Permissions\NotAllowedException + */ + public function externalSignUp(ActivityModel $activity, $fullName, $email, array $fieldResults) + { + if (!($this->isAllowed('externalSignup', 'activitySignup'))) { + $translator = $this->getTranslator(); + throw new \User\Permissions\NotAllowedException( + $translator->translate('You are not allowed to create signups for this activity') + ); + } + $this->manualSignUp($activity, $fullName, $email, $fieldResults); + } - $signup = new UserActivitySignup(); + /** + * Sign an external user up for an activity. + * + * @param \Activity\Service\AcitivityModel $activity + * @param type $user + * @param array $fieldResults + * @throws \User\Permissions\NotAllowedException + */ + protected function manualSignUp(ActivityModel $activity, $fullName, $email, array $fieldResults) + { + $signup = new ExternalActivitySignup(); + $signup->setEmail($email); + $signup->setFullName($fullName); + $this->createSignup($signup, $activity, $fieldResults); + } + + /** + * Creates the generic parts of a signup. + * @param ActivitySignup $signup + * @param ActivityModel $activity + * @param type $user + * @param array $fieldResults + * @return ActivitySignup + */ + protected function createSignup(ActivitySignup $signup, ActivityModel $activity, array $fieldResults) + { $signup->setActivity($activity); - $signup->setUser($user); $optionMapper = $this->getServiceManager()->get('activity_mapper_activity_option'); + $em = $this->getServiceManager()->get('Doctrine\ORM\EntityManager'); foreach ($activity->getFields() as $field){ $fieldValue = new \Activity\Model\ActivityFieldValue(); $fieldValue->setField($field); @@ -196,6 +272,7 @@ public function signUp(ActivityModel $activity, array $fieldResults) } $em->persist($signup); $em->flush(); + return $signup; } /** @@ -220,13 +297,25 @@ public function signOff(ActivityModel $activity, Member $user) if (is_null($signUp)) { return; } + $this->removeSignUp($signUp); + } - $em = $this->getServiceManager()->get('Doctrine\ORM\EntityManager'); - $values = $this->getActivityFieldValueMapper()->getFieldValuesBySignup($signUp); - foreach($values as $value){ - $em->remove($value); + public function externalSignOff(ExternalActivitySignup $signup) + { + if (!($this->isAllowed('adminSignup', 'activity') || + $this->isAllowed('adminSignup', $signup->getActivity()))) { + $translator = $this->getTranslator(); + throw new \User\Permissions\NotAllowedException( + $translator->translate('You are not allowed to remove external signups for this activity') + ); } - $em->remove($signUp); + $this->removeSignUp($signup); + } + + protected function removeSignUp(ActivitySignup $signup) + { + $em = $this->getServiceManager()->get('Doctrine\ORM\EntityManager'); + $em->remove($signup); $em->flush(); } diff --git a/module/Activity/view/activity/activity/view.phtml b/module/Activity/view/activity/activity/view.phtml index 0528dc03f2..95234fbaa8 100644 --- a/module/Activity/view/activity/activity/view.phtml +++ b/module/Activity/view/activity/activity/view.phtml @@ -166,6 +166,7 @@ $this->headTitle($this->translate('Activities')); ?> get('submit'); $submit->setAttribute('class', 'btn btn-primary'); + echo $this->formElement($form->get('security')); echo $this->formSubmit($submit); echo $this->form()->closeTag();?> diff --git a/module/Activity/view/activity/admin/participants.phtml b/module/Activity/view/activity/admin/participants.phtml index b15044dfb4..df2308bee3 100644 --- a/module/Activity/view/activity/admin/participants.phtml +++ b/module/Activity/view/activity/admin/participants.phtml @@ -4,12 +4,50 @@ $this->headTitle($this->escapeHtml($activity->getName())); $this->headTitle($this->translate('Participants')); ?> + +
= $this->translate('Full name:'); ?> | += $this->formRow($externalSignupForm->get('fullName')) ?> | +
= $this->translate('Email address:'); ?> | += $this->formRow($externalSignupForm->get('email')) ?> | +
= $this->escapeHtml($field->getName()) ?>: | += $this->formRow($externalSignupForm->get($field->getId())) ?> | +