/** * Adds columns from the model to the bridge that creates the browse table. * * Overrule this function to add different columns to the browse table, without * having to recode the core table building code. * * @param \MUtil_Model_Bridge_TableBridge $bridge * @param \MUtil_Model_ModelAbstract $model * @return void */ protected function addBrowseTableColumns(\MUtil_Model_Bridge_TableBridge $bridge, \MUtil_Model_ModelAbstract $model) { if ($model->has('row_class')) { $bridge->getTable()->tbody()->getFirst(true)->appendAttrib('class', $bridge->row_class); } if ($editMenuItem = $this->getEditMenuItem()) { $bridge->addItemLink($editMenuItem->toActionLinkLower($this->request, $bridge)); } // make sure search results are highlighted $this->applyTextMarker(); 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); } } } else { foreach ($model->getItemsOrdered() as $name) { if ($label = $model->get($name, 'label')) { $bridge->add($name, $label); } } } if ($deleteMenuItem = $this->findMenuItem($this->request->getControllerName(), 'delete')) { $bridge->addItemLink($deleteMenuItem->toActionLinkLower($this->request, $bridge)); } }
/** * Adds rows from the model to the bridge that creates the browse table. * * Overrule this function to add different columns to the browse table, without * having to recode the core table building code. * * @param \MUtil_Model_Bridge_VerticalTableBridge $bridge * @param \MUtil_Model_ModelAbstract $model * @return void */ protected function addShowTableRows(\MUtil_Model_Bridge_VerticalTableBridge $bridge, \MUtil_Model_ModelAbstract $model) { $items = $model->getItemsOrdered(); foreach ($items as $name) { if ($model->get($name, 'type') === \MUtil_Model::TYPE_CHILD_MODEL) { $this->submodel = $model->get($name, 'model'); $subitems = $this->submodel->getItemsOrdered(); } } if (isset($subitems) && is_array($subitems)) { $items = array_diff($items, $subitems); } foreach ($items as $name) { if ($label = $model->get($name, 'label')) { $bridge->addItem($name, $label); } } /*if ($subitems) { $bridge->addItem('gctt', 'moo'); }*/ if ($model->has('row_class')) { // Make sure deactivated rounds are show as deleted foreach ($bridge->getTable()->tbody() as $tr) { foreach ($tr as $td) { if ('td' === $td->tagName) { $td->appendAttrib('class', $bridge->row_class); } } } } }
/** * Creates the model * * @return \MUtil_Model_ModelAbstract */ protected function createModel() { // Replace two checkboxes with on radio button control $this->model->set('ggp_staff_members', 'elementClass', 'Hidden'); $this->model->setOnSave('ggp_staff_members', array($this, 'saveIsStaff')); $this->model->set('ggp_respondent_members', 'elementClass', 'Hidden'); $this->model->setOnSave('ggp_respondent_members', array($this, 'saveIsRespondent')); $options = array('1' => $this->model->get('ggp_staff_members', 'label'), '2' => $this->model->get('ggp_respondent_members', 'label')); $this->model->set('staff_respondent', 'label', $this->_('Can be assigned to'), 'elementClass', 'Radio', 'multiOptions', $options, 'order', $this->model->getOrder('ggp_staff_members') + 1); $this->model->setOnLoad('staff_respondent', array($this, 'loadStaffRespondent')); return $this->model; }
/** * Adds columns from the model to the bridge that creates the browse table. * * Overrule this function to add different columns to the browse table, without * having to recode the core table building code. * * @param \MUtil_Model_Bridge_TableBridge $bridge * @param \MUtil_Model_ModelAbstract $model * @return void */ protected function addBrowseTableColumns(\MUtil_Model_Bridge_TableBridge $bridge, \MUtil_Model_ModelAbstract $model) { // Make sure these fields are loaded $model->get('gro_valid_after_field'); $model->get('gro_valid_after_id'); $model->get('gro_valid_after_length'); $model->get('gro_valid_after_source'); $model->get('gro_valid_after_unit'); $model->get('gro_valid_for_field'); $model->get('gro_valid_for_id'); $model->get('gro_valid_for_length'); $model->get('gro_valid_for_source'); $model->get('gro_valid_for_unit'); parent::addBrowseTableColumns($bridge, $model); }
/** * 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_Bridge_FormBridgeInterface $bridge * @param \MUtil_Model_ModelAbstract $model */ protected function addFormElements(\MUtil_Model_Bridge_FormBridgeInterface $bridge, \MUtil_Model_ModelAbstract $model) { if (!$this->createData) { $bridge->addHidden('gtr_id_track'); } $bridge->addText('gtr_track_name'); // gtr_track_class if ($this->trackEngine) { $options = $model->get('gtr_track_class', 'multiOptions'); $alternatives = $this->trackEngine->getConversionTargets($options); if (count($alternatives) > 1) { $options = $alternatives; $bridge->addHidden($this->_oldClassName); if (!isset($this->formData[$this->_oldClassName])) { $this->formData[$this->_oldClassName] = $this->formData['gtr_track_class']; } $classEdit = true; } else { $classEdit = false; } } else { $tracker = $this->loader->getTracker(); $options = $tracker->getTrackEngineList(true, true); $classEdit = true; } $model->set('gtr_track_class', 'multiOptions', $options, 'escape', false); if ($classEdit) { $bridge->addRadio('gtr_track_class'); } else { $bridge->addExhibitor('gtr_track_class'); } $bridge->addDate('gtr_date_start'); $bridge->addDate('gtr_date_until'); if (!$this->createData) { $bridge->addCheckbox('gtr_active'); } if ($model->has('gtr_code')) { $bridge->addText('gtr_code'); } if ($model->has('gtr_calculation_event', 'label')) { $bridge->add('gtr_calculation_event'); } if ($model->has('gtr_completed_event', 'label')) { $bridge->add('gtr_completed_event'); } if ($model->has('gtr_beforefieldupdate_event', 'label')) { $bridge->add('gtr_beforefieldupdate_event'); } if ($model->has('gtr_fieldupdate_event', 'label')) { $bridge->add('gtr_fieldupdate_event'); } $bridge->add('gtr_organizations'); if (\MUtil_Bootstrap::enabled()) { $element = new \MUtil_Bootstrap_Form_Element_ToggleCheckboxes('toggleOrg', array('selector' => 'input[name^=gtr_organizations]')); } else { $element = new \Gems_JQuery_Form_Element_ToggleCheckboxes('toggleOrg', array('selector' => 'input[name^=gtr_organizations]')); } $element->setLabel($this->_('Toggle')); $bridge->addElement($element); }
/** * Returns true if and only if $value meets the validation requirements * * If $value fails validation, then this method returns false, and * getMessages() will return an array of messages that explain why the * validation failed. * * @param mixed $value * @param array $context * @return boolean * @throws \Zend_Validate_Exception If validation of $value is impossible */ public function isValid($value, $context = array()) { $this->_setValue($value); // Make sure the (optionally filtered) value is in the context $context[reset($this->_fields)] = $value; $filter = array(); foreach ($this->_fields as $name) { // Return valid when not all the fields to check for are in the context if (!isset($context[$name])) { return true; } $filter[$name] = $context[$name]; } $check = array(); $doGet = $this->_model->hasItemsUsed(); $keys = $this->_model->getKeys(); foreach ($keys as $id => $key) { if ($doGet) { // Make sure the item is used $this->_model->get($key); } if (isset($context[$id])) { $check[$key] = $context[$id]; } elseif (isset($context[$key])) { $check[$key] = $context[$key]; } else { // Not all keys are in => therefore this is a new item $check = false; break; } } $rows = $this->_model->load($filter); if (!$rows) { return true; } if (!$check) { // Rows where found while it is a new item $this->_error(self::ERROR_RECORD_FOUND); return false; } $count = count($check); foreach ($rows as $row) { // Check for return of the whole check if (count(array_intersect_assoc($check, $row)) !== $count) { // There exists a row with the same values but not the same keys $this->_error(self::ERROR_RECORD_FOUND); return false; } } return true; }
/** * A ModelAbstract->setOnSave() function that tracks the change * * @see \MUtil_Model_ModelAbstract * * @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 Of the values concatenated */ public function saveValue($value, $isNew = false, $name = null, array $context = array()) { // \MUtil_Echo::track($value, $this->_changedValue); // Once the value is set (and e.g. stored in the database) do not overwrite it if ($this->_changedValue == $value) { return $value; } $compare = $this->_model->get($name, __CLASS__); if (!(is_array($compare) && 2 === count($compare))) { // Actually a valid setting, do nothring return $value; } list($trackedField, $oldValueField) = $compare; if (!isset($context[$trackedField], $context[$oldValueField])) { return $value; } if (!($context[$trackedField] && $context[$oldValueField])) { return $context[$trackedField] || $context[$oldValueField] ? $this->_changedValue : $this->_unchangedValue; } $storageFormat = $this->_model->get($trackedField, 'storageFormat'); if (!$storageFormat) { return $context[$trackedField] == $context[$oldValueField] ? $this->_unchangedValue : $this->_changedValue; } if ($context[$oldValueField] instanceof \Zend_Date) { $oldValue = $context[$oldValueField]; } else { $oldValue = new \MUtil_Date($context[$oldValueField], $storageFormat); } if ($context[$trackedField] instanceof \Zend_Date) { $currentValue = $context[$trackedField]; } elseif (\Zend_Date::isDate($context[$trackedField], $storageFormat)) { $currentValue = new \MUtil_Date($context[$trackedField], $storageFormat); } else { if ($this->_model->has($trackedField, 'dateFormat')) { $secondFormat = $this->_model->get($trackedField, 'dateFormat'); } else { $secondFormat = \MUtil_Model_Bridge_FormBridge::getFixedOption('date', 'dateFormat'); } if (!\Zend_Date::isDate($context[$trackedField], $secondFormat)) { // Cannot compare, do nothing return $value; } $currentValue = new \MUtil_Date($context[$trackedField], $secondFormat); } // \MUtil_Echo::track($trackedField, $oldValueField, $oldValue->toString(), $currentValue->toString(), $oldValue->getTimestamp() === $currentValue->getTimestamp()); return $oldValue->getTimestamp() === $currentValue->getTimestamp() ? $this->_unchangedValue : $this->_changedValue; }
/** * Adds columns from the model to the bridge that creates the browse table. * * Overrule this function to add different columns to the browse table, without * having to recode the core table building code. * * @param \MUtil_Model_Bridge_TableBridge $bridge * @param \MUtil_Model_ModelAbstract $model * @return void */ protected function addBrowseTableColumns(\MUtil_Model_Bridge_TableBridge $bridge, \MUtil_Model_ModelAbstract $model) { // Add link to patient to overview $menuItems = $this->findMenuItems('respondent', 'show'); if ($menuItems) { $menuItem = reset($menuItems); if ($menuItem instanceof \Gems_Menu_SubMenuItem) { $href = $menuItem->toHRefAttribute($bridge); if ($href) { $aElem = new \MUtil_Html_AElement($href); $aElem->setOnEmpty(''); // Make sure org is known $model->get('gr2o_id_organization'); $model->set('gr2o_patient_nr', 'itemDisplay', $aElem); $model->set('respondent_name', 'itemDisplay', $aElem); } } } $model->set('gto_id_token', 'formatFunction', 'strtoupper'); $bridge->setDefaultRowClass(\MUtil_Html_TableElement::createAlternateRowClass('even', 'even', 'odd', 'odd')); $tr1 = $bridge->tr(); $tr1->appendAttrib('class', $bridge->row_class); $tr1->appendAttrib('title', $bridge->gto_comment); $bridge->addColumn($this->createShowTokenButton($bridge), ' ')->rowspan = 2; // Space needed because TableElement does not look at rowspans $bridge->addSortable('gto_valid_from'); $bridge->addSortable('gto_valid_until'); $bridge->addSortable('gto_id_token'); // $bridge->addSortable('gto_mail_sent_num', $this->_('Contact moments'))->rowspan = 2; $this->addRespondentCell($bridge, $model); $bridge->addMultiSort('ggp_name', array($this->createActionButtons($bridge))); $tr2 = $bridge->tr(); $tr2->appendAttrib('class', $bridge->row_class); $tr2->appendAttrib('title', $bridge->gto_comment); $bridge->addSortable('gto_mail_sent_date'); $bridge->addSortable('gto_completion_time'); $bridge->addSortable('gto_mail_sent_num', $this->_('Contact moments')); if ($this->multiTracks) { $model->set('gr2t_track_info', 'tableDisplay', 'smallData'); $model->set('gto_round_description', 'tableDisplay', 'smallData'); $bridge->addMultiSort('gtr_track_name', 'gr2t_track_info', array($bridge->gtr_track_name->if(\MUtil_Html::raw(' » ')), ' '), 'gsu_survey_name', 'gto_round_description'); } else { $bridge->addMultiSort('gto_round_description', \MUtil_Html::raw('; '), 'gsu_survey_name'); } $bridge->addSortable('assigned_by'); }
/** * Adds columns from the model to the bridge that creates the browse table. * * Overrule this function to add different columns to the browse table, without * having to recode the core table building code. * * @param \MUtil_Model_Bridge_TableBridge $bridge * @param \MUtil_Model_ModelAbstract $model * @return void */ protected function addBrowseTableColumns(\MUtil_Model_Bridge_TableBridge $bridge, \MUtil_Model_ModelAbstract $model) { // $bridge->getTable()->setAlternateRowClass('odd', 'odd', 'even', 'even'); // \MUtil_Model::$verbose = true; $bridge->add('gro_round_description', $bridge->createSortLink('gro_id_order', $model->get('gro_round_description', 'label'))); $bridge->addSortable('gsu_survey_name'); $bridge->th(array($bridge->createSortLink('answered'), 'colspan' => 2))->class = 'centerAlign'; $bridge->td($bridge->answered)->class = 'centerAlign'; $bridge->td($this->percentageLazy($bridge->answered, $bridge->total))->class = 'rightAlign'; $bridge->th(array($bridge->createSortLink('missed'), 'colspan' => 2))->class = 'centerAlign'; $bridge->td($bridge->missed)->class = 'centerAlign'; $bridge->td($this->percentageLazy($bridge->missed, $bridge->total))->class = 'rightAlign'; $bridge->th(array($bridge->createSortLink('open'), 'colspan' => 2))->class = 'centerAlign'; $bridge->td($bridge->open)->class = 'centerAlign'; $bridge->td($this->percentageLazy($bridge->open, $bridge->total))->class = 'rightAlign'; // $bridge->addSortable('answered'); // $bridge->addSortable('missed'); // $bridge->addSortable('open'); // $bridge->add('future'); // $bridge->add('unknown'); $bridge->addColumn(array('=', 'class' => 'centerAlign')); $bridge->addSortable('total'); $bridge->addSortable('gsu_id_primary_group'); // $bridge->tr(); // $bridge->add('gsu_survey_name')->colspan = 4; // $bridge->add('gsu_id_primary_group')->colspan = 2; // $bridge->addColumn(); /* $bridge->addColumn( array( $bridge->gsu_survey_name, \MUtil_Html::create('em', ' - ', $bridge->gsu_id_primary_group) ), array( $model->get('gsu_survey_name', 'label'), \MUtil_Html::create('em', ' - ', $model->get('gsu_id_primary_group', 'label')) ) )->colspan = 7; $bridge->add('removed'); // */ }
/** * Checks and updates the on and off strings when one of the effecteds is a date, time or datetime field * * @param string $valueOn * @param string $valueOff */ protected function checkPicker(&$valueOn, &$valueOff) { $effecteds = array_keys($this->getEffecteds()); foreach ($effecteds as $field) { if ($this->model instanceof \MUtil_Model_ModelAbstract && $this->model->has($field)) { $modelItemType = $this->model->get($field, 'type'); $dateFormat = $this->model->get($field, 'dateFormat'); $timeFormat = $this->model->get($field, 'timeFormat'); switch ($modelItemType) { case \MUtil_Model::TYPE_DATE: case \MUtil_Model::TYPE_TIME: case \MUtil_Model::TYPE_DATETIME: $picker = 'datepicker'; break; default: $picker = ''; break; } if (!empty($picker)) { // If none set, get the locale default dateformat if (!$dateFormat && !$timeFormat && \Zend_Registry::isRegistered('Zend_Locale')) { $dateFormat = \ZendX_JQuery_View_Helper_DatePicker::resolveZendLocaleToDatePickerFormat(); } if ($dateFormat) { if ($timeFormat) { $picker = 'datetimepicker'; } } elseif ($timeFormat) { $picker = 'timepicker'; } $valueOn .= "\$('#{$field}').{$picker}('enable');"; $valueOff .= "\$('#{$field}').{$picker}('disable');"; } } } }
/** * Translate textual null values to actual PHP nulls and trim any whitespace * * @param mixed $value * @param scalar $key The array key, optionally a model key as well * @return mixed */ public function filterBasic(&$value, $key) { if (is_string($value) && $this->nullValue === strtoupper($value)) { $value = null; return; } if ($this->_targetModel instanceof \MUtil_Model_ModelAbstract) { if ($this->_targetModel->is($key, 'type', \MUtil_Model::TYPE_DATE)) { $format = $this->dateFormat; } elseif ($this->_targetModel->is($key, 'type', \MUtil_Model::TYPE_DATETIME)) { $format = $this->datetimeFormat; } elseif ($this->_targetModel->is($key, 'type', \MUtil_Model::TYPE_TIME)) { $format = $this->timeFormat; } else { $format = false; } if ($this->dateLocale && is_string($this->dateLocale)) { $this->dateLocale = new \Zend_Locale($this->dateLocale); } if ($format && \Zend_Date::isDate($value, $format, $this->dateLocale)) { $value = new \MUtil_Date($value, $format, $this->dateLocale); return; } $options = $this->_targetModel->get($key, 'multiOptions'); if ($options && !isset($options[$value]) && in_array($value, $options)) { $value = array_search($value, $options); } } if (is_string($value)) { $value = trim($value); return; } return; }
/** * 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_Bridge_FormBridgeInterface $bridge * @param \MUtil_Model_ModelAbstract $model */ protected function addFormElements(\MUtil_Model_Bridge_FormBridgeInterface $bridge, \MUtil_Model_ModelAbstract $model) { $bridge->addHtml('to', 'label', $this->_('To')); $bridge->addHtml('prefered_language', 'label', $this->_('Prefered Language')); $bridge->addElement($this->mailElements->createTemplateSelectElement('select_template', $this->_('Template'), $this->mailTarget, $this->templateOnly, true)); if ($this->templateOnly) { $bridge->addHidden('subject'); } else { $bridge->addText('subject', 'label', $this->_('Subject'), 'size', 50); } $mailBody = $bridge->addElement($this->mailElements->createBodyElement('mailBody', $this->_('Message'), $model->get('gctt_body', 'required'), $this->templateOnly)); if ($mailBody instanceof \Gems_Form_Element_CKEditor) { $mailBody->config['availablefields'] = $this->mailer->getMailFields(); $mailBody->config['availablefieldsLabel'] = $this->_('Fields'); $mailBody->config['extraPlugins'] .= ',availablefields'; $mailBody->config['toolbar'][] = array('availablefields'); } if (!$this->templateOnly) { $bridge->addFakeSubmit('preview', array('label' => $this->_('Preview'))); } $bridge->addElement($this->createFromSelect('from', $this->_('From'))); $bridge->addElement($this->mailElements->createSubmitButton('send', $this->_('Send'))); $bridge->addElement($this->mailElements->createPreviewHtmlElement('Preview HTML')); $bridge->addElement($this->mailElements->createPreviewTextElement('Preview Text')); if (!$this->templateOnly) { $bridge->addHtml('available_fields', array('label' => $this->_('Available fields'))); } }
/** * Handles creating or replacing the view for this survey * * @param \Gems_Tracker_Survey $viewName * @param \MUtil_Model_ModelAbstract $answerModel */ protected function replaceCreateView(\Gems_Tracker_Survey $survey, \MUtil_Model_ModelAbstract $answerModel) { $viewName = $this->getViewName($survey); $responseDb = $this->project->getResponseDatabase(); $fieldSql = ''; foreach ($answerModel->getItemsOrdered() as $name) { if (true === $answerModel->get($name, 'survey_question') && !in_array($name, array('submitdate', 'startdate', 'datestamp')) && !$answerModel->is($name, 'type', \MUtil_Model::TYPE_NOVALUE)) { // Only real answers $fieldSql .= ',MAX(IF(gdr_answer_id = ' . $responseDb->quote($name) . ', gdr_response, NULL)) AS ' . $responseDb->quoteIdentifier($name); } } if ($fieldSql > '') { $dbConfig = $this->db->getConfig(); $tokenTable = $this->db->quoteIdentifier($dbConfig['dbname'] . '.gems__tokens'); $createViewSql = 'CREATE OR REPLACE VIEW ' . $responseDb->quoteIdentifier($viewName) . ' AS SELECT gdr_id_token'; $createViewSql .= $fieldSql; $createViewSql .= "FROM gemsdata__responses join " . $tokenTable . " on (gto_id_token=gdr_id_token and gto_id_survey=" . $survey->getSurveyId() . ") GROUP BY gdr_id_token;"; try { $responseDb->query($createViewSql)->execute(); } catch (Exception $exc) { $responseConfig = $responseDb->getConfig(); $dbUser = $this->db->quoteIdentifier($responseConfig['username']) . '@' . $this->db->quoteIdentifier($responseConfig['host']); $statement = "GRANT SELECT ON " . $tokenTable . " TO " . $dbUser; $this->getBatch()->addMessage(sprintf($this->_("Creating view failed, try adding rights using the following statement: %s"), $statement)); } } }
/** * Adds columns from the model to the bridge that creates the browse table. * * Overrule this function to add different columns to the browse table, without * having to recode the core table building code. * * @param \MUtil_Model_Bridge_TableBridge $bridge * @param \MUtil_Model_ModelAbstract $model * @return void */ protected function addBrowseTableColumns(\MUtil_Model_Bridge_TableBridge $bridge, \MUtil_Model_ModelAbstract $model) { $bridge->gr2o_patient_nr; $bridge->gr2o_id_organization; if ($menuItem = $this->menu->find(array('controller' => 'appointment', 'action' => 'show', 'allowed' => true))) { $appButton = $menuItem->toActionLink($this->request, $bridge, $this->_('Show appointment')); } else { $appButton = null; } if ($menuItem = $this->menu->find(array('controller' => 'appointment', 'action' => 'edit', 'allowed' => true))) { $editButton = $menuItem->toActionLink($this->request, $bridge, $this->_('Edit appointment')); } else { $editButton = null; } $br = \MUtil_Html::create('br'); $table = $bridge->getTable(); $table->appendAttrib('class', 'calendar'); $bridge->tr()->appendAttrib('class', $bridge->row_class); if ($appButton) { $bridge->addItemLink($appButton)->class = 'middleAlign'; } if ($this->sortableLinks) { $bridge->addMultiSort(array($bridge->date_only), $br, 'gap_admission_time')->class = 'date'; $bridge->addMultiSort('gap_subject', $br, 'glo_name'); $bridge->addMultiSort('gaa_name', $br, 'gapr_name'); $bridge->addMultiSort('gor_name', $br, 'glo_name'); } else { $bridge->addMultiSort(array($bridge->date_only), $br, array($bridge->gap_admission_time, $model->get('gap_admission_time', 'label'))); $bridge->addMultiSort(array($bridge->gap_subject, $model->get('gap_subject', 'label')), $br, array($bridge->gas_name, $model->get('gas_name', 'label'))); $bridge->addMultiSort(array($bridge->gaa_name, $model->get('gaa_name', 'label')), $br, array($bridge->gapr_name, $model->get('gapr_name', 'label'))); $bridge->addMultiSort(array($bridge->gor_name, $model->get('gor_name', 'label')), $br, array($bridge->glo_name, $model->get('glo_name', 'label'))); } if ($editButton) { $bridge->addItemLink($editButton)->class = 'middleAlign rightAlign'; } }
/** * Add an extra model to the union * * @param \MUtil_Model_ModelAbstract $model * @param array $fieldMap Map from the sub model field names to this models names * @param string $name * @return \MUtil_Model_UnionModelAbstract (continuation pattern) */ public function addUnionModel(\MUtil_Model_ModelAbstract $model, array $fieldMap = null, $name = null) { if (null === $name) { $name = $model->getName(); } $this->_unionModels[$name] = $model; if ($fieldMap) { $this->_unionMapsFrom[$name] = $fieldMap; $this->_unionMapsTo[$name] = array_flip($fieldMap); } else { $this->_unionMapsFrom[$name] = false; $this->_unionMapsTo[$name] = false; $fieldMap = array(); } foreach ($model->getItemsOrdered() as $subName) { if (isset($fieldMap[$subName])) { $mainName = $fieldMap[$subName]; } else { $mainName = $subName; } $this->set($mainName, $model->get($subName)); } return $this; }
/** * Returns an array with all columns from the model that have a label * * @param array $data * @param \MUtil_Model_ModelAbstract $model * @return array */ protected function getExcelData($data, \MUtil_Model_ModelAbstract $model) { $headings = array(); $emptyMsg = $this->_('No data found.'); foreach ($model->getItemsOrdered() as $name) { if ($label = $model->get($name, 'label')) { $headings[$name] = (string) $label; } } $results = array(); $results[] = $headings; if ($headings) { if ($data) { foreach ($data as $row) { foreach ($headings as $key => $value) { $result[$key] = isset($row[$key]) ? $row[$key] : null; } $results[] = $result; } return $results; } else { foreach ($headings as $key => $value) { $result[$key] = $emptyMsg; } $results[] = $result; return $results; } } else { return array($emptyMsg); } }
/** * This transform function checks the filter for * a) retreiving filters to be applied to the transforming data, * b) adding filters that are the result * * @param \MUtil_Model_ModelAbstract $model * @param array $filter * @return array The (optionally changed) filter */ public function transformFilter(\MUtil_Model_ModelAbstract $model, array $filter) { // Make sure the join fields are in the result set foreach ($this->_joins as $joins) { foreach ($joins as $source => $target) { if (!is_integer($source)) { $model->get($source); } } } return $filter; }
/** * Should handle execution of the task, taking as much (optional) parameters as needed * * The parameters should be optional and failing to provide them should be handled by * the task * * @param array $row Row to save */ public function execute($row = null, $noToken = \Gems_Model_Translator_AnswerTranslatorAbstract::TOKEN_ERROR, $tokenCompletion = \Gems_Model_Translator_AnswerTranslatorAbstract::TOKEN_ERROR) { // \MUtil_Echo::track($row); if ($row) { $answers = $row; $double = false; $token = null; $tracker = $this->loader->getTracker(); $userId = $this->loader->getCurrentUser()->getUserId(); // \Gems_Tracker::$verbose = true; $batch = $this->getBatch(); $batch->addToCounter('imported'); // Remove all "non-answer" fields unset($answers['token'], $answers['patient_id'], $answers['organization_id'], $answers['track_id'], $answers['survey_id'], $answers['completion_date'], $answers['gto_id_token']); if (isset($row['survey_id'])) { $model = $tracker->getSurvey($row['survey_id'])->getAnswerModel('en'); foreach ($answers as $key => &$value) { if ($value instanceof \Zend_Date) { $value = $value->toString($model->getWithDefault($key, 'storageFormat', 'yyyy-MM-dd HH:mm:ss')); } } } if (isset($row['token']) && $row['token']) { $token = $tracker->getToken($row['token']); if ($token->exists && $token->isCompleted() && $token->getReceptionCode()->isSuccess()) { $currentAnswers = $token->getRawAnswers(); $usedAnswers = array_intersect_key($answers, $currentAnswers); // \MUtil_Echo::track($currentAnswers, $answers, $usedAnswers); if ($usedAnswers) { foreach ($usedAnswers as $name => $value) { if (null === $answers[$name] || $answers[$name] == $this->targetModel->get($name, 'default')) { // There is no value to set, so do not set the value unset($answers[$name]); } elseif (!(null === $value || $value == $this->targetModel->get($name, 'default'))) { // The value was already set $double = true; // But no break because of previous unsets // break; } } } } } if (!($token && $token->exists)) { if (!(isset($row['track_id']) && $row['track_id'])) { } // create token? } if ($answers) { if ($double) { if (\Gems_Model_Translator_AnswerTranslatorAbstract::TOKEN_OVERWRITE == $tokenCompletion) { $code = $this->util->getReceptionCode('redo'); $oldComment = ""; if ($token->getComment()) { $oldComment .= "\n\n"; $oldComment .= $this->_('Previous comments:'); $oldComment .= "\n"; $oldComment .= $token->getComment(); } $newComment = sprintf($this->_('Token %s overwritten by import.'), $token->getTokenId()); $replacementTokenId = $token->createReplacement($newComment . $oldComment, $userId); $count = $batch->addToCounter('overwritten', 1); $batch->setMessage('overwritten', sprintf($this->plural('%d token overwrote an existing token.', '%d tokens overwrote existing tokens.', $count), $count)); $oldToken = $token; $token = $tracker->getToken($replacementTokenId); // Add the old answers to the new answer set as the new answers OVERWRITE the old data $answers = $answers + $currentAnswers; // Make sure the Next token is set right $oldToken->setNextToken($token); $oldToken->setReceptionCode($code, sprintf($this->_('Token %s overwritten by import.'), $token->getTokenId()) . $oldComment, $userId); } else { $oldComment = ""; if ($token->getComment()) { $oldComment .= "\n\n"; $oldComment .= $this->_('Previous comments:'); $oldComment .= "\n"; $oldComment .= $token->getComment(); } $newComment = sprintf($this->_('More answers for token %s by import.'), $token->getTokenId()); $replacementTokenId = $token->createReplacement($newComment . $oldComment, $userId); $count = $batch->addToCounter('addedAnswers', 1); $batch->setMessage('addedAnswers', sprintf($this->plural('%d token was imported as a new extra token.', '%d tokens were imported as a new extra token.', $count), $count)); $oldToken = $token; $token = $tracker->getToken($replacementTokenId); // Make sure the Next token is set right $oldToken->setNextToken($token); $oldToken->setReceptionCode($oldToken->getReceptionCode(), sprintf($this->_('Additional answers in imported token %s.'), $token->getTokenId()) . $oldComment, $userId); } } // There are still answers left to save // Make sure the token is known $token->getUrl($this->locale->getLanguage(), $userId); $token->setRawAnswers($answers); if (isset($row['completion_date']) && $row['completion_date']) { $token->setCompletionTime($row['completion_date'], $userId); } elseif (!$token->isCompleted()) { $token->setCompletionTime(new \MUtil_Date(), $userId); } $token->getRespondentTrack()->checkTrackTokens($userId, $token); $count = $batch->addToCounter('changed', 1); $batch->setMessage('changed', sprintf($this->plural('%d token imported.', '%d tokens imported.', $count), $count)); } } }
/** * Recursively apply the changes from a dependency * * @param \MUtil_Model_ModelAbstract $model * @param array $changes * @param array $data Referenced data */ protected function _applyDependencyChanges(\MUtil_Model_ModelAbstract $model, array $changes, array &$data) { // \MUtil_Echo::track($model->getName(), $changes, $data); // Here we could allow only those changes this dependency claims to change // or even check all of them are set. foreach ($changes as $name => $settings) { if (isset($settings['model'])) { $submodel = $model->get($name, 'model'); // \MUtil_Echo::track($name, $settings['model'], $data[$name]); if ($submodel instanceof \MUtil_Model_ModelAbstract) { if (!isset($data[$name])) { $data[$name] = array(); } foreach ($data[$name] as &$row) { $submodel->_applyDependencyChanges($submodel, $settings['model'], $row); } } unset($settings['model']); } $model->set($name, $settings); // Change the actual value if (isset($settings['value'])) { // \MUtil_Echo::track($name, $settings['value']); $data[$name] = $settings['value']; } } }
/** * Hook that loads the form data from $_POST or the model * * Or from whatever other source you specify here. */ protected function loadFormData() { if ($this->request->isPost()) { $this->formData = $this->request->getPost() + $this->formData; } else { foreach ($this->importModel->getColNames('default') as $name) { if (!(isset($this->formData[$name]) && $this->formData[$name])) { $this->formData[$name] = $this->importModel->get($name, 'default'); } } } if (!(isset($this->formData['import_id']) && $this->formData['import_id'])) { $this->formData['import_id'] = mt_rand(10000, 99999) . time(); } $this->_session = new \Zend_Session_Namespace(__CLASS__ . '-' . $this->formData['import_id']); if (isset($this->formData[$this->stepFieldName]) && $this->formData[$this->stepFieldName] > 1 && !(isset($this->_session->localfile) && $this->_session->localfile)) { $this->_session->localfile = \MUtil_File::createTemporaryIn($this->tempDirectory, $this->request->getControllerName() . '_'); } // Must always exists $this->fileMode = 'file' === $this->formData['mode']; // Set the translator $translator = $this->getImportTranslator(); if ($translator instanceof \MUtil_Model_ModelTranslatorInterface) { $this->importer->setImportTranslator($translator); } // \MUtil_Echo::track($_POST, $_FILES, $this->formData); }
/** * This is the actual format function, copied from the Exhibitor for field * * @param type $name * @param type $result *@param \MUtil_Model_ModelAbstract $model * @return type */ private function _format($name, $result, $model) { static $view = null; if (!isset($this->_options[$name])) { $this->_options[$name] = $model->get($name, array('default', 'multiOptions', 'formatFunction', 'dateFormat', 'storageFormat', 'itemDisplay')); } $options = $this->_options[$name]; foreach ($options as $key => $value) { switch ($key) { case 'default': if (is_null($result)) { $result = $value; } break; case 'multiOptions': $multiOptions = $value; if (is_array($multiOptions)) { /* * Sometimes a field is an array and will be formatted later on using the * formatFunction -> handle each element in the array. */ if (is_array($result)) { foreach ($result as $key => $value) { if (array_key_exists($value, $multiOptions)) { $result[$key] = $multiOptions[$value]; } } } else { if (array_key_exists($result, $multiOptions)) { $result = $multiOptions[$result]; } } } break; case 'formatFunction': $callback = $value; $result = call_user_func($callback, $result); break; case 'dateFormat': if (array_key_exists('formatFunction', $options)) { // if there is a formatFunction skip the date formatting continue; } $dateFormat = $value; $storageFormat = $model->get($name, 'storageFormat'); $result = \MUtil_Date::format($result, $dateFormat, $storageFormat); break; case 'itemDisplay': $function = $value; if (is_callable($function)) { $result = call_user_func($function, $result); } elseif (is_object($function)) { if ($function instanceof \MUtil_Html_ElementInterface || method_exists($function, 'append')) { $object = clone $function; $result = $object->append($result); } } elseif (is_string($function)) { // Assume it is a html tag when a string $result = \MUtil_Html::create($function, $result); } default: break; } } if (is_object($result)) { // If it is Lazy, execute it if ($result instanceof \MUtil_Lazy_LazyInterface) { $result = \MUtil_Lazy::rise($result); } // If it is Html, render it if ($result instanceof \MUtil_Html_HtmlInterface) { if (is_null($view)) { $viewRenderer = \Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); if (null === $viewRenderer->view) { $viewRenderer->initView(); } $view = $viewRenderer->view; } $result = $result->render($view); } } return $result; }
/** * Restores the header position of question before their corresponding question_sub * * When sub-questions with the same parent are shown continuous the parent is shown * once before them. When the sub-questions are displayed in seperate groups the * parent is shown once at their start. * * Stand alone headers without any corresponding value are removed. When they do have * a value of their own they are still shown, but their position may change according * to their sub-questions position. (NOTE: As in LimeSurvey their are no question * headers with values we leave it at this for the moment.) * * @param \MUtil_Model_ModelAbstract $model * @param array $currentNames The current names in use (allows chaining) * @return array Of the names of labels that should be shown */ protected function restoreHeaderPositions(\MUtil_Model_ModelAbstract $model, array $currentNames) { $lastParent = null; $results = array(); foreach ($currentNames as $name) { if ($model->is($name, 'type', \MUtil_Model::TYPE_NOVALUE)) { // Skip header types that contain no value continue; } if ($parent = $model->get($name, 'parent_question')) { // Check for change of parent if ($lastParent !== $parent) { if (isset($results[$parent])) { // Add another copy of the parent to the array $results[] = $parent; } else { // Insert parent header on name if it was not shown before $results[$parent] = $parent; } $lastParent = $parent; } } else { // Make sure a question (without parent) is picked up as parent too $lastParent = $name; } // If already set (as a $parent) this will not // redisplay the $parent as $result[$name] does // not change position $results[$name] = $name; } return $results; }
/** * Adds rows from the model to the bridge that creates the browse table. * * Overrule this function to add different columns to the browse table, without * having to recode the core table building code. * * @param \MUtil_Model_Bridge_VerticalTableBridge $bridge * @param \MUtil_Model_ModelAbstract $model * @return void */ protected function addShowTableRows(\MUtil_Model_Bridge_VerticalTableBridge $bridge, \MUtil_Model_ModelAbstract $model) { foreach ($model->getItemsOrdered() as $name) { if ($label = $model->get($name, 'label')) { $bridge->addItem($name, $label); } } if ($model->has('row_class')) { // Make sure deactivated rounds are show as deleted foreach ($bridge->getTable()->tbody() as $tr) { foreach ($tr as $td) { if ('td' === $td->tagName) { $td->appendAttrib('class', $bridge->row_class); } } } } }
/** * Use this function for a default application of this type to the model * * @param \MUtil_Model_ModelAbstract $model * @param string $name The field to set the seperator character * @return \MUtil_Model_Type_ConcatenatedRow (continuation pattern) */ public function apply(\MUtil_Model_ModelAbstract $model, $name) { $model->set($name, 'formatFunction', array($this, 'format')); $model->setOnLoad($name, array($this, 'loadValue')); $model->setOnSave($name, array($this, 'saveValue')); if ($model instanceof \MUtil_Model_DatabaseModelAbstract) { $model->setOnTextFilter($name, array($this, 'textFilter')); } $this->options = $model->get($name, 'multiOptions'); return $this; }
/** * Returns a formatted value or a lazy call to that function, * depending on the mode. * * @param string $name The field name or key name * @return mixed Lazy unless in single row mode * @throws \MUtil_Model_ModelException */ public function getFormatted($name) { if (isset($this->{$name})) { return $this->{$name}; } $fieldName = $this->_checkName($name); // Make sure the field is in the trackUsage fields list $this->model->get($fieldName); if (self::MODE_SINGLE_ROW === $this->mode && isset($this->_data[$fieldName])) { $this->{$name} = $this->format($fieldName, $this->_data[$fieldName]); } else { $this->{$name} = new LazyBridgeFormat($this, $fieldName); } if ($fieldName !== $name) { $this->model->get($name); $this->{$fieldName} = $this->{$name}; } return $this->{$name}; }
/** * Returns an array with all columns from the model that have a label * * @param array $data * @param \MUtil_Model_ModelAbstract $model * @return array */ protected function getExcelData($data, \MUtil_Model_ModelAbstract $model) { $headings = array(); $emptyMsg = sprintf($this->_('No %s found.'), $this->getTopic(0)); foreach ($model->getItemsOrdered() as $name) { if ($label = $model->get($name, 'label')) { $headings[$name] = (string) $label; } } $results = array(); $results[] = $headings; if ($headings) { if ($data) { foreach ($data as $row) { $results[] = array_intersect_key($row, $headings); } return $results; } else { $result = array(); foreach ($headings as $key => $value) { $result[$key] = $emptyMsg; } $results[] = $result; return $results; } } else { return array($emptyMsg); } }
/** * Adds columns from the model to the bridge that creates the browse table. * * Overrule this function to add different columns to the browse table, without * having to recode the core table building code. * * @param \MUtil_Model_Bridge_TableBridge $bridge * @param \MUtil_Model_ModelAbstract $model * @return void */ protected function addBrowseTableColumns(\MUtil_Model_Bridge_TableBridge $bridge, \MUtil_Model_ModelAbstract $model) { 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); } } } else { foreach ($model->getItemsOrdered() as $name) { if ($label = $model->get($name, 'label')) { $bridge->add($name, $label); } } } }
/** * Adds columns from the model to the bridge that creates the browse table. * * Overrule this function to add different columns to the browse table, without * having to recode the core table building code. * * @param \MUtil_Model_Bridge_TableBridge $bridge * @param \MUtil_Model_ModelAbstract $model * @return void */ protected function addBrowseTableColumns(\MUtil_Model_Bridge_TableBridge $bridge, \MUtil_Model_ModelAbstract $model) { $tUtil = $this->util->getTokenData(); $table = $bridge->getTable(); $table->appendAttrib('class', 'compliance'); $thead = $table->thead(); $th_row = $thead->tr(array('class' => 'rounds')); $th = $th_row->td(); $span = 1; $cRound = null; $cDesc = null; $thead->tr(); if ($showMenuItem = $this->getShowMenuItem()) { $bridge->addItemLink($showMenuItem->toActionLinkLower($this->request, $bridge)); } // Initialize alter $alternateClass = new \MUtil_Lazy_Alternate(array('odd', 'even')); foreach ($model->getItemsOrdered() as $name) { if ($label = $model->get($name, 'label')) { $round = $model->get($name, 'round'); if ($round == $cRound) { $span++; $class = null; } else { // If the round has an icon, show the icon else just 'R' since // complete round description messes up the display $th->append($cDesc); $th->title = $cRound; $th->colspan = $span; $span = 1; $cRound = $round; if ($cIcon = $model->get($name, 'roundIcon')) { $cDesc = \MUtil_Html_ImgElement::imgFile($cIcon, array('alt' => $cRound, 'title' => $cRound)); } else { if (substr($name, 0, 5) == 'stat_') { $cDesc = 'R'; } else { $cDesc = null; } } $class = 'newRound'; $thClass = $class . ' ' . $alternateClass; // Add alternate class only for th $th = $th_row->td(array('class' => $thClass)); } if ($model->get($name, 'noSort')) { $title = array(\MUtil_Lazy::method($tUtil, 'getStatusDescription', $bridge->{$name}), "\n" . $model->get($name, 'description')); $token = 'tok_' . substr($name, 5); $href = new \MUtil_Html_HrefArrayAttribute(array($this->request->getControllerKey() => 'track', $this->request->getActionKey() => 'show', \MUtil_Model::REQUEST_ID => $bridge->{$token})); $href->setRouteReset(); $onclick = new \MUtil_Html_OnClickArrayAttribute(); $onclick->addUrl($href)->addCancelBubble(); $tds = $bridge->addColumn(array(\MUtil_Html_AElement::iflink($bridge->{$token}, array($href, 'onclick' => 'event.cancelBubble = true;', 'title' => $title, $bridge->{$name}), $bridge->{$name}), 'class' => array('round', \MUtil_Lazy::method($tUtil, 'getStatusClass', $bridge->{$name})), 'title' => $title, 'onclick' => \MUtil_Lazy::iff($bridge->{$token}, $onclick)), array($label, 'title' => $model->get($name, 'description'), 'class' => 'round')); } else { $tds = $bridge->addSortable($name, $label); } if ($class) { $tds->appendAttrib('class', $class); } } } $th->append($cRound); $th->colspan = $span; }
/** * Adds columns from the model to the bridge that creates the browse table. * * Overrule this function to add different columns to the browse table, without * having to recode the core table building code. * * @param \MUtil_Model_Bridge_TableBridge $bridge * @param \MUtil_Model_ModelAbstract $model * @return void */ protected function addBrowseTableColumns(\MUtil_Model_Bridge_TableBridge $bridge, \MUtil_Model_ModelAbstract $model) { foreach ($model->getItemsOrdered() as $name) { if ($label = $model->get($name, 'label')) { $bridge->addSortable($name, $label); } } }