From 48ee90a0ee64fdbd2d44acbbf0fa9bcb0cf9b816 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Mon, 4 Nov 2013 00:01:24 -0330 Subject: [PATCH] Controllers refactored to use the API. - Moved session handling into its own class. - A LOT of TODO comments added - Refactored the 3 controllers Due to the state of the codebase, I'm not sure if any of this works. --- module/AbaLookup/config/module.config.php | 2 +- .../src/AbaLookup/AbaLookupController.php | 103 +++----- .../src/AbaLookup/HomeController.php | 82 ++----- .../src/AbaLookup/Session/Session.php | 57 +++++ .../src/AbaLookup/UsersController.php | 224 +++++++----------- 5 files changed, 199 insertions(+), 269 deletions(-) create mode 100644 module/AbaLookup/src/AbaLookup/Session/Session.php diff --git a/module/AbaLookup/config/module.config.php b/module/AbaLookup/config/module.config.php index 89c198e..2ebe094 100644 --- a/module/AbaLookup/config/module.config.php +++ b/module/AbaLookup/config/module.config.php @@ -73,7 +73,7 @@ 'users' => [ 'type' => 'Segment', 'options' => [ - 'route' => '/users/:id/:action[/:mode]', + 'route' => '/users/:id/:action', 'constraints' => [ 'id' => '[0-9]*', 'action' => '[a-zA-Z0-9_-]+', diff --git a/module/AbaLookup/src/AbaLookup/AbaLookupController.php b/module/AbaLookup/src/AbaLookup/AbaLookupController.php index 32d737e..35a0e8f 100644 --- a/module/AbaLookup/src/AbaLookup/AbaLookupController.php +++ b/module/AbaLookup/src/AbaLookup/AbaLookupController.php @@ -2,119 +2,78 @@ namespace AbaLookup; -use - Zend\Mvc\Controller\AbstractActionController, - Zend\Session\Container, - Zend\View\Model\ViewModel -; +use Zend\Mvc\Controller\AbstractActionController; +use Zend\View\Model\ViewModel; +/** + * Base controller class + */ abstract class AbaLookupController extends AbstractActionController { - /** - * The key used to store the user in session - */ - const SESSION_USER_NAMESPACE = 'user'; - const SESSION_USER_ID_KEY = 'id'; - - /** - * 3 months in seconds - */ - const SECONDS_3_MONTHS = 7884000; - /** * Returns the API object for the given name * + * Gets from the API factory the appropriate API and returns + * an instance. + * * @param string $name The name of the API class. * @return mixed */ protected function getApi($name) { + // TODO - Does the API factory throw an exception? return $this->serviceLocator('Lookup\ApiFactory')->get($name); } /** - * Returns a redirect to the login route - * - * @return ViewModel - */ - protected function redirectToLoginPage() - { - return $this->redirect()->toRoute('auth/login'); - } - - /** - * Sets the session for the given user - * - * @param int $id The user id. - * @param boolean $remember Whether to set an explicit TTL for the user session. + * @return ViewModel Redirect to the home route. */ - protected function setUserSession($id, $remember = FALSE) + protected function redirectHome() { - $session = new Container(self::SESSION_USER_NAMESPACE); - $session->getManager() - ->getConfig() - ->setCookieHttpOnly(TRUE); // As per issue #87 - if (isset($remember) && $remember) { - $session->getManager() - ->rememberMe(self::SECONDS_3_MONTHS); - } - $session->offsetSet(self::SESSION_USER_ID_KEY, $id); + return $this->redirect()->toRoute('home'); } /** - * Unsets the session + * @return ViewModel Redirect to the login route. */ - protected function unsetUserSession() - { - $session = new Container(self::SESSION_USER_NAMESPACE); - $session->offsetUnset(self::SESSION_USER_ID_KEY); - } - - /** - * Returns whether a user is currently in session - * - * @return bool - */ - protected function isUserInSession() + protected function redirectToLoginPage() { - $session = new Container(self::SESSION_USER_NAMESPACE); - return $session->offsetExists(self::SESSION_USER_ID_KEY); + return $this->redirect()->toRoute('auth/login'); } /** - * Returns the id of the current user session + * Redirects to the users route given a user ID and an action * - * @return Lookup\Entity\User|NULL + * @param int $id The user ID. + * @param string $action The route action. + * @return ViewModel Redirect to the users route. */ - protected function currentSessionUser() + protected function redirectToUsersRoute($id, $action = 'profile') { - if (!$this->isUserInSession()) { - return NULL; - } - $session = new Container(self::SESSION_USER_NAMESPACE); - return $this->getApi('UserAccount') - ->get($session->offsetGet(self::SESSION_USER_ID_KEY)); + $params = ['id' => $id, 'action' => $action]; + return $this->redirect()->toRoute('users', $params); } /** - * Prepares the given layout to be displayed for the given user + * Prepares the layout to be displayed for the given user * * Nests the footer widget into the layout, and attaches the current - * to the layout as a variable. + * user to the layout as a variable. * - * @param ViewModel $layout The layout for the view. - * @param Lookup\Entity\User $user The user currently in session. + * @param Lookup\Entity\User $user The user in session. + * @return void */ - protected function prepareLayout($layout, Lookup\Entity\User $user = NULL) + protected function prepareLayout(Lookup\Entity\User $user = NULL) { - // Add the footer + // Add the footer template + $layout = $this->layout(); $footer = new ViewModel(); $footer->setTemplate('widget/footer'); $layout->addChild($footer, 'footer'); - // Add the user's URL - if (!isset($user)) { + if (is_null($user)) { return; } + // Attach the user to the view $layout->setVariable('user', $user); } } diff --git a/module/AbaLookup/src/AbaLookup/HomeController.php b/module/AbaLookup/src/AbaLookup/HomeController.php index cf2c10a..997c67c 100644 --- a/module/AbaLookup/src/AbaLookup/HomeController.php +++ b/module/AbaLookup/src/AbaLookup/HomeController.php @@ -2,76 +2,34 @@ namespace AbaLookup; -/** - * Controller for home actions - */ +use AbaLookup\Session\Session; +use Zend\EventManager\EventManagerInterface; +use Zend\Mvc\MvcEvent; + class HomeController extends AbaLookupController { - /** - * Displays the home page - * - * @return array - */ - public function indexAction() + public function setEventManager(EventManagerInterface $events) + { + parent::setEventManager($events); + $events->attach(MvcEvent::EVENT_DISPATCH, [$this, 'beforeAction'], 100); + } + + public function beforeAction() { // Set the home layout $this->layout('layout/home'); - $layout = $this->layout(); - $user = $this->currentSessionUser(); + $uid = Session::getUserId(); + try { + $user = $this->getApi('UserAccount') + ->get($uid); + } catch (Lookup\Api\Exception\InvalidDataException $e) { + // TODO - Handle this + $user = NULL; + } // Prepare the layout - $this->prepareLayout($layout, $user); + $this->prepareLayout($user); return [ 'user' => $user, ]; } - - /** - * Displays the privacy policy - * - * @return array - */ - public function privacyAction() - { - return $this->indexAction(); - } - - /** - * Displays the about page - * - * @return array - */ - public function aboutAction() - { - return $this->indexAction(); - } - - /** - * Displays the terms of service - * - * @return array - */ - public function termsAction() - { - return $this->indexAction(); - } - - /** - * Displays information about the sponsors - * - * @return array - */ - public function sponsorsAction() - { - return $this->indexAction(); - } - - /** - * Displays site colophon - * - * @return array - */ - public function colophonAction() - { - return $this->indexAction(); - } } diff --git a/module/AbaLookup/src/AbaLookup/Session/Session.php b/module/AbaLookup/src/AbaLookup/Session/Session.php new file mode 100644 index 0000000..67ff61b --- /dev/null +++ b/module/AbaLookup/src/AbaLookup/Session/Session.php @@ -0,0 +1,57 @@ +getManager() + ->getConfig() + ->setCookieHttpOnly(TRUE) // As per issue #87 + ->rememberMe((is_bool($remember) && $remember) ? Session::SECONDS_3_MONTHS : 0); + $session->offsetSet(Session::SESSION_USER_KEY_ID, $id); + } + + /** + * @return int|NULL The ID of the user in session. + */ + public static function getUserId() + { + return (new Container(Session::SESSION_USER_NAMESPACE))->offsetGet(Session::SESSION_USER_ID_KEY); + } + + /** + * Unsets the user ID for the session + * + * @return void + */ + public static function unsetUserId() + { + (new Container(Session::SESSION_USER_NAMESPACE))->offsetUnset(Session::SESSION_USER_ID_KEY); + } +} diff --git a/module/AbaLookup/src/AbaLookup/UsersController.php b/module/AbaLookup/src/AbaLookup/UsersController.php index 1ac9846..ca0a5c6 100644 --- a/module/AbaLookup/src/AbaLookup/UsersController.php +++ b/module/AbaLookup/src/AbaLookup/UsersController.php @@ -2,47 +2,44 @@ namespace AbaLookup; -use - AbaLookup\Form\LoginForm, - AbaLookup\Form\ProfileEditForm, - AbaLookup\Form\RegisterForm, - Zend\View\Model\ViewModel -; +use AbaLookup\Form\LoginForm; +use AbaLookup\Form\ProfileEditForm; +use AbaLookup\Form\RegisterForm; +use AbaLookup\Form\ScheduleForm; +use AbaLookup\Session\Session; +use Zend\View\Model\ViewModel; /** - * Handles all actions involving users + * Controller for user actions */ class UsersController extends AbaLookupController { /** * Registers the user or shows a registration form * - * Shows the registration form, validates the form data, creates a user from - * the submitted data, and then adds the user into the database. + * Shows the registration form or sends the POST data along to the + * API for validation as needed. * * @return array|Zend\Http\Response */ public function registerAction() { - // If a user is already logged in - $user = $this->currentSessionUser(); - if (isset($user)) { + // Is a user logged in? + $uid = Session::getUserId(); + if (!is_null($uid)) { // Redirect the user to their profile page - $params = [ - 'id' => $user->getId(), - 'action' => 'profile', - ]; - return $this->redirect()->toRoute('users', $params); + return $this->redirectToUsersRoute($id); } // Prepare the view layout - $this->prepareLayout($this->layout()); + $this->prepareLayout(); // Get the user type from the URL - // Create a registration form $type = $this->params('type'); + // Create a registration form for the particular + // type of user that is registering $form = new RegisterForm($type); - // If the user has not submitted a POST request + // If the user has NOT submitted a POST request if (!$this->request->isPost()) { - // The user has not submitted the form + // Show the registration form return [ 'form' => $form, 'type' => $type, @@ -51,7 +48,7 @@ public function registerAction() // The user has submitted via POST // TODO - Validate Terms of Service // TODO - Show previous data to user - $data = $this->params(); + $data = $this->params(); // TODO - Is this correct? try { $id = $this->getApi('UserAccount')->put( $data->fromPost($form::ELEMENT_NAME_EMAIL_ADDRESS), @@ -61,6 +58,8 @@ public function registerAction() $data->fromPost($form::ELEMENT_NAME_POSTAL_CODE), array_intersect_key( $data->fromPost(), + // Flip this array to get the keys that are valid + // Only the valid keys remain from the POST data array_flip([ $form::ELEMENT_NAME_ABA_COURSE, $form::ELEMENT_NAME_CERTIFICATE_OF_CONDUCT, @@ -71,56 +70,49 @@ public function registerAction() ) ); } catch (Lookup\Api\Exception\InvalidDataException $e) { + // Show the user the error message return [ 'error' => $e->getMessage(), 'form' => $form, 'type' => $type, ]; } - $this->setUserSession($id); + Session::setUserId($id); // Redirect the user to their profile page - $params = [ - 'id' => $id, - 'action' => 'profile', - ]; - return $this->redirect()->toRoute('users', $params); + return $this->redirectToUsersRoute($id); } /** * Logs the user in * - * Verify the user credentials and if valid login user in. + * Sends the POST data along to the API as needed. * * @return array|Zend\Http\Response */ public function loginAction() { - // If a user is already logged in - $user = $this->currentSessionUser(); - if (isset($user)) { - // Show the user their profile page - $params = [ - 'id' => $user->getId(), - 'action' => 'profile', - ]; - return $this->redirect()->toRoute('users', $params); + // Is a user logged in? + $uid = Session::getUserId(); + if (!is_null($uid)) { + // Redirect the user to their profile page + return $this->redirectToUsersRoute($id); } // Prepare the view layout - $this->prepareLayout($this->layout()); + $this->prepareLayout(); // Create a login form $form = new LoginForm(); - // If the user has not submitted a POST request + // If the user has NOT submitted a POST request if (!$this->request->isPost()) { // Show the login form return [ 'form' => $form, ]; } - // The user has submitted via POST + // The user has submitted data via POST $data = $this->params(); try { - $user = $this->getApi('UserAccount')->get([ - 'email' => $data->fromPost($form::ELEMENT_NAME_EMAIL_ADDRESS), + $id = $this->getApi('UserAccount')->get([ + 'email' => $data->fromPost($form::ELEMENT_NAME_EMAIL_ADDRESS), 'password' => $data->fromPost($form::ELEMENT_NAME_PASSWORD), ]); } catch (Lookup\Api\Exception\InvalidDataException $e) { @@ -130,13 +122,8 @@ public function loginAction() ]; } // Create a session for the user - $id = $user->getId(); - $this->setUserSession($id, $form->rememberMe()); - $params = [ - 'id' => $id, - 'action' => 'profile', - ]; - return $this->redirect()->toRoute('users', $params); + Session::setUserId($id, $form->rememberMe()); + return $this->redirectToUsersRoute($id); } /** @@ -149,126 +136,93 @@ public function loginAction() */ public function logoutAction() { - if ($this->isUserInSession()) { - $this->unsetUserSession(); - } - return $this->redirect()->toRoute('home'); + Session::unsetUserId(); + return $this->redirectHome(); } /** * Displays the user's profile * - * Edits to the user's profile arrive via POST with - * a parameter of 'mode' => 'edit'. + * Edits to the user's profile arrive via POST. * * @return array|Zend\Http\Response */ public function profileAction() { - // If a user is not in session - $user = $this->currentSessionUser(); - if (!isset($user)) { - // Redirect to the login view + try { + $uid = Session::getUserId(); + $user = $this->getApi('UserAccount') + ->get($uid); + } catch (Lookup\Api\Exception\InvalidDataException $e) { + // The ID is NOT valid return $this->redirectToLoginPage(); } // Prepare the layout - $this->prepareLayout($this->layout(), $user); - // If the mode is not edit - // The user is viewing their profile - if ($this->params('mode') !== 'edit') { - // Show the user's profile - return [ - 'user' => $user, - ]; - } - // The user is editing their profile info + $this->prepareLayout($user); $form = new ProfileEditForm($user); - $edit = new ViewModel([ - 'user' => $user, - 'form' => $form, - ]); - $edit->setTemplate('profile/edit'); - // If the user has not submitted a POST request + // If the user has NOT submitted a POST request if (!$this->request->isPost()) { // Show the edit form - return $edit; + return [ + 'user' => $user, + 'form' => $form, + ]; } - // The user has submitted via POST + // The user has submitted data via POST $data = $this->params(); try { - $this->getApi('UserAccount')->post($user->getId(), [ - 'email' => $data->fromPost($form::ELEMENT_NAME_EMAIL_ADDRESS), - 'display_name' => $data->fromPost($form::ELEMENT_NAME_DISPLAY_NAME), - 'postal_code' => $data->fromPost($form::ELEMENT_NAME_POSTAL_CODE), - 'aba_course' => $data->fromPost($form::ELEMENT_NAME_ABA_COURSE), + $this->getApi('UserAccount')->post($uid, [ + 'aba_course' => $data->fromPost($form::ELEMENT_NAME_ABA_COURSE), 'certificate_of_conduct' => $data->fromPost($form::ELEMENT_NAME_CERTIFICATE_OF_CONDUCT_DATE), - 'gender' => $data->fromPost($form::ELEMENT_NAME_GENDER), - 'phone_number' => $data->fromPost($form::ELEMENT_NAME_PHONE_NUMBER), + 'display_name' => $data->fromPost($form::ELEMENT_NAME_DISPLAY_NAME), + 'email' => $data->fromPost($form::ELEMENT_NAME_EMAIL_ADDRESS), + 'gender' => $data->fromPost($form::ELEMENT_NAME_GENDER), + 'phone_number' => $data->fromPost($form::ELEMENT_NAME_PHONE_NUMBER), + 'postal_code' => $data->fromPost($form::ELEMENT_NAME_POSTAL_CODE), ]); } catch (Lookup\Api\Exception\InvalidDataException $e) { - $edit->setVariable('error', $e->getMessage()); - return $edit; + // Show the error message + return [ + 'error' => $e->getMessage(), + 'user' => $user, + 'form' => $form, + ]; } // Redirect to the profile page - return $this->redirect()->toRoute('users', [ - 'id' => $user->getId(), - 'action' => 'profile', - ]); + return $this->redirectToUsersRoute($uid); } /** * Displays the user's schedule * - * Edits to the schedule arrive via POST with a 'mode' == 'add'. + * Edits to the schedule arrive via POST. * * @return array|Zend\Http\Response */ public function scheduleAction() { - // If a user is not in session - $user = $this->currentSessionUser(); - if (!isset($user)) { - // Redirect to the login view + try { + $uid = Session::getUserId(); + $user = $this->getApi('UserAccount') + ->get($uid); + } catch (Lookup\Api\Exception\InvalidDataException $e) { + // The user ID is NOT valid return $this->redirectToLoginPage(); } // Prepare the layout - $this->prepareLayout($this->layout(), $user); - // Get the user's schedule - $schedule = $this->getUserSchedule($user); - // If the user submitted changes - if ( - $this->request->isPost() - && ($this->params('mode') === 'edit') - ) { + $this->prepareLayout($user); + // Get the user's schedules + $schedules = $this->getApi('Schedule') + ->get(['user_id' => $uid]); + if ($this->request->isPost()) { // Add the availability to the schedule - $params = array_values($this->request->getPost()->toArray()); - list($day, $startTime, $endTime, $addRemove) = $params; - try { - $schedule->setAvailability( - (int) $day, - (int) $startTime, - (int) $endTime, - ($addRemove == 'add') - ); - } catch (InvalidArgumentException $e) { - return [ - 'error' => $e->getMessage(), - 'user' => $user, - 'schedule' => $schedule, - ]; - } - // Persist the changes - $this->save($schedule); - // Redirect to the schedule page - $params = [ - 'id' => $user->getId(), - 'action' => 'schedule', - ]; - return $this->redirect()->toRoute('users', $params); + $data = $this->params(); + // TODO - Make a PUT request to ScheduleInterval API + return $this->redirectToUsersRoute($uid, 'schedule'); } // Show the user their schedule return [ - 'schedule' => $schedule, + 'schedules' => $schedules, 'user' => $user, ]; } @@ -280,14 +234,16 @@ public function scheduleAction() */ public function matchesAction() { - // If a user is not in session - $user = $this->currentSessionUser(); - if (!isset($user)) { - // Redirect to the login view + try { + $uid = Session::getUserId(); + $user = $this->getApi('UserAccount') + ->get($uid); + } catch (Lookup\Api\Exception\InvalidDataException $e) { + // The user ID is NOT valid return $this->redirectToLoginPage(); } // Prepare the layout - $this->prepareLayout($this->layout(), $user); + $this->prepareLayout($user); // Show the user their matches return [ 'user' => $user,