|
From: <gem...@li...> - 2012-07-18 08:01:15
|
Revision: 852
http://gemstracker.svn.sourceforge.net/gemstracker/?rev=852&view=rev
Author: mennodekker
Date: 2012-07-18 08:01:04 +0000 (Wed, 18 Jul 2012)
Log Message:
-----------
Fixed #549: Allow a layered login when organizations have children
Modified Paths:
--------------
trunk/library/classes/Gems/Default/IndexAction.php
trunk/library/classes/Gems/User/Form/OrganizationFormAbstract.php
trunk/library/classes/Gems/User/UserLoader.php
Added Paths:
-----------
trunk/library/classes/Gems/User/Form/LayeredLoginForm.php
Modified: trunk/library/classes/Gems/Default/IndexAction.php
===================================================================
--- trunk/library/classes/Gems/Default/IndexAction.php 2012-07-17 15:55:22 UTC (rev 851)
+++ trunk/library/classes/Gems/Default/IndexAction.php 2012-07-18 08:01:04 UTC (rev 852)
@@ -56,6 +56,14 @@
protected $labelWidthFactor = null;
/**
+ * Use a flat login (false = default) or a layered login where you first
+ * select a parent organization and then see a list of child organizations.
+ *
+ * @var boolean
+ */
+ protected $layeredLogin = false;
+
+ /**
* For small numbers of organizations a multiline selectbox will be nice. This
* setting handles how many lines will display at once. Use 1 for the normal
* dropdown selectbox
@@ -108,7 +116,11 @@
Gems_Html::init();
- return $this->loader->getUserLoader()->getLoginForm($args);
+ if ($this->layeredLogin === true) {
+ return $this->loader->getUserLoader()->getLayeredLoginForm($args);
+ } else {
+ return $this->loader->getUserLoader()->getLoginForm($args);
+ }
}
/**
@@ -208,7 +220,7 @@
$previousRequestParameters = $staticSession->previousRequestParameters;
$previousRequestMode = $staticSession->previousRequestMode;
- if ($request->isPost()) {
+ if ($form->wasSubmitted()) {
if ($form->isValid($request->getPost(), false)) {
$user = $form->getUser();
$user->setAsCurrentUser();
@@ -258,6 +270,10 @@
$log = Gems_AccessLog::getLog();
$log->log('loginFail', $this->getRequest(), $msg, null, true);
} // */
+ } else {
+ if ($request->isPost()) {
+ $form->populate($this->getRequest()->getPost());
+ }
}
$this->displayLoginForm($form);
Added: trunk/library/classes/Gems/User/Form/LayeredLoginForm.php
===================================================================
--- trunk/library/classes/Gems/User/Form/LayeredLoginForm.php (rev 0)
+++ trunk/library/classes/Gems/User/Form/LayeredLoginForm.php 2012-07-18 08:01:04 UTC (rev 852)
@@ -0,0 +1,248 @@
+<?php
+
+/**
+ * Copyright (c) 2011, Erasmus MC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Erasmus MC nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Short description of file
+ *
+ * @package Gems
+ * @subpackage
+ * @copyright Copyright (c) 2011 Erasmus MC
+ * @license New BSD License
+ * @version $Id: Sample.php 215 2011-07-12 08:52:54Z michiel $
+ */
+
+/**
+ * Short description for LoginForm
+ *
+ * Long description for class LoginForm (if any)...
+ *
+ * @package Gems
+ * @subpackage Sample
+ * @copyright Copyright (c) 2011 Erasmus MC
+ * @license New BSD License
+ * @since Class available since version 1.0
+ * @deprecated Class deprecated since version 2.0
+ */
+class Gems_User_Form_LayeredLoginForm extends Gems_User_Form_LoginForm
+{
+ /**
+ * @var Zend_Db_Adapter_Abstract
+ */
+ public $db;
+
+ /**
+ * The field name for the top organization element.
+ *
+ * @var string
+ */
+ public $topOrganizationFieldName = 'toporganization';
+
+ /**
+ * Return array of organizations that are a child of the given parentId
+ *
+ * @param int $parentId
+ * @return array
+ */
+ public function getChildOrganisations($parentId = null)
+ {
+ if (is_null($parentId)) {
+ return array();
+ }
+
+ try {
+ $organizations = $this->db->fetchPairs('SELECT gor_id_organization, gor_name FROM gems__organizations WHERE gor_active=1 AND gor_has_login=1 AND (gor_accessible_by LIKE ' . $this->db->quote(':' . $parentId . ':') . ' OR gor_id_organization = ' . $this->db->quote($parentId) . ') ORDER BY gor_name');
+ } catch (Exception $e) {
+ try {
+ // 1.4 fallback
+ $organizations = $this->db->fetchPairs('SELECT gor_id_organization, gor_name FROM gems__organizations WHERE gor_active=1 AND (gor_accessible_by LIKE ' . $this->db->quote(':' . $parentId . ':') . ' OR gor_id_organization = ' . $this->db->quote($parentId) . ') ORDER BY gor_name');
+ } catch (Exception $e) {
+ $organizations = array();
+ }
+ }
+
+ natsort($organizations);
+
+ return $organizations;
+ }
+
+ /**
+ * Returns the top organization id that should currently be used for this form.
+ *
+ * @return int Returns the current organization id, if any
+ */
+ public function getCurrentTopOrganizationId()
+ {
+ $userLoader = $this->loader->getUserLoader();
+
+ // Url determines organization first.
+ if ($orgId = $userLoader->getOrganizationIdByUrl()) {
+ $this->_organizationFromUrl = true;
+ return ' ';
+ }
+
+ $request = $this->getRequest();
+ if ($request->isPost() && ($orgId = $request->getParam($this->topOrganizationFieldName))) {
+ Gems_Cookies::set('gems_toporganization', $orgId);
+ return $orgId;
+ } else {
+ return Gems_Cookies::get($this->getRequest(), 'gems_toporganization', ' ');
+ }
+ }
+
+ /**
+ * Returns/sets an element for determining / selecting the organization.
+ *
+ * Depends on the top-organization
+ *
+ * @return Zend_Form_Element_Xhtml
+ */
+ public function getOrganizationElement()
+ {
+ $element = $this->getElement($this->organizationFieldName);
+ $orgId = $this->getCurrentOrganizationId();
+ $parentId = $this->getCurrentTopOrganizationId();
+ $childOrgs = $this->getChildOrganisations($parentId);
+
+ if (!empty($childOrgs)) {
+ if (count($childOrgs) == 1) {
+ $element = new Zend_Form_Element_Hidden($this->organizationFieldName);
+ $this->addElement($element);
+
+ if (! $this->_organizationFromUrl) {
+ $orgIds = array_keys($childOrgs);
+ $orgId = reset($orgIds);
+ }
+
+ $element->setValue($orgId);
+ $this->getRequest()->setPost($this->organizationFieldName, $orgId);
+
+ } else {
+ $element = new Zend_Form_Element_Select($this->organizationFieldName);
+ $element->setLabel($this->translate->_('Organization'));
+ $element->setRegisterInArrayValidator(true);
+ $element->setRequired(true);
+ $element->setMultiOptions($childOrgs);
+
+ if ($this->organizationMaxLines > 1) {
+ $element->setAttrib('size', min(count($orgs) + 1, $this->organizationMaxLines));
+ }
+ $this->addElement($element);
+ $element->setValue($orgId);
+ }
+ }
+
+ return $element;
+ }
+
+ /**
+ * Return a list of organizations that are considered top-organizations, in this
+ * case organizations that are not accessible by others as they are considered
+ * the children of the top organizations. Feel free to modify to suit your
+ * needs.
+ *
+ * @return array
+ */
+ public function getTopOrganisations()
+ {
+ try {
+ $organizations = $this->db->fetchPairs('SELECT gor_id_organization, gor_name FROM gems__organizations WHERE gor_active=1 AND gor_has_login=1 AND gor_accessible_by IS NULL ORDER BY gor_name');
+ } catch (Exception $e) {
+ try {
+ // 1.4 fallback
+ $organizations = $this->db->fetchPairs('SELECT gor_id_organization, gor_name FROM gems__organizations WHERE gor_active=1 AND gor_accessible_by IS NULL ORDER BY gor_name');
+ } catch (Exception $e) {
+ $organizations = array();
+ }
+ }
+
+ natsort($organizations);
+
+ return $organizations;
+ }
+
+
+ /**
+ * Returns/sets an element for determining / selecting the top-organization.
+ *
+ * @return null|\Zend_Form_Element_Select
+ */
+ public function getTopOrganizationElement()
+ {
+ $element = $this->getElement($this->topOrganizationFieldName);
+ $orgId = $this->getCurrentTopOrganizationId();
+ $orgs = $this->getTopOrganisations();
+ $hidden = $this->_organizationFromUrl || (count($orgs) < 2);
+
+ if ($this->_organizationFromUrl) {
+ return null;
+ }
+
+ if ($hidden) {
+ if (! $element instanceof Zend_Form_Element_Hidden) {
+ $element = new Zend_Form_Element_Hidden($this->topOrganizationFieldName);
+ $this->addElement($element);
+ }
+
+ $orgIds = array_keys($orgs);
+ $orgId = reset($orgIds);
+
+ $element->setValue($orgId);
+
+ } elseif (! $element instanceof Zend_Form_Element_Select) {
+ $element = new Zend_Form_Element_Select($this->topOrganizationFieldName);
+ $element->setLabel($this->translate->_('Organization'));
+ $element->setRegisterInArrayValidator(true);
+ $element->setRequired(true);
+ $element->setMultiOptions($orgs);
+ $element->setAttrib('onchange', 'this.form.submit();');
+
+ if ($this->organizationMaxLines > 1) {
+ $element->setAttrib('size', min(count($orgs) + 1, $this->organizationMaxLines));
+ }
+ $this->addElement($element);
+
+ $element->setValue($orgId);
+ }
+
+ return $element;
+ }
+
+ /**
+ * Load the elements, starting with the extra top organization element and
+ * continue with the other elements like in the standard login form
+ *
+ * @return Gems_User_Form_LayeredLoginForm
+ */
+ public function loadDefaultElements()
+ {
+ $this->getTopOrganizationElement();
+
+ parent::loadDefaultElements();
+
+ return $this;
+ }
+}
\ No newline at end of file
Modified: trunk/library/classes/Gems/User/Form/OrganizationFormAbstract.php
===================================================================
--- trunk/library/classes/Gems/User/Form/OrganizationFormAbstract.php 2012-07-17 15:55:22 UTC (rev 851)
+++ trunk/library/classes/Gems/User/Form/OrganizationFormAbstract.php 2012-07-18 08:01:04 UTC (rev 852)
@@ -284,6 +284,12 @@
*/
public function wasSubmitted()
{
- return $this->getSubmitButton()->isChecked();
+ // If form was not (yet) populated, we can not use isChecked() so do this manually
+ $request = $this->getRequest();
+ if ($request->isPost() && $request->getPost($this->_submitFieldName) == $this->getSubmitButtonLabel()) {
+ return true;
+ } else {
+ return false;
+ }
}
}
Modified: trunk/library/classes/Gems/User/UserLoader.php
===================================================================
--- trunk/library/classes/Gems/User/UserLoader.php 2012-07-17 15:55:22 UTC (rev 851)
+++ trunk/library/classes/Gems/User/UserLoader.php 2012-07-18 08:01:04 UTC (rev 852)
@@ -305,6 +305,20 @@
}
/**
+ * Returns a layered login form where user first selects a top organization and then a
+ * child organization
+ *
+ * @param mixed $args_array MUtil_Ra::args array for LoginForm initiation.
+ * @return Gems_User_Form_LayeredLoginForm
+ */
+ public function getLayeredLoginForm($args_array = null)
+ {
+ $args = MUtil_Ra::args(func_get_args());
+
+ return $this->_loadClass('Form_LayeredLoginForm', true, array($args));
+ }
+
+ /**
* Returns a login form
*
* @param mixed $args_array MUtil_Ra::args array for LoginForm initiation.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|