From: <gem...@li...> - 2013-02-28 17:40:34
|
Revision: 1167 http://sourceforge.net/p/gemstracker/code/1167 Author: matijsdejong Date: 2013-02-28 17:40:31 +0000 (Thu, 28 Feb 2013) Log Message: ----------- FormBridge.php supports FakeSubmit elements ModelSnippetActionAbstract can now apply multicolumn display through getBrowseColumns() Moving RespondentModel.php settings to object itself ModelTabFormSnippetGeneric.php now knows how to generate tabbed forms from the Model/RespondentModel.php Small generalization of TabForm.php DbLookup->getOrganizationsWithRespondents() shows all organizations that could have a respondent Translated->formatDateTime returns null when the date input is not a real date Started on RespondentNewAction.php Modified Paths: -------------- trunk/library/classes/Gems/Communication/RespondentModelWriter.php trunk/library/classes/Gems/Model/RespondentModel.php trunk/library/classes/Gems/Snippets/ModelTabFormSnippetGeneric.php trunk/library/classes/Gems/TabForm.php trunk/library/classes/Gems/Util/DbLookup.php trunk/library/classes/Gems/Util/Translated.php trunk/library/classes/MUtil/Controller/ModelSnippetActionAbstract.php trunk/library/classes/MUtil/Model/FormBridge.php trunk/library/classes/MUtil/Snippets/ModelTableSnippetAbstract.php trunk/library/snippets/Organization/ChooseOrganizationSnippet.php Added Paths: ----------- trunk/library/classes/Gems/Default/RespondentNewAction.php Modified: trunk/library/classes/Gems/Communication/RespondentModelWriter.php =================================================================== --- trunk/library/classes/Gems/Communication/RespondentModelWriter.php 2013-02-28 15:13:09 UTC (rev 1166) +++ trunk/library/classes/Gems/Communication/RespondentModelWriter.php 2013-02-28 17:40:31 UTC (rev 1167) @@ -3,7 +3,7 @@ /** * 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 @@ -14,7 +14,7 @@ * * 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 @@ -32,7 +32,7 @@ /** * Writer implementation to save respondents to the database - * + * * @author Michiel Rook <mi...@to...> * @version $Id$ * @package Gems @@ -44,22 +44,22 @@ * @var Gems_Model_RespondentModel */ private $_model = null; - + public function __construct() { - $this->_model = GemsEscort::getInstance()->getLoader()->getModels()->getRespondentModel(true); + $this->_model = GemsEscort::getInstance()->getLoader()->getModels()->createRespondentModel(); } - + /** * - Fetches respondent based on bsn / reception code and patient nr * - Creates the respondent if it does not exist, updates otherwise - * + * * @see Gems_Model_RespondentModel * @see Gems_Communication_RespondentWriter::writeRespondent() * * @param Gems_Communication_RespondentContainer $respondent * @param int $userId - * @return boolean True if a new respondent was added, false if one was updated + * @return boolean True if a new respondent was added, false if one was updated */ public function writeRespondent(Gems_Communication_RespondentContainer $respondent, &$userId) { @@ -70,17 +70,17 @@ 'gr2o_patient_nr' => $respondent->getPatientId() ) ); - + $data = $this->_model->loadFirst(); $isNew = false; - + if (empty($data)) { $isNew = true; $data = $this->_model->loadNew(); } - + unset($data['grs_email']); - + $data['gr2o_patient_nr'] = $respondent->getPatientId(); $data['grs_first_name'] = $respondent->getFirstName(); $data['grs_last_name'] = $respondent->getLastName(); @@ -88,11 +88,11 @@ $data['grs_ssn'] = $respondent->getBsn(); $data['grs_gender'] = $respondent->getGender(); $data['grs_birthday'] = $respondent->getBirthday(); - + $data = $this->_model->save($data); - + $userId = $data['grs_id_user']; - + return $isNew; } } \ No newline at end of file Added: trunk/library/classes/Gems/Default/RespondentNewAction.php =================================================================== --- trunk/library/classes/Gems/Default/RespondentNewAction.php (rev 0) +++ trunk/library/classes/Gems/Default/RespondentNewAction.php 2013-02-28 17:40:31 UTC (rev 1167) @@ -0,0 +1,159 @@ +<?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 <COPYRIGHT HOLDER> 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. + * + * + * @package Gems + * @subpackage Default + * @author Matijs de Jong <mj...@ma...> + * @copyright Copyright (c) 2011 Erasmus MC + * @license New BSD License + * @version $Id: RespondentNewAction.php$ + */ + +/** + * + * + * @package Gems + * @subpackage Default + * @copyright Copyright (c) 2011 Erasmus MC + * @license New BSD License + * @since Class available since version 1.6 + */ +abstract class Gems_Default_RespondentNewAction extends Gems_Controller_ModelSnippetActionAbstract +{ + /** + * The snippets used for the create and edit actions. + * + * @var mixed String or array of snippets name + */ + protected $createEditSnippets = 'ModelTabFormSnippetGeneric'; + + /** + * + * @var Gems_Loader + */ + public $loader; + + /** + * Creates a model for getModel(). Called only for each new $action. + * + * The parameters allow you to easily adapt the model to the current action. The $detailed + * parameter was added, because the most common use of action is a split between detailed + * and summarized actions. + * + * @param boolean $detailed True when the current action is not in $summarizedActions. + * @param string $action The current action. + * @return MUtil_Model_ModelAbstract + */ + protected function createModel($detailed, $action) + { + $model = $this->loader->getModels()->createRespondentModel(); + + if (! $detailed) { + return $model->applyBrowseSettings(); + } + + switch ($action) { + case 'create': + case 'edit': + return $model->applyEditSettings(); + + default: + return $model->applyDetailSettings(); + } + } + + /** + * Set column usage to use for the browser. + * + * Must be an array of arrays containing the input for TableBridge->setMultisort() + * + * @return array or false + */ + public function getBrowseColumns() + { + $model = $this->getModel(); + + $model->setIfExists('gr2o_opened', 'tableDisplay', 'small'); + $model->setIfExists('grs_email', 'formatFunction', 'MUtil_Html_AElement::ifmail'); + + // Newline placeholder + $br = MUtil_Html::create('br'); + + // Display separator and phone sign only if phone exist. + $phonesep = MUtil_Html::raw('☏ '); // $bridge->itemIf($bridge->grs_phone_1, MUtil_Html::raw('☏ ')); + $citysep = MUtil_Html::raw(' '); // $bridge->itemIf($bridge->grs_zipcode, MUtil_Html::raw(' ')); + + if ($this->loader->getCurrentUser()->hasPrivilege('pr.respondent.multiorg')) { + $columns[] = array('gr2o_patient_nr', $br, 'gr2o_id_organization'); + } else { + $columns[] = array('gr2o_patient_nr', $br, 'gr2o_opened'); + } + $columns[] = array('name', $br, 'grs_email'); + $columns[] = array('grs_address_1', $br, 'grs_zipcode', $citysep, 'grs_city'); + $columns[] = array('grs_birthday', $br, $phonesep, 'grs_phone_1'); + + return $columns; + } + + /** + * Helper function to get the title for the index action. + * + * @return $string + */ + public function getIndexTitle() + { + return $this->_('Respondents'); + } + + /** + * Helper function to allow generalized statements about the items in the model. + * + * @param int $count + * @return $string + */ + public function getTopic($count = 1) + { + return $this->plural('respondent', 'respondents', $count);; + } + + /** + * Overrule default index for the case that the current + * organization cannot have users. + */ + public function indexAction() + { + $user = $this->loader->getCurrentUser(); + + if ($user->hasPrivilege('pr.respondent.multiorg') || $user->getCurrentOrganization()->canHaveRespondents()) { + parent::indexAction(); + } else { + $this->addSnippet('Organization_ChooseOrganizationSnippet'); + } + } +} Modified: trunk/library/classes/Gems/Model/RespondentModel.php =================================================================== --- trunk/library/classes/Gems/Model/RespondentModel.php 2013-02-28 15:13:09 UTC (rev 1166) +++ trunk/library/classes/Gems/Model/RespondentModel.php 2013-02-28 17:40:31 UTC (rev 1167) @@ -69,6 +69,14 @@ */ protected $project; + /** + * @var Gems_Util + */ + protected $util; + + /** + * Self constructor + */ public function __construct() { // gems__respondents MUST be first table for INSERTS!! @@ -84,8 +92,12 @@ $this->setOnSave('gr2o_opened_by', GemsEscort::getInstance()->session->user_id); $this->setSaveOnChange('gr2o_opened_by'); + if (! $this->has('grs_ssn')) { + $this->hashSsn = self::SSN_HIDE; + } if (self::SSN_HASH === $this->hashSsn) { - $this->setSaveWhenNotNull('grs_ssn'); + $this->setSaveWhen('grs_ssn', array($this, 'whenSSN')); + $this->setOnLoad('grs_ssn', array($this, 'saveSSN')); $this->setOnSave('grs_ssn', array($this, 'formatSSN')); } } @@ -145,6 +157,201 @@ } /** + * Set those settings needed for the browse display + * + * @return \Gems_Model_RespondentModel + */ + public function applyBrowseSettings() + { + $dbLookup = $this->util->getDbLookup(); + $translated = $this->util->getTranslated(); + $translator = $this->translate->getAdapter(); + + $this->resetOrder(); + + if ($this->has('gr2o_id_organization') && $this->isMultiOrganization()) { + $this->set('gr2o_id_organization', + 'label', $translator->_('Organization'), + 'multiOptions', $dbLookup->getOrganizationsWithRespondents() + ); + } + + $this->setIfExists('gr2o_patient_nr', 'label', $translator->_('Respondent nr')); + + $this->set('name', + 'label', $translator->_('Name'), + 'column_expression', "CONCAT( + COALESCE(CONCAT(grs_last_name, ', '), '-, '), + COALESCE(CONCAT(grs_first_name, ' '), ''), + COALESCE(grs_surname_prefix, ''))", + 'fieldlist', array('grs_last_name', 'grs_first_name', 'grs_surname_prefix')); + + $this->setIfExists('grs_email', 'label', $translator->_('E-Mail')); + + $this->setIfExists('grs_address_1', 'label', $translator->_('Street')); + $this->setIfExists('grs_zipcode', 'label', $translator->_('Zipcode')); + $this->setIfExists('grs_city', 'label', $translator->_('City')); + + $this->setIfExists('grs_phone_1', 'label', $translator->_('Phone')); + + $this->setIfExists('grs_birthday', + 'label', $translator->_('Birthday'), + 'dateFormat', Zend_Date::DATE_MEDIUM); + + $this->setIfExists('gr2o_opened', + 'label', $translator->_('Opened'), + 'formatFunction', $translated->formatDateTime); + $this->setIfExists('gr2o_consent', + 'label', $translator->_('Consent'), + 'multiOptions', $dbLookup->getUserConsents() + ); + + return $this; + } + + /** + * Set those settings needed for the detailed display + * + * @param mixed $locale The locale for the settings + * @return \Gems_Model_RespondentModel + */ + public function applyDetailSettings($locale = null) + { + $dbLookup = $this->util->getDbLookup(); + $translated = $this->util->getTranslated(); + $translator = $this->translate->getAdapter(); + + $this->resetOrder(); + if ($this->has('gr2o_id_organization')) { + $this->set('gr2o_id_organization', + 'label', $translator->_('Organization'), + 'tab', $translator->_('Identification') + ); + + if ($this->isMultiOrganization()) { + $user = $this->loader->getCurrentUser(); + + $this->set('gr2o_id_organization', + 'default', $user->getCurrentOrganizationId(), + 'multiOptions', $user->getRespondentOrganizations() + ); + } + } + + // The SSN + if ($this->hashSsn !== Gems_Model_RespondentModel::SSN_HIDE) { + $this->set('grs_ssn', 'label', $translator->_('SSN')); + } + + $this->setIfExists('gr2o_patient_nr', 'label', $translator->_('Respondent number')); + + $this->setIfExists('grs_first_name', 'label', $translator->_('First name')); + $this->setIfExists('grs_surname_prefix', + 'label', $translator->_('Surname prefix'), + 'description', $translator->_('de, van der, \'t, etc...') + ); + $this->setIfExists('grs_last_name', 'label', $translator->_('Last name')); + + $this->setIfExists('grs_gender', + 'label', $translator->_('Gender'), + 'multiOptions', $translated->getGenderHello() + ); + + $this->setIfExists('grs_email', 'label', $translator->_('E-Mail')); + + $this->setIfExists('grs_address_1', 'label', $translator->_('Street')); + $this->setIfExists('grs_zipcode', 'label', $translator->_('Zipcode')); + $this->setIfExists('grs_city', 'label', $translator->_('City')); + + $this->setIfExists('grs_phone_1', 'label', $translator->_('Phone')); + + $this->setIfExists('grs_birthday', + 'label', $translator->_('Birthday'), + 'dateFormat', Zend_Date::DATE_MEDIUM + ); + + $this->setIfExists('gr2o_opened', + 'label', $translator->_('Opened'), + 'formatFunction', $translated->formatDateTime + ); + + $this->setIfExists('gr2o_consent', + 'label', $translator->_('Consent'), + 'multiOptions', $dbLookup->getUserConsents() + ); + + $this->set('gr2o_comments', 'label', $translator->_('Comments')); + $this->set('gr2o_treatment', 'label', $translator->_('Treatment')); + + $this->addColumn('CASE WHEN grs_email IS NULL OR LENGTH(TRIM(grs_email)) = 0 THEN 1 ELSE 0 END', 'calc_email'); + + return $this; + } + + /** + * Set those values needed for editing + * + * @param mixed $locale The locale for the settings + * @return \Gems_Model_RespondentModel + */ + public function applyEditSettings($locale = null) + { + $this->applyDetailSettings($locale); + $this->copyKeys(); // The user can edit the keys. + + $translated = $this->util->getTranslated(); + $translator = $this->translate->getAdapter(); + $ucfirst = new Zend_Filter_Callback('ucfirst'); + + if ($this->hashSsn !== Gems_Model_RespondentModel::SSN_HIDE) { + $this->set('grs_ssn', + 'size', 10, + 'maxlength', 12, + 'filter', 'Digits'); + + if (APPLICATION_ENV !== 'production') { + $bsn = new MUtil_Validate_Dutch_Burgerservicenummer(); + $num = mt_rand(100000000, 999999999); + + while (! $bsn->isValid($num)) { + $num++; + } + + $this->setIfExists('grs_ssn', 'description', sprintf($translator->_('Random Example BSN: %s'), $num)); + } else { + $this->setIfExists('grs_ssn', 'description', $translator->_('Enter a 9-digit SSN number.')); + } + } + + $this->setIfExists('gr2o_patient_nr', + 'size', 15, + 'minlength', 4, + 'validator', $this->createUniqueValidator( + array('gr2o_patient_nr', 'gr2o_id_organization'), + array('gr2o_id_user' => 'grs_id_user', 'gr2o_id_organization') + ) + ); + + $this->setIfExists('grs_first_name', 'filter', $ucfirst); + $this->setIfExists('grs_last_name', 'filter', $ucfirst, 'required', true); + + $this->setIfExists('grs_gender', + 'elementClass', 'Radio', + 'separator', '', + 'multiOptions', $translated->getGenders(), + 'tab', $translator->_('Medical data') + ); + + $this->setIfExists('gr2o_opened', 'elementClass', 'Exhibitor'); + + $this->setIfExists('gr2o_consent', 'default', $this->util->getDefaultConsent()); + + $this->setIfExists('grs_iso_lang', 'default', 'nl'); + + return $this; + } + + /** * Apply hash function for array_walk_recursive in _checkFilterUsed() * * @see _checkFilterUsed() @@ -159,22 +366,6 @@ } } - /** - * Return a hashed version of the input value. - * - * @param mixed $value The value being saved - * @param boolean $isNew True when a new item is being saved - * @param string $name The name of the current field - * @param array $context Optional, the other values being saved - * @return string The salted hash as a 32-character hexadecimal number. - */ - public function formatSSN($value, $isNew = false, $name = null, array $context = array()) - { - if ($value) { - return $this->project->getValueHash($value); - } - } - public function copyKeys($reset = false) { $keys = $this->_getKeysFor('gems__respondent2org'); @@ -196,6 +387,22 @@ } /** + * Return a hashed version of the input value. + * + * @param mixed $value The value being saved + * @param boolean $isNew True when a new item is being saved + * @param string $name The name of the current field + * @param array $context Optional, the other values being saved + * @return string The output to display + */ + public function hideSSN($value, $isNew = false, $name = null, array $context = array()) + { + if ($value) { + return str_repeat('*', 9); + } + } + + /** * True when the default filter can contain multiple organizations * * @return boolean @@ -205,5 +412,35 @@ // return ($this->user->hasPrivilege('pr.respondent.multiorg') && (! $this->user->getCurrentOrganization()->canHaveRespondents())); return $this->user->hasPrivilege('pr.respondent.multiorg'); } + + /** + * Return a hashed version of the input value. + * + * @param mixed $value The value being saved + * @param boolean $isNew True when a new item is being saved + * @param string $name The name of the current field + * @param array $context Optional, the other values being saved + * @return string The salted hash as a 32-character hexadecimal number. + */ + public function saveSSN($value, $isNew = false, $name = null, array $context = array()) + { + if ($value) { + return $this->project->getValueHash($value); + } + } + + /** + * Return a hashed version of the input value. + * + * @param mixed $value The value being saved + * @param boolean $isNew True when a new item is being saved + * @param string $name The name of the current field + * @param array $context Optional, the other values being saved + * @return boolean + */ + public function whenSSN($value, $isNew = false, $name = null, array $context = array()) + { + return $value && ($value !== $this->hideSSN($value, $isNew, $name, $context)); + } } Modified: trunk/library/classes/Gems/Snippets/ModelTabFormSnippetGeneric.php =================================================================== --- trunk/library/classes/Gems/Snippets/ModelTabFormSnippetGeneric.php 2013-02-28 15:13:09 UTC (rev 1166) +++ trunk/library/classes/Gems/Snippets/ModelTabFormSnippetGeneric.php 2013-02-28 17:40:31 UTC (rev 1167) @@ -54,6 +54,67 @@ protected $_form; /** + * Adds elements from the model to the bridge that creates the form. + * + * Overrule this function to add different elements to the browse table, without + * having to recode the core table building code. + * + * @param MUtil_Model_FormBridge $bridge + * @param MUtil_Model_ModelAbstract $model + */ + protected function addFormElements(MUtil_Model_FormBridge $bridge, MUtil_Model_ModelAbstract $model) + { + //Get all elements in the model if not already done + $this->initItems(); + + // Add 'tooltip' to the allowed displayoptions + $displayOptions = $bridge->getAllowedOptions(MUtil_Model_FormBridge::DISPLAY_OPTIONS); + if (!array_search('tooltip', $displayOptions)) { + $displayOptions[] = 'tooltip'; + } + $bridge->setAllowedOptions(MUtil_Model_FormBridge::DISPLAY_OPTIONS, $displayOptions); + + $tab = 0; + $group = 0; + foreach ($model->getItemsOrdered() as $name) { + // Get all options at once + $modelOptions = $model->get($name); + if ($tabName = $model->get($name, 'tab')) { + $bridge->addTab('tab' . $tab, 'value', $tabName); + $tab++; + } + + if ($model->has($name, 'label')) { + $bridge->add($name); + + if ($theName = $model->get('startGroup')) { + //We start a new group here! + $groupElements = array(); + $groupElements[] = $name; + $groupName = $theName; + } elseif ($theName = $model->get('endGroup')) { + //Ok, last element define the group + $groupElements[] = $name; + $bridge->addDisplayGroup('grp_' . $groupElements[0], $groupElements, + 'description', $groupName, + 'showLabels', ($theName == 'showLabels'), + 'class', 'grp' . $group); + $group++; + unset($groupElements); + unset($groupName); + } else { + //If we are in a group, add the elements to the group + if (isset($groupElements)) { + $groupElements[] = $name; + } + } + } else { + $bridge->addHidden($name); + } + } + } + + /** * Simple default function for making sure there is a $this->_saveButton. * * As the save button is not part of the model - but of the interface - it Modified: trunk/library/classes/Gems/TabForm.php =================================================================== --- trunk/library/classes/Gems/TabForm.php 2013-02-28 15:13:09 UTC (rev 1166) +++ trunk/library/classes/Gems/TabForm.php 2013-02-28 17:40:31 UTC (rev 1167) @@ -128,7 +128,9 @@ */ public function addTab($name, $title) { - if ($title instanceof MUtil_Html_Sequence) $title = $title->render($form->getView()); + if ($title instanceof MUtil_Html_HtmlInterface) { + $title = $title->render($this->getView()); + } $tab = new Gems_Form_TabSubForm(array('name' => $name, 'title' => strip_tags($title))); $this->currentTab = $tab; $this->addSubForm($tab, $name); @@ -247,13 +249,13 @@ * As addElement and addDisplayGroup provide a fluent way of working with subforms * we need to provide a method to skip back to the main form again. */ - public function resetContext() { + public function resetContext() { $this->currentTab = null; } /** * Select a tab by it's numerical index - * + * * @param int $tabIdx */ public function selectTab($tabIdx) { @@ -276,7 +278,7 @@ } parent::setView($view); - + if ($this->_view !== $view) { $this->activateJQuery(); if (false === $view->getPluginLoader('helper')->getPaths('Gems_JQuery_View_Helper')) { Modified: trunk/library/classes/Gems/Util/DbLookup.php =================================================================== --- trunk/library/classes/Gems/Util/DbLookup.php 2013-02-28 15:13:09 UTC (rev 1166) +++ trunk/library/classes/Gems/Util/DbLookup.php 2013-02-28 17:40:31 UTC (rev 1167) @@ -337,7 +337,12 @@ static $organizations; if (! $organizations) { - $organizations = $this->db->fetchPairs('SELECT gor_id_organization, gor_name FROM gems__organizations WHERE gor_active=1 AND gor_has_respondents=1 ORDER BY gor_name'); + $organizations = $this->db->fetchPairs( + 'SELECT gor_id_organization, gor_name + FROM gems__organizations + WHERE gor_active = 1 AND (gor_has_respondents = 1 OR gor_add_respondents = 1) + ORDER BY gor_name' + ); natsort($organizations); } Modified: trunk/library/classes/Gems/Util/Translated.php =================================================================== --- trunk/library/classes/Gems/Util/Translated.php 2013-02-28 15:13:09 UTC (rev 1166) +++ trunk/library/classes/Gems/Util/Translated.php 2013-02-28 17:40:31 UTC (rev 1167) @@ -126,48 +126,50 @@ public function formatDateTime($dateTimeValue) { - if ($dateTimeValue) { - //$dateTime = strtotime($dateTimeValue); - // MUtil_Echo::track($dateTimeValue, date('c', $dateTime), $dateTime / 86400, date('c', time()), time() / 86400); - // TODO: Timezone seems to screw this one up - //$days = floor($dateTime / 86400) - floor(time() / 86400); // 86400 = 24*60*60 - if ($dateTimeValue instanceof MUtil_Date) { - $dateTime = clone $dateTimeValue; - } else { - $dateTime = new MUtil_Date($dateTimeValue, Zend_Date::ISO_8601); - } - $days = $dateTime->diffDays(); + if (! $dateTimeValue) { + return null; + } - switch ($days) { - case -2: - return $this->_('2 days ago'); + //$dateTime = strtotime($dateTimeValue); + // MUtil_Echo::track($dateTimeValue, date('c', $dateTime), $dateTime / 86400, date('c', time()), time() / 86400); + // TODO: Timezone seems to screw this one up + //$days = floor($dateTime / 86400) - floor(time() / 86400); // 86400 = 24*60*60 + if ($dateTimeValue instanceof MUtil_Date) { + $dateTime = clone $dateTimeValue; + } elseif (MUtil_Date::isDate($dateTimeValue, Zend_Date::ISO_8601)) { + $dateTime = new MUtil_Date($dateTimeValue, Zend_Date::ISO_8601); + } else { + return null; + } + $days = $dateTime->diffDays(); - case -1: - return $this->_('Yesterday'); + switch ($days) { + case -2: + return $this->_('2 days ago'); - case 0: - return $this->_('Today'); + case -1: + return $this->_('Yesterday'); - case 1: - return $this->_('Tomorrow'); + case 0: + return $this->_('Today'); - case 2: - return $this->_('Over 2 days'); + case 1: + return $this->_('Tomorrow'); - default: - if (($days > -14) && ($days < 14)) { - if ($days > 0) { - return sprintf($this->_('Over %d days'), $days); - } else { - return sprintf($this->_('%d days ago'), -$days); - } + case 2: + return $this->_('Over 2 days'); + + default: + if (($days > -14) && ($days < 14)) { + if ($days > 0) { + return sprintf($this->_('Over %d days'), $days); + } else { + return sprintf($this->_('%d days ago'), -$days); } + } - return date($this->phpDateFormatString, $dateTime->getTimestamp()); // . ' (' . $days . ')'; - } + return date($this->phpDateFormatString, $dateTime->getTimestamp()); // . ' (' . $days . ')'; } - - return null; } /** Modified: trunk/library/classes/MUtil/Controller/ModelSnippetActionAbstract.php =================================================================== --- trunk/library/classes/MUtil/Controller/ModelSnippetActionAbstract.php 2013-02-28 15:13:09 UTC (rev 1166) +++ trunk/library/classes/MUtil/Controller/ModelSnippetActionAbstract.php 2013-02-28 17:40:31 UTC (rev 1167) @@ -113,7 +113,7 @@ * * @var array Mixed key => value array for snippet initialization */ - protected $autofilterParameters = array(); + protected $autofilterParameters = array('columns' => 'getBrowseColumns'); /** * The snippets used for the autofilter action. @@ -380,6 +380,18 @@ } /** + * Set column usage to use for the browser. + * + * Must be an array of arrays containing the input for TableBridge->setMultisort() + * + * @return array or false + */ + public function getBrowseColumns() + { + return false; + } + + /** * Returns the model for the current $action. * * The parameters allow you to easily adapt the model to the current action. The $detailed Modified: trunk/library/classes/MUtil/Model/FormBridge.php =================================================================== --- trunk/library/classes/MUtil/Model/FormBridge.php 2013-02-28 15:13:09 UTC (rev 1166) +++ trunk/library/classes/MUtil/Model/FormBridge.php 2013-02-28 17:40:31 UTC (rev 1167) @@ -50,19 +50,20 @@ */ class MUtil_Model_FormBridge { - const AUTO_OPTIONS = 'auto'; - const CHECK_OPTIONS = 'check'; - const DATE_OPTIONS = 'date'; - const DISPLAY_OPTIONS = 'display'; - const EXHIBIT_OPTIONS = 'exhibit'; - const FILE_OPTIONS = 'file'; - const GROUP_OPTIONS = 'displaygroup'; - const JQUERY_OPTIONS = 'jquery'; - const MULTI_OPTIONS = 'multi'; - const PASSWORD_OPTIONS = 'password'; - const TAB_OPTIONS = 'tab'; - const TEXT_OPTIONS = 'text'; - const TEXTAREA_OPTIONS = 'textarea'; + const AUTO_OPTIONS = 'auto'; + const CHECK_OPTIONS = 'check'; + const DATE_OPTIONS = 'date'; + const DISPLAY_OPTIONS = 'display'; + const EXHIBIT_OPTIONS = 'exhibit'; + const FAKESUBMIT_OPTIONS = 'fakesubmit'; + const FILE_OPTIONS = 'file'; + const GROUP_OPTIONS = 'displaygroup'; + const JQUERY_OPTIONS = 'jquery'; + const MULTI_OPTIONS = 'multi'; + const PASSWORD_OPTIONS = 'password'; + const TAB_OPTIONS = 'tab'; + const TEXT_OPTIONS = 'text'; + const TEXTAREA_OPTIONS = 'textarea'; /** * The key to use in the Zend_Registry to store global fixed options @@ -82,19 +83,20 @@ // First list html attributes, then Zend attributes, lastly own attributes private $_allowedOptions = array( - self::AUTO_OPTIONS => array('elementClass', 'multiOptions'), - self::CHECK_OPTIONS => array('checkedValue', 'uncheckedValue'), - self::DATE_OPTIONS => array('dateFormat', 'storageFormat'), - self::DISPLAY_OPTIONS => array('accesskey', 'autoInsertNotEmptyValidator', 'class', 'disabled', 'description', 'escape', 'label', 'onclick', 'readonly', 'required', 'tabindex', 'value', 'showLabels', 'labelplacement'), - self::EXHIBIT_OPTIONS => array('formatFunction'), - self::FILE_OPTIONS => array('accept', 'count', 'destination', 'valueDisabled'), - self::GROUP_OPTIONS => array('elements', 'legend', 'separator'), - self::JQUERY_OPTIONS => array('jQueryParams'), - self::MULTI_OPTIONS => array('disable', 'multiOptions', 'onchange', 'separator', 'size', 'disableTranslator'), - self::PASSWORD_OPTIONS => array('repeatLabel'), - self::TAB_OPTIONS => array('value'), - self::TEXT_OPTIONS => array('maxlength', 'minlength', 'onchange', 'onfocus', 'onselect', 'size'), - self::TEXTAREA_OPTIONS => array('cols', 'rows', 'wrap'), + self::AUTO_OPTIONS => array('elementClass', 'multiOptions'), + self::CHECK_OPTIONS => array('checkedValue', 'uncheckedValue'), + self::DATE_OPTIONS => array('dateFormat', 'storageFormat'), + self::DISPLAY_OPTIONS => array('accesskey', 'autoInsertNotEmptyValidator', 'class', 'disabled', 'description', 'escape', 'label', 'onclick', 'readonly', 'required', 'tabindex', 'value', 'showLabels', 'labelplacement'), + self::EXHIBIT_OPTIONS => array('formatFunction'), + self::FAKESUBMIT_OPTIONS => array('label', 'tabindex', 'disabled'), + self::FILE_OPTIONS => array('accept', 'count', 'destination', 'valueDisabled'), + self::GROUP_OPTIONS => array('elements', 'legend', 'separator'), + self::JQUERY_OPTIONS => array('jQueryParams'), + self::MULTI_OPTIONS => array('disable', 'multiOptions', 'onchange', 'separator', 'size', 'disableTranslator'), + self::PASSWORD_OPTIONS => array('repeatLabel'), + self::TAB_OPTIONS => array('value'), + self::TEXT_OPTIONS => array('maxlength', 'minlength', 'onchange', 'onfocus', 'onselect', 'size'), + self::TEXTAREA_OPTIONS => array('cols', 'rows', 'wrap'), ); public function __construct(MUtil_Model_ModelAbstract $model, Zend_Form $form) @@ -402,14 +404,24 @@ return $this->_addToForm($element->getName(), $element); } + /** + * Add an element that just displays the value to the user + * + * @param string $name Name of element + * @param mixed $arrayOrKey1 MUtil_Ra::pairs() name => value array + * @return \MUtil_Form_Element_Exhibitor + */ public function addExhibitor($name, $arrayOrKey1 = null, $value1 = null, $key2 = null, $value2 = null) { - $options = func_get_args(); - $options = MUtil_Ra::pairs($options, 1); + $options = $this->_mergeOptions( + $name, + MUtil_Ra::pairs(func_get_args(), 1), + self::DATE_OPTIONS, + self::DISPLAY_OPTIONS, + self::EXHIBIT_OPTIONS, + self::MULTI_OPTIONS + ); - $options = $this->_mergeOptions($name, $options, - self::DATE_OPTIONS, self::DISPLAY_OPTIONS, self::EXHIBIT_OPTIONS, self::MULTI_OPTIONS); - $element = new MUtil_Form_Element_Exhibitor($name, $options); $this->form->addElement($element); @@ -418,6 +430,29 @@ return $element; } + /** + * Add an element that just displays the value to the user + * + * @param string $name Name of element + * @param mixed $arrayOrKey1 MUtil_Ra::pairs() name => value array + * @return \MUtil_Form_Element_FakeSubmit + */ + public function addFakeSubmit($name, $arrayOrKey1 = null, $value1 = null, $key2 = null, $value2 = null) + { + $options = $this->_mergeOptions( + $name, + MUtil_Ra::pairs(func_get_args(), 1), + self::FAKESUBMIT_OPTIONS + ); + + $element = new MUtil_Form_Element_FakeSubmit($name, $options); + + $this->form->addElement($element); + // MUtil_Echo::r($element->getOrder(), $element->getName()); + + return $element; + } + public function addFile($name, $arrayOrKey1 = null, $value1 = null, $key2 = null, $value2 = null) { $options = func_get_args(); @@ -523,6 +558,52 @@ return $this->_addToForm($name, 'Select', $options); } + + /** + * Adds a group of checkboxes (multicheckbox) + * + * @see Zend_Form_Element_MultiCheckbox + * + * @param string $name Name of element + * @param mixed $arrayOrKey1 MUtil_Ra::pairs() name => value array + * @return Zend_Form_Element_MultiCheckbox + */ + public function addMultiCheckbox($name, $arrayOrKey1 = null, $value1 = null, $key2 = null, $value2 = null) + { + $options = func_get_args(); + $options = MUtil_Ra::pairs($options, 1); + + // Is often added automatically, but should not be used here + $this->_moveOption('maxlength', $options); + + $options = $this->_mergeOptions($name, $options, + self::DISPLAY_OPTIONS, self::MULTI_OPTIONS); + + return $this->_addToForm($name, 'MultiCheckbox', $options); + } + + /** + * Adds a select box with multiple options + * + * @see Zend_Form_Element_Multiselect + * + * @param string $name Name of element + * @param mixed $arrayOrKey1 MUtil_Ra::pairs() name => value array + */ + public function addMultiSelect($name, $arrayOrKey1 = null, $value1 = null, $key2 = null, $value2 = null) + { + $options = func_get_args(); + $options = MUtil_Ra::pairs($options, 1); + + // Is often added automatically, but should not be used here + $this->_moveOption('maxlength', $options); + + $options = $this->_mergeOptions($name, $options, + self::DISPLAY_OPTIONS, self::MULTI_OPTIONS); + + return $this->_addToForm($name, 'Multiselect', $options); + } + public function addPassword($name, $arrayOrKey1 = null, $value1 = null, $key2 = null, $value2 = null) { $options = func_get_args(); @@ -592,53 +673,7 @@ return $this->_addToForm($name, 'Select', $options); } - /** - * Adds a group of checkboxes (multicheckbox) - * - * @see Zend_Form_Element_MultiCheckbox - * - * @param string $name Name of element - * @param mixed $arrayOrKey1 MUtil_Ra::pairs() name => value array - * @return Zend_Form_Element_MultiCheckbox - */ - public function addMultiCheckbox($name, $arrayOrKey1 = null, $value1 = null, $key2 = null, $value2 = null) - { - $options = func_get_args(); - $options = MUtil_Ra::pairs($options, 1); - - // Is often added automatically, but should not be used here - $this->_moveOption('maxlength', $options); - - $options = $this->_mergeOptions($name, $options, - self::DISPLAY_OPTIONS, self::MULTI_OPTIONS); - - return $this->_addToForm($name, 'MultiCheckbox', $options); - } - - /** - * Adds a select box with multiple options - * - * @see Zend_Form_Element_Multiselect - * - * @param string $name Name of element - * @param mixed $arrayOrKey1 MUtil_Ra::pairs() name => value array - */ - public function addMultiSelect($name, $arrayOrKey1 = null, $value1 = null, $key2 = null, $value2 = null) - { - $options = func_get_args(); - $options = MUtil_Ra::pairs($options, 1); - - // Is often added automatically, but should not be used here - $this->_moveOption('maxlength', $options); - - $options = $this->_mergeOptions($name, $options, - self::DISPLAY_OPTIONS, self::MULTI_OPTIONS); - - return $this->_addToForm($name, 'Multiselect', $options); - } - - /** * Start a tab after this element, with the given name / title * * Can ofcourse only be used in tabbed forms. @@ -676,12 +711,13 @@ public function addText($name, $arrayOrKey1 = null, $value1 = null, $key2 = null, $value2 = null) { - $options = func_get_args(); - $options = MUtil_Ra::pairs($options, 1); + $options = $this->_mergeOptions( + $name, + MUtil_Ra::pairs(func_get_args(), 1), + self::DISPLAY_OPTIONS, + self::TEXT_OPTIONS + ); - $options = $this->_mergeOptions($name, $options, - self::DISPLAY_OPTIONS, self::TEXT_OPTIONS); - $stringlength = $this->_getStringLength($options); if ($stringlength) { Modified: trunk/library/classes/MUtil/Snippets/ModelTableSnippetAbstract.php =================================================================== --- trunk/library/classes/MUtil/Snippets/ModelTableSnippetAbstract.php 2013-02-28 15:13:09 UTC (rev 1166) +++ trunk/library/classes/MUtil/Snippets/ModelTableSnippetAbstract.php 2013-02-28 17:40:31 UTC (rev 1167) @@ -78,6 +78,13 @@ public $caption; /** + * An array of nested arrays, each defining the input for setMultiSort + * + * @var array + */ + public $columns; + + /** * Content to show when there are no rows. * * Null shows '…' @@ -112,7 +119,11 @@ */ protected function addBrowseTableColumns(MUtil_Model_TableBridge $bridge, MUtil_Model_ModelAbstract $model) { - if ($this->sortableLinks) { + if ($this->columns) { + foreach ($this->columns as $column) { + call_user_func_array(array($bridge, 'addMultiSort'), $column); + } + } elseif ($this->sortableLinks) { foreach($model->getItemsOrdered() as $name) { if ($label = $model->get($name, 'label')) { $bridge->addSortable($name, $label); Modified: trunk/library/snippets/Organization/ChooseOrganizationSnippet.php =================================================================== --- trunk/library/snippets/Organization/ChooseOrganizationSnippet.php 2013-02-28 15:13:09 UTC (rev 1166) +++ trunk/library/snippets/Organization/ChooseOrganizationSnippet.php 2013-02-28 17:40:31 UTC (rev 1167) @@ -89,17 +89,13 @@ $url[$this->request->getControllerKey()] = 'organization'; $url[$this->request->getActionKey()] = 'change-ui'; - if ($orgs = $user->getAllowedOrganizations()) { + if ($orgs = $user->getRespondentOrganizations()) { $html->pInfo($this->_('This organization cannot have any respondents, please choose one that does:')); foreach ($orgs as $orgId => $name) { - $org = $this->loader->getOrganization($orgId); + $url['org'] = $orgId; - if ($org->canHaveRespondents()) { - $url['org'] = $orgId; - - $html->pInfo()->actionLink($url, $name, array('style' => 'font-size: 120%;')); - } + $html->pInfo()->actionLink($url, $name, array('style' => 'font-size: 120%;')); } } else { $html->pInfo($this->_('This organization cannot have any respondents.')); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |