|
From: <gem...@li...> - 2013-01-15 18:02:35
|
Revision: 1101
http://gemstracker.svn.sourceforge.net/gemstracker/?rev=1101&view=rev
Author: matijsdejong
Date: 2013-01-15 18:02:16 +0000 (Tue, 15 Jan 2013)
Log Message:
-----------
new ComplianceAction to show an overview of track progress (first version only: layout needs work)
new MUtil/Model/ModelTransformerInterface.php with three implementations
Modified Paths:
--------------
trunk/library/classes/Gems/Menu/MenuAbstract.php
trunk/library/classes/Gems/Selector/DateSelectorAbstract.php
trunk/library/classes/MUtil/Model/DatabaseModelAbstract.php
trunk/library/classes/MUtil/Model/ModelAbstract.php
trunk/library/classes/MUtil/Model/ModelTransformerAbstract.php
trunk/library/classes/MUtil/Model/SelectModelPaginator.php
trunk/library/classes/MUtil/Model/Transform/RequiredRowsTransformer.php
trunk/library/configs/db/patches.sql
Added Paths:
-----------
trunk/library/classes/Gems/Default/ComplianceAction.php
trunk/library/classes/Gems/Snippets/Tracker/Compliance/
trunk/library/classes/Gems/Snippets/Tracker/Compliance/ComplianceSearchFormSnippet.php
trunk/library/classes/Gems/Snippets/Tracker/Compliance/ComplianceTableSnippet.php
trunk/library/classes/MUtil/Model/ModelTransformerInterface.php
trunk/library/classes/MUtil/Model/Transform/CrossTabTransformer.php
trunk/library/classes/MUtil/Model/Transform/JoinTransformer.php
trunk/library/controllers/ComplianceController.php
Added: trunk/library/classes/Gems/Default/ComplianceAction.php
===================================================================
--- trunk/library/classes/Gems/Default/ComplianceAction.php (rev 0)
+++ trunk/library/classes/Gems/Default/ComplianceAction.php 2013-01-15 18:02:16 UTC (rev 1101)
@@ -0,0 +1,111 @@
+<?php
+
+/**
+ * Copyright (c) 2012, 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.
+ *
+ *
+ * @package Gems
+ * @subpackage Default
+ * @author Matijs de Jong <mj...@ma...>
+ * @copyright Copyright (c) 2012 Erasmus MC
+ * @license New BSD License
+ * @version $id: ComplianceAction.php 203 2012-01-01t 12:51:32Z matijs $
+ */
+
+/**
+ *
+ *
+ * @package Gems
+ * @subpackage Default
+ * @copyright Copyright (c) 2012 Erasmus MC
+ * @license New BSD License
+ * @since Class available since version 1.6
+ */
+class Gems_Default_ComplianceAction extends Gems_Controller_ModelSnippetActionAbstract
+{
+ /**
+ * The snippets used for the autofilter action.
+ *
+ * @var mixed String or array of snippets name
+ */
+ protected $autofilterSnippets = 'Tracker_Compliance_ComplianceTableSnippet';
+
+ /**
+ * The snippets used for the index action, before those in autofilter
+ *
+ * @var mixed String or array of snippets name
+ */
+ protected $indexStartSnippets = array('Generic_ContentTitleSnippet', 'Tracker_Compliance_ComplianceSearchFormSnippet');
+
+ /**
+ * 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
+ */
+ public function createModel($detailed, $action)
+ {
+ $model = new Gems_Model_JoinModel('resptrack' , 'gems__respondent2track');
+ $model->addTable('gems__respondent2org', array(
+ 'gr2t_id_user' => 'gr2o_id_user',
+ 'gr2t_id_organization' => 'gr2o_id_organization'
+ ));
+ $model->addTable('gems__tracks', array('gr2t_id_track' => 'gtr_id_track'));
+
+ $model->resetOrder();
+ $model->set('gr2o_patient_nr', 'label', $this->_('Respondent nr'));
+ $model->set('gr2t_start_date', 'label', $this->_('Start date'), 'dateFormat', 'dd-MM-yyyy');
+ $model->set('gr2t_end_date', 'label', $this->_('End date'), 'dateFormat', 'dd-MM-yyyy');
+
+ return $model;
+ }
+
+ /**
+ * Helper function to get the title for the index action.
+ *
+ * @return $string
+ */
+ public function getIndexTitle()
+ {
+ return $this->_('Compliance');
+ }
+
+ /**
+ * 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('track', 'tracks', $count);
+ }
+}
Modified: trunk/library/classes/Gems/Menu/MenuAbstract.php
===================================================================
--- trunk/library/classes/Gems/Menu/MenuAbstract.php 2013-01-14 18:21:45 UTC (rev 1100)
+++ trunk/library/classes/Gems/Menu/MenuAbstract.php 2013-01-15 18:02:16 UTC (rev 1101)
@@ -322,6 +322,9 @@
{
$infoPage = $this->addContainer($label);
+ $infoPage->addPage($this->_('Compliance'), 'pr.plan.compliance', 'compliance', 'index')
+ ->addAutofilterAction();
+
$plans[] = $infoPage->addPage($this->_('By period'), 'pr.plan.overview', 'overview-plan', 'index');
$plans[] = $infoPage->addPage($this->_('By token'), 'pr.plan.token', 'token-plan', 'index');
$plans[] = $infoPage->addPage($this->_('By respondent'), 'pr.plan.respondent', 'respondent-plan', 'index');
Modified: trunk/library/classes/Gems/Selector/DateSelectorAbstract.php
===================================================================
--- trunk/library/classes/Gems/Selector/DateSelectorAbstract.php 2013-01-14 18:21:45 UTC (rev 1100)
+++ trunk/library/classes/Gems/Selector/DateSelectorAbstract.php 2013-01-15 18:02:16 UTC (rev 1101)
@@ -329,7 +329,7 @@
} else {
$this->dateFactorChanges = array_fill_keys(array('D', 'W', 'M', 'Y'), 0);
}
- // MUtil_Echo::r($requiredRows);
+ // M qUtil_Echo::track($requiredRows);
// MUtil_Echo::rs($start, $end, $where);
$select = new Zend_Db_Select($this->db);
@@ -346,12 +346,13 @@
// Display by column cannot use formatFunction as it is a simple repeater
// $model->set('duration_avg', 'formatFunction', $this->util->getLocalized()->formatNumber);
- $tmodel = new MUtil_Model_Transform_RequiredRowsTransformer($model);
- $tmodel->setDefaultRow($this->getDefaultRow());
- $tmodel->setRequiredRows($requiredRows);
- $tmodel->setKeyItemCount($keyCount);
+ $transformer = new MUtil_Model_Transform_RequiredRowsTransformer();
+ $transformer->setDefaultRow($this->getDefaultRow());
+ $transformer->setRequiredRows($requiredRows);
+ $transformer->setKeyItemCount($keyCount);
+ $model->addTransformer($transformer);
- return $tmodel;
+ return $model;
}
protected function getDateDescriptions()
Added: trunk/library/classes/Gems/Snippets/Tracker/Compliance/ComplianceSearchFormSnippet.php
===================================================================
--- trunk/library/classes/Gems/Snippets/Tracker/Compliance/ComplianceSearchFormSnippet.php (rev 0)
+++ trunk/library/classes/Gems/Snippets/Tracker/Compliance/ComplianceSearchFormSnippet.php 2013-01-15 18:02:16 UTC (rev 1101)
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * Copyright (c) 2012, 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.
+ *
+ *
+ * @package Gems
+ * @subpackage Tracker
+ * @author Matijs de Jong <mj...@ma...>
+ * @copyright Copyright (c) 2012 Erasmus MC
+ * @license New BSD License
+ * @version $id: ComplianceSearchFormSnippet.php 203 2012-01-01t 12:51:32Z matijs $
+ */
+
+/**
+ *
+ *
+ * @package Gems
+ * @subpackage Tracker
+ * @copyright Copyright (c) 2012 Erasmus MC
+ * @license New BSD License
+ * @since Class available since version 1.5
+ */
+class Gems_Snippets_Tracker_Compliance_ComplianceSearchFormSnippet extends Gems_Snippets_AutosearchFormSnippet
+{
+ /**
+ * Returns a text element for autosearch. Can be overruled.
+ *
+ * The form / html elements to search on. Elements can be grouped by inserting null's between them.
+ * That creates a distinct group of elements
+ *
+ * @param array $data The $form field values (can be usefull, but no need to set them)
+ * @return array Of Zend_Form_Element's or static tekst to add to the html or null for group breaks.
+ */
+ protected function getAutoSearchElements(array $data)
+ {
+ $elements[] = $this->_createSelectElement('gr2t_id_track',
+ $this->util->getTrackData()->getAllTracks(),
+ $this->_('(select a track)'));
+
+ $elements[] = $this->_createSelectElement('gr2o_id_organization',
+ $this->util->getDbLookup()->getOrganizationsWithRespondents(),
+ $this->_('(all organizations)'));
+
+ return $elements;
+ }
+
+}
Added: trunk/library/classes/Gems/Snippets/Tracker/Compliance/ComplianceTableSnippet.php
===================================================================
--- trunk/library/classes/Gems/Snippets/Tracker/Compliance/ComplianceTableSnippet.php (rev 0)
+++ trunk/library/classes/Gems/Snippets/Tracker/Compliance/ComplianceTableSnippet.php 2013-01-15 18:02:16 UTC (rev 1101)
@@ -0,0 +1,181 @@
+<?php
+
+/**
+ * Copyright (c) 2012, 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.
+ *
+ *
+ * @package Gems
+ * @subpackage Tracker
+ * @author Matijs de Jong <mj...@ma...>
+ * @copyright Copyright (c) 2012 Erasmus MC
+ * @license New BSD License
+ * @version $id: ComplianceTableSnippet.php 203 2012-01-01t 12:51:32Z matijs $
+ */
+
+/**
+ *
+ *
+ * @package Gems
+ * @subpackage Tracker
+ * @copyright Copyright (c) 2012 Erasmus MC
+ * @license New BSD License
+ * @since Class available since version 1.5
+ */
+class Gems_Snippets_Tracker_Compliance_ComplianceTableSnippet extends Gems_Snippets_ModelTableSnippetGeneric
+{
+ /**
+ *
+ * @var Zend_Db_Adapter_Abstract
+ */
+ protected $db;
+
+ /**
+ *
+ * @var Gems_Loader
+ */
+ protected $loader;
+
+ /**
+ * Creates the model
+ *
+ * @return MUtil_Model_ModelAbstract
+ */
+ protected function createModel()
+ {
+ $model = parent::createModel();
+ $trackId = $this->getTrackId();
+
+ if (! $trackId) {
+ return $model;
+ }
+
+ $select = $this->db->select();
+ $select->from('gems__rounds', array('gro_id_round', 'gro_id_order', 'gro_round_description'))
+ ->where('gro_id_track = ?', $trackId)
+ ->order('gro_id_order');
+
+ $data = $this->db->fetchAll($select);
+
+ if (! $data) {
+ return $model;
+ }
+
+ $status = new Zend_Db_Expr("
+ CASE
+ WHEN gto_completion_time IS NOT NULL THEN 'A'
+ WHEN gto_valid_from IS NULL THEN 'U'
+ WHEN gto_valid_from > CURRENT_TIMESTAMP THEN 'W'
+ WHEN gto_valid_until < CURRENT_TIMESTAMP THEN 'M'
+ ELSE 'O'
+ END
+ ");
+
+ // $labels = $model->getCol('label');
+
+ $select = $this->db->select();
+ $select->from('gems__tokens', array('gto_id_respondent_track', 'gto_id_round', 'status' => $status))
+ ->joinInner('gems__reception_codes', 'gto_reception_code = grc_id_reception_code', array())
+ ->where('grc_success = 1')
+ ->where('gto_id_track = ?', $trackId)
+ ->order('gto_id_respondent_track')
+ ->order('gto_round_order');
+
+ // MUtil_Echo::track($this->db->fetchAll($select));
+
+ $newModel = new MUtil_Model_SelectModel($select, 'tok');
+ $newModel->setKeys(array('gto_id_respondent_track'));
+ // $model->addLeftTable('gems__tokens', array('gr2t_id_track' => 'gto_id_track'));
+ // $model->addLeftTable('gems__reception_codes', array('gto_reception_code' => 'grc_id_reception_code'));
+ // $model->addFilter(array('grc_success' => 1));
+ // $newModel = $model;
+
+ $transformer = new MUtil_Model_Transform_CrossTabTransformer();
+ $transformer->setCrosstabFields('gto_id_round', 'status');
+
+ foreach ($data as $row) {
+ $name = 'col_' . $row['gro_id_round'];
+ $transformer->set($name, 'label', $row['gro_id_order'], 'description', $row['gro_round_description']);
+ // break;
+ }
+
+ $newModel->addTransformer($transformer);
+ // MUtil_Echo::track($data);
+
+ $joinTrans = new MUtil_Model_Transform_JoinTransformer();
+ $joinTrans->addModel($newModel, array('gr2t_id_respondent_track' => 'gto_id_respondent_track'));
+
+ $model->resetOrder();
+ $model->set('gr2o_patient_nr');
+ $model->set('gr2t_start_date');
+ $model->addTransformer($joinTrans);
+ return $model;
+
+ return $newModel;
+ }
+
+ /**
+ * Returns a show menu item, if access is allowed by privileges
+ *
+ * @return Gems_Menu_SubMenuItem
+ */
+ protected function getShowMenuItem()
+ {
+ return $this->findMenuItem('track', 'show-track');
+ }
+
+ /**
+ *
+ * @return int Return the track id if any or null
+ */
+ public function getTrackId()
+ {
+ if ($this->requestCache) {
+ $data = $this->requestCache->getProgramParams();
+ if (isset($data['gr2t_id_track'])) {
+ return $data['gr2t_id_track'];
+ }
+ } else {
+ return $this->request->getParam('gr2t_id_track');
+ }
+ }
+
+ /**
+ * Overrule to implement snippet specific filtering and sorting.
+ *
+ * @param MUtil_Model_ModelAbstract $model
+ */
+ protected function processFilterAndSort(MUtil_Model_ModelAbstract $model)
+ {
+ $trackId = $this->getTrackId();
+
+ if ($trackId) {
+ parent::processFilterAndSort($model);
+ } else {
+ $model->setFilter(array('1=0'));
+ $this->onEmpty = $this->_('No track selected...');
+ }
+ }
+}
Modified: trunk/library/classes/MUtil/Model/DatabaseModelAbstract.php
===================================================================
--- trunk/library/classes/MUtil/Model/DatabaseModelAbstract.php 2013-01-14 18:21:45 UTC (rev 1100)
+++ trunk/library/classes/MUtil/Model/DatabaseModelAbstract.php 2013-01-15 18:02:16 UTC (rev 1101)
@@ -166,6 +166,16 @@
}
if (null === $value) {
$select->where($name . ' IS NULL');
+ } elseif (is_array($value)) {
+ if ($value) {
+ foreach ($value as $sub) {
+ $subs[] = $adapter->quote($value);
+ }
+ $select->where($name . ' IN (' . implode(', ', $subs) . ')');
+ } else {
+ // Never a result when a value should be one of an empty set.
+ $select->where('1=0');
+ }
} else {
$select->where($name . ' = ?', $value);
}
@@ -318,6 +328,23 @@
return $this->_createSelect($filter, $sort)->query(Zend_Db::FETCH_ASSOC)->fetchAll();
}
+ /**
+ * Returns an array containing the first requested item.
+ *
+ * @param mixed $filter True to use the stored filter, array to specify a different filter
+ * @param mixed $sort True to use the stored sort, array to specify a different sort
+ * @return array An array or false
+ */
+ protected function _loadFirst($filter = true, $sort = true)
+ {
+ $select = $this->_createSelect($filter, $sort);
+ $select->limit(1, 0);
+
+ $data = $select->query(Zend_Db::FETCH_ASSOC)->fetch();
+
+ return $data;
+ }
+
protected function _loadTableMetaData(Zend_Db_Table_Abstract $table)
{
$table_name = $this->_getTableName($table);
@@ -703,10 +730,10 @@
public function formatLoadDate($value, $isNew = false, $name = null, array $context = array())
{
// If not empty or zend_db_expression and not already a zend date, we
- // transform to a Zend_Date using the ISO_8601 format
+ // transform to a Zend_Date using the ISO_8601 format
if (!empty($value) && !($value instanceof Zend_Date) && !($value instanceof Zend_Db_Expr)) {
try {
- $tmpDate = new MUtil_Date($value, Zend_Date::ISO_8601);
+ $tmpDate = new MUtil_Date($value, Zend_Date::ISO_8601);
} catch (Exception $exc) {
// On failure, we use the input value
$tmpDate = $value;
@@ -895,26 +922,6 @@
}
/**
- * Returns an array containing the first requested item.
- *
- * @param mixed $filter True to use the stored filter, array to specify a different filter
- * @param mixed $sort True to use the stored sort, array to specify a different sort
- * @return array An array or false
- */
- public function loadFirst($filter = true, $sort = true)
- {
- $select = $this->_createSelect($filter, $sort);
- $select->limit(1, 0);
-
- $data = $select->query(Zend_Db::FETCH_ASSOC)->fetch();
- if (is_array($data)) {
- $data = $this->_filterDataAfterLoad($data, false);
- }
-
- return $data;
- }
-
- /**
* Returns a Zend_Paginator for the items in the model
*
* @param mixed $filter True to use the stored filter, array to specify a different filter
@@ -929,26 +936,6 @@
return new Zend_Paginator($adapter);
}
- /**
- * Helper function for SelectModelPaginator to process
- * setOnLoads.
- *
- * @see MUtil_Model_SelectModelPaginator
- *
- * @param array $data Nested array
- * @return array Nested
- */
- public function processAfterLoad(array $data)
- {
- if ($this->getMeta(parent::LOAD_TRANSFORMER)) {
- foreach ($data as $key => $row) {
- $data[$key] = $this->_filterDataAfterLoad($row, false);
- }
- }
-
- return $data;
- }
-
// abstract public function save(array $newValues);
/**
Modified: trunk/library/classes/MUtil/Model/ModelAbstract.php
===================================================================
--- trunk/library/classes/MUtil/Model/ModelAbstract.php 2013-01-14 18:21:45 UTC (rev 1100)
+++ trunk/library/classes/MUtil/Model/ModelAbstract.php 2013-01-15 18:02:16 UTC (rev 1101)
@@ -110,12 +110,22 @@
private $_model_used = false;
/**
+ *
+ * @var array of MUtil_Model_ModelTransformerInterface
+ */
+ private $_transformers = array();
+
+ /**
* The increment for item ordering, default is 10
*
* @var int
*/
public $orderIncrement = 10;
+ /**
+ *
+ * @param string $modelName Hopefully unique model name
+ */
public function __construct($modelName)
{
$this->_model_name = $modelName;
@@ -267,6 +277,20 @@
*/
abstract protected function _load($filter = true, $sort = true);
+ /**
+ * Returns a nested array containing the items requested.
+ *
+ * @param mixed $filter True to use the stored filter, array to specify a different filter
+ * @param mixed $sort True to use the stored sort, array to specify a different sort
+ * @return array Nested array or false
+ */
+ protected function _loadFirst($filter = true, $sort = true)
+ {
+ $data = $this->_load($filter, $sort);
+
+ return reset($data);
+ }
+
protected function addChanged($add = 1)
{
$this->_changedCount += $add;
@@ -310,6 +334,21 @@
}
/**
+ * Add a model transformer
+ *
+ * @param MUtil_Model_ModelTransformerInterface $transformer
+ * @return MUtil_Model_ModelAbstract (continuation pattern)
+ */
+ public function addTransformer(MUtil_Model_ModelTransformerInterface $transformer)
+ {
+ foreach ($transformer->getFieldInfo($this) as $name => $info) {
+ $this->set($name, $info);
+ }
+ $this->_transformers[] = $transformer;
+ return $this;
+ }
+
+ /**
* Stores the fields that can be used for sorting or filtering in the
* sort / filter objects attached to this model.
*
@@ -864,6 +903,17 @@
}
/**
+ * Get the model transformers
+ *
+ * @return array of MUtil_Model_ModelTransformerInterface
+ */
+ public function getTransformers()
+ {
+ $this->_transformers[] = $transformer;
+ return $this;
+ }
+
+ /**
* Splits a wildcard search text into its constituent parts.
*
* @param string $searchText
@@ -1000,10 +1050,8 @@
{
$data = $this->_load($filter, $sort);
- if (is_array($data) && $this->getMeta(self::LOAD_TRANSFORMER)) {
- foreach ($data as $key => $row) {
- $data[$key] = $this->_filterDataAfterLoad($row, false);
- }
+ if (is_array($data)) {
+ $data = $this->processAfterLoad($data);
}
return $data;
@@ -1018,13 +1066,20 @@
*/
public function loadFirst($filter = true, $sort = true)
{
- $data = $this->_load($filter, $sort);
- // Return the first row or null.
- $data = reset($data);
- if (is_array($data) && $this->getMeta(self::LOAD_TRANSFORMER)) {
- $data = $this->_filterDataAfterLoad($data, false);
+ $row = $this->_loadFirst($filter, $sort);
+ MUtil_Echo::track($row);
+
+ if (! is_array($row)) {
+ // Return false
+ return false;
}
- return $data;
+
+ // Transform the row
+ $data = $this->processAfterLoad(array($row));
+ MUtil_Echo::track($data);
+
+ // Return resulting first row
+ return reset($data);
}
/**
@@ -1084,6 +1139,29 @@
/**
+ * Helper function that procesess the raw data after a load.
+ *
+ * @see MUtil_Model_SelectModelPaginator
+ *
+ * @param array $data Nested array containing rows
+ * @return array Nested
+ */
+ public function processAfterLoad(array $data)
+ {
+ foreach ($this->_transformers as $transformer) {
+ $data = $transformer->transformLoad($this, $data);
+ }
+
+ if ($this->getMeta(self::LOAD_TRANSFORMER)) {
+ foreach ($data as $key => $row) {
+ $data[$key] = $this->_filterDataAfterLoad($row, false);
+ }
+ }
+
+ return $data;
+ }
+
+ /**
* Remove one attribute for a field name in the model.
*
* Example:
@@ -1094,7 +1172,7 @@
*
* @param string $name The fieldname
* @param string $key The name of the key
- * @return $this
+ * @return MUtil_Model_ModelAbstract (continuation pattern)
*/
public function remove($name, $key = null)
{
@@ -1167,13 +1245,13 @@
* </code>
* Both set the attribute 'save' to true for 'field_x'.
*
- * @param string $name The fieldname
+ * @param string $name The fieldname
* @param mixed $arrayOrKey1 A key => value array or the name of the first key, see MUtil_Args::pairs()
* @param mixed $value1 The value for $arrayOrKey1 or null when $arrayOrKey1 is an array
* @param string $key2 Optional second key when $arrayOrKey1 is a string
* @param mixed $value2 Optional second value when $arrayOrKey1 is a string,
* an unlimited number of $key values pairs can be given.
- * @return $this
+ * @return \MUtil_Model_ModelAbstract
*/
public function set($name, $arrayOrKey1 = null, $value1 = null, $key2 = null, $value2 = null)
{
@@ -1261,7 +1339,7 @@
* @param mixed $value1 The value for $arrayOrKey1 or null when $arrayOrKey1 is an array
* @param string $key2 Optional second key when $arrayOrKey1 is a string
* @param mixed $value2 Optional second value when $arrayOrKey1 is a string, an unlimited number of $key values pairs can be given.
- * @return $this
+ * @return MUtil_Model_ModelAbstract (continuation pattern)
*/
public function setCol($arrayOrKey1 = null, $value1 = null, $key2 = null, $value2 = null)
{
@@ -1353,7 +1431,7 @@
* @param mixed $value1 The value for $arrayOrKey1 or null when $arrayOrKey1 is an array
* @param string $key2 Optional second key when $arrayOrKey1 is a string
* @param mixed $value2 Optional second value when $arrayOrKey1 is a string, an unlimited number of $key values pairs can be given.
- * @return $this
+ * @return MUtil_Model_ModelAbstract (continuation pattern)
*/
public function setMulti(array $names, $arrayOrKey1 = null, $value1 = null, $key2 = null, $value2 = null)
{
@@ -1443,6 +1521,22 @@
return $this->setSaveWhen($name, array(__CLASS__, 'whenNotNull'));
}
+ /**
+ * set the model transformers
+ *
+ * @param array $transformers of MUtil_Model_ModelTransformerInterface
+ * @return MUtil_Model_ModelAbstract (continuation pattern)
+ */
+ public function setTransformers(array $transformers)
+ {
+ $this->_transformers = array();
+ foreach ($transformers as $transformer) {
+ $this->addTransformer($transformer);
+ }
+ return $this;
+ }
+
+
public function setSort($value)
{
return $this->setMeta('sort', $this->_checkSortValue($value));
Modified: trunk/library/classes/MUtil/Model/ModelTransformerAbstract.php
===================================================================
--- trunk/library/classes/MUtil/Model/ModelTransformerAbstract.php 2013-01-14 18:21:45 UTC (rev 1100)
+++ trunk/library/classes/MUtil/Model/ModelTransformerAbstract.php 2013-01-15 18:02:16 UTC (rev 1101)
@@ -25,208 +25,140 @@
* 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 MUtil
+ * @subpackage Model
+ * @author Matijs de Jong <mj...@ma...>
+ * @copyright Copyright (c) 2012 Erasmus MC
+ * @license New BSD License
+ * @version $id: ModelTransformerInterface.php 203 2012-01-01t 12:51:32Z matijs $
*/
/**
- * @author Matijs de Jong
- * @since 1.0
- * @version 1.1
- * @package MUtil
+ * A general transformer that implements all required functions, without
+ * them doing anything so you can just implement what you need.
+ *
+ * @package MUtil
* @subpackage Model
+ * @copyright Copyright (c) 2012 Erasmus MC
+ * @license New BSD License
+ * @since Class available since MUtil version 1.2 (in current form)
*/
-abstract class MUtil_Model_ModelTransformerAbstract extends MUtil_Model_ModelAbstract
+abstract class MUtil_Model_ModelTransformerAbstract implements MUtil_Model_ModelTransformerInterface
{
- protected $sourceModel;
-
- public function __construct(array $args, array $paramTypes = array())
- {
- $paramTypes['sourceModel'] = 'MUtil_Model_ModelAbstract';
- $paramTypes['name'] = 'is_string';
-
- $args = MUtil_Ra::args($args, $paramTypes);
-
- if (isset($args['name'])) {
- $name = $args['name'];
- unset($args['name']);
- } else {
- if (isset($args['sourceModel'])) {
- $name = $args['sourceModel']->getName();
- } else {
- // MUtil_Echo::r($args);
- throw new MUtil_Model_ModelException('No $name or $sourceModel parameter specified for ' . get_class($this) . ' constructor.');
- }
- }
- // MUtil_Echo::r($args, $name);
-
- parent::__construct($name);
-
- foreach ($args as $name => $arg) {
- $function = 'set' . ucfirst($name);
- if (method_exists($this, $function)) {
- $this->$function($arg);
- } else {
- throw new MUtil_Model_ModelException("Unknown argument $name in " . get_class($this) . ' constructor.');
- }
- }
- }
-
- protected function _getKeyValue($name, $key)
- {
- if ($this->sourceModel) {
- return $this->sourceModel->_getKeyValue($name, $key);
- }
- }
-
/**
- * Returns a nested array containing the items requested.
*
- * @param mixed $filter True to use the stored filter, array to specify a different filter
- * @param mixed $sort True to use the stored sort, array to specify a different sort
- * @return array Nested array or false
+ * @var array
*/
- protected function _load($filter = true, $sort = true)
- {
- $data = $this->sourceModel->_load($filter, $sort);
+ protected $_fields = array();
- return $this->transform($data, $filter, $sort);
- }
-
- public function delete($filter = true)
- {
- throw new Exception('Cannot delete ' . get_class($this) . ' data.');
- }
-
+ /**
+ * Gets one or more values for a certain field name.
+ *
+ * @see MUtil_Model_ModelAbstract->get()
+ *
+ * @param string $name Field name
+ * @param string|array|null $arrayOrKey1 Null or the name of a single attribute or an array of attribute names
+ * @param string $key2 Optional a second attribute name.
+ * @return mixed
+ */
public function get($name, $arrayOrKey1 = null, $key2 = null)
{
- if ($this->sourceModel) {
- $args = func_get_args();
+ $args = func_get_args();
+ $args = MUtil_Ra::args($args, 1);
- call_user_func_array(array($this->sourceModel, 'get'), $args);
- }
- return $this;
- }
+ switch (count($args)) {
+ case 0:
+ if (isset($this->_fields[$name])) {
+ return $this->_fields[$name];
+ } else {
+ return array();
+ }
- public function getAlias($name)
- {
- if ($this->sourceModel) {
- return $this->sourceModel->getAlias($name);
- }
- }
+ case 1:
+ $key = $arrayOrKey1;
+ if (isset($this->_fields[$name][$arrayOrKey1])) {
+ return $this->_fields[$name][$arrayOrKey1];
+ } else {
+ return null;
+ }
- public function getItemNames()
- {
- if ($this->sourceModel) {
- return $this->sourceModel->getItemNames();
+ default:
+ $results = array();
+ foreach ($args as $key) {
+ if (isset($this->_fields[$name][$arrayOrKey1])) {
+ $results[$key] = $this->_fields[$name][$arrayOrKey1];
+ }
+ }
+ return $results;
}
}
- public function getItemsOrdered()
+ /**
+ * If the transformer add's fields, these should be returned here.
+ * Called in $model->AddTransformer(), so the transformer MUST
+ * know which fields to add by then (optionally using the model
+ * for that).
+ *
+ * @param MUtil_Model_ModelAbstract $model The parent model
+ * @return array Of filedname => set() values
+ */
+ public function getFieldInfo(MUtil_Model_ModelAbstract $model)
{
- if ($this->sourceModel) {
- return $this->sourceModel->getItemsOrdered();
- }
+ return $this->_fields;
}
/**
- * Return an identifier the item specified by $forData
+ * Set one or more attributes for a field names in the model.
*
- * basically transforms the fieldnames ointo oan IDn => value array
+ * @see MUtil_Model_ModelAbstract->set()
*
- * @param mixed $forData Array value to vilter on
- * @param array $href Or ArrayObject
- * @return array That can by used as href
+ * @param string $name The fieldname
+ * @param mixed $arrayOrKey1 A key => value array or the name of the first key, see MUtil_Args::pairs()
+ * @param mixed $value1 The value for $arrayOrKey1 or null when $arrayOrKey1 is an array
+ * @param string $key2 Optional second key when $arrayOrKey1 is a string
+ * @param mixed $value2 Optional second value when $arrayOrKey1 is a string,
+ * an unlimited number of $key values pairs can be given.
+ * @return \MUtil_Model_ModelTransformerAbstract
*/
- public function getKeyRef($forData, $href = array())
- {
- if ($this->sourceModel) {
- return $this->sourceModel->getKeyRef($forData, $href);
- }
- }
-
- public function getKeys($reset = false)
- {
- if ($this->sourceModel) {
- return $this->sourceModel->getKeys($reset);
- }
- }
-
- public function getMeta($key, $default = null)
- {
- if ($this->sourceModel) {
- return $this->sourceModel->getMeta($key, $default);
- }
- }
-
- public function getSourceModel()
- {
- return $this->sourceModel;
- }
-
- public function has($name, $subkey = null)
- {
- if ($this->sourceModel) {
- return $this->sourceModel->has($name, $subkey);
- }
- return false;
- }
-
- public function hasMeta($key)
- {
- if ($this->sourceModel) {
- return $this->sourceModel->hasMeta($key);
- }
- return false;
- }
-
- public function hasNew()
- {
- return false;
- }
-
- public function resetOrder()
- {
- if ($this->sourceModel) {
- $this->sourceModel->resetOrder();
- }
- return $this;
- }
-
- public function save(array $newValues, array $filter = null)
- {
- throw new Exception('Cannot save ' . get_class($this) . ' data.');
- }
-
public function set($name, $arrayOrKey1 = null, $value1 = null, $key2 = null, $value2 = null)
{
- if ($this->sourceModel) {
- $args = func_get_args();
+ $args = func_get_args();
+ $args = MUtil_Ra::pairs($args, 1);
- call_user_func_array(array($this->sourceModel, 'set'), $args);
- }
- return $this;
- }
+ foreach ($args as $key => $value) {
+ // If $key end with ] it is array value
+ if (substr($key, -1) == ']') {
+ if (substr($key, -2) == '[]') {
+ // If $key ends with [], append it to array
+ $key = substr($key, 0, -2);
+ $this->_fields[$name][$key][] = $value;
+ } else {
+ // Otherwise extract subkey
+ $pos = strpos($key, '[');
+ $subkey = substr($key, $pos + 1, -1);
+ $key = substr($key, 0, $pos);
- public function setKeys(array $keys)
- {
- if ($this->sourceModel) {
- $this->sourceModel->setKeys($key, $value);
+ $this->_fields[$name][$key][$subkey] = $value;
+ }
+ } else {
+ $this->_fields[$name][$key] = $value;
+ }
}
- return $this;
- }
- public function setMeta($key, $value)
- {
- if ($this->sourceModel) {
- $this->sourceModel->setMeta($key, $value);
- }
return $this;
}
- public function setSourceModel(MUtil_Model_ModelAbstract $model)
+ /**
+ * The transform function performs the actual transformation of the data and is called after
+ * the loading of the data in the source model.
+ *
+ * @param MUtil_Model_ModelAbstract $model The parent model
+ * @param array $data Nested array
+ * @return array Nested array containing (optionally) transformed data
+ */
+ public function transformLoad(MUtil_Model_ModelAbstract $model, array $data)
{
- $this->sourceModel = $model;
- return $this;
+ return $data;
}
-
- abstract public function transform($data, $filter = true, $sort = true);
}
Added: trunk/library/classes/MUtil/Model/ModelTransformerInterface.php
===================================================================
--- trunk/library/classes/MUtil/Model/ModelTransformerInterface.php (rev 0)
+++ trunk/library/classes/MUtil/Model/ModelTransformerInterface.php 2013-01-15 18:02:16 UTC (rev 1101)
@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * Copyright (c) 2012, 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.
+ *
+ *
+ * @package MUtil
+ * @subpackage Model
+ * @author Matijs de Jong <mj...@ma...>
+ * @copyright Copyright (c) 2012 Erasmus MC
+ * @license New BSD License
+ * @version $id: ModelTransformerInterface.php 203 2012-01-01t 12:51:32Z matijs $
+ */
+
+/**
+ * An general interface to transform the data retrieved by a model
+ *
+ * @package MUtil
+ * @subpackage Model
+ * @copyright Copyright (c) 2012 Erasmus MC
+ * @license New BSD License
+ * @since Class available since MUtil version 1.2
+ */
+interface MUtil_Model_ModelTransformerInterface
+{
+ /**
+ * If the transformer add's fields, these should be returned here.
+ * Called in $model->AddTransformer(), so the transformer MUST
+ * know which fields to add by then (optionally using the model
+ * for that).
+ *
+ * @param MUtil_Model_ModelAbstract $model The parent model
+ * @return array Of filedname => set() values
+ */
+ public function getFieldInfo(MUtil_Model_ModelAbstract $model);
+
+ /**
+ * The transform function performs the actual transformation of the data and is called after
+ * the loading of the data in the source model.
+ *
+ * @param MUtil_Model_ModelAbstract $model The parent model
+ * @param array $data Nested array
+ * @return array Nested array containing (optionally) transformed data
+ */
+ public function transformLoad(MUtil_Model_ModelAbstract $model, array $data);
+}
Modified: trunk/library/classes/MUtil/Model/SelectModelPaginator.php
===================================================================
--- trunk/library/classes/MUtil/Model/SelectModelPaginator.php 2013-01-14 18:21:45 UTC (rev 1100)
+++ trunk/library/classes/MUtil/Model/SelectModelPaginator.php 2013-01-15 18:02:16 UTC (rev 1101)
@@ -94,7 +94,7 @@
$items = $this->_selectAdapter->getItems($offset, $itemCountPerPage);
// MUtil_Echo::track($items);
- if ($items && is_array($items)) {
+ if (is_array($items)) {
$items = $this->_model->processAfterLoad($items);
}
// MUtil_Echo::track($items);
Added: trunk/library/classes/MUtil/Model/Transform/CrossTabTransformer.php
===================================================================
--- trunk/library/classes/MUtil/Model/Transform/CrossTabTransformer.php (rev 0)
+++ trunk/library/classes/MUtil/Model/Transform/CrossTabTransformer.php 2013-01-15 18:02:16 UTC (rev 1101)
@@ -0,0 +1,122 @@
+<?php
+
+/**
+ * Copyright (c) 2012, 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.
+ *
+ *
+ * @package MUtil
+ * @subpackage Model
+ * @author Matijs de Jong <mj...@ma...>
+ * @copyright Copyright (c) 2012 Erasmus MC
+ * @license New BSD License
+ * @version $id: CrossTabTransformer.php 203 2012-01-01t 12:51:32Z matijs $
+ */
+
+/**
+ *
+ *
+ * @package MUtil
+ * @subpackage Model
+ * @copyright Copyright (c) 2012 Erasmus MC
+ * @license New BSD License
+ * @since Class available since MUtil version 1.2
+ */
+class MUtil_Model_Transform_CrossTabTransformer extends MUtil_Model_ModelTransformerAbstract
+{
+ /**
+ * The field to crosstab over
+ *
+ * @var string
+ */
+ protected $idField;
+
+ /**
+ *
+ * @var string
+ */
+ protected $valueField;
+
+ /**
+ *
+ * @param string $idField The field values to perform the crosstab over
+ * @param string $valueField The field values to crosstab
+ * @return MUtil_Model_Transform_CrossTabTransformer (continuation pattern)
+ */
+ public function setCrosstabFields($idField, $valueField)
+ {
+ $this->idField = $idField;
+ $this->valueField = $valueField;
+
+ return $this;
+
+ }
+
+ /**
+ * The transform function performs the actual transformation of the data and is called after
+ * the loading of the data in the source model.
+ *
+ * @param MUtil_Model_ModelAbstract $model The parent model
+ * @param array $data Nested array
+ * @return array Nested array containing (optionally) transformed data
+ */
+ public function transformLoad(MUtil_Model_ModelAbstract $model, array $data)
+ {
+ if (! $data) {
+ return $data;
+ }
+
+ //*
+ $row = reset($data);
+ if (! ($this->idField &&
+ $this->valueField &&
+ isset($row[$this->idField]) &&
+ array_key_exists($this->valueField, $row)
+ )) {
+ return $data;
+ }
+
+ $keys = $model->getKeys();
+ $keys = array_combine($keys, $keys);
+ $default = array_fill_keys(array_keys($this->_fields), null);
+ $except = array($this->idField => 1, $this->valueField => 1);
+ $results = array();
+ foreach ($data as $row) {
+ $name = 'col_' . $row[$this->idField];
+
+ if (isset($this->_fields[$name])) {
+ $key = implode("\t", array_intersect_key($row, $keys));
+
+ if (! isset($results[$key])) {
+ $results[$key] = array_diff_key($row, $except) + $default;
+ }
+ $results[$key][$name] = $row[$this->valueField];
+ }
+ }
+
+ // MUtil_Echo::track($results, $data);
+ return $results;
+ }
+}
Added: trunk/library/classes/MUtil/Model/Transform/JoinTransformer.php
===================================================================
--- trunk/library/classes/MUtil/Model/Transform/JoinTransformer.php (rev 0)
+++ trunk/library/classes/MUtil/Model/Transform/JoinTransformer.php 2013-01-15 18:02:16 UTC (rev 1101)
@@ -0,0 +1,143 @@
+<?php
+
+/**
+ * Copyright (c) 2012, 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.
+ *
+ *
+ * @package MUtil
+ * @subpackage Model
+ * @author Matijs de Jong <mj...@ma...>
+ * @copyright Copyright (c) 2012 Erasmus MC
+ * @license New BSD License
+ * @version $id: JoinTransformer.php 203 2012-01-01t 12:51:32Z matijs $
+ */
+
+/**
+ * Transform that can be used to join models to another model in non-relational
+ * ways.
+ *
+ * @package MUtil
+ * @subpackage Model
+ * @copyright Copyright (c) 2012 Erasmus MC
+ * @license New BSD License
+ * @since Class available since MUtil version 1.2
+ */
+class MUtil_Model_Transform_JoinTransformer implements MUtil_Model_ModelTransformerInterface
+{
+ /**
+ *
+ * @var array of join functions
+ */
+ protected $_joins = array();
+
+ /**
+ *
+ * @var array of MUtil_Model_ModelAbstract
+ */
+ protected $_subModels = array();
+
+ public function addModel(MUtil_Model_ModelAbstract $subModel, array $joinFields)
+ {
+ $name = $subModel->getName();
+ $this->_subModels[$name] = $subModel;
+ $this->_joins[$name] = $joinFields;
+
+ if (count($joinFields) > 1) {
+ throw new MUtil_Model_ModelException(__CLASS__ . " currently accepts single field joins only.");
+ }
+
+ return $this;
+ }
+
+ /**
+ * If the transformer add's fields, these should be returned here.
+ * Called in $model->AddTransformer(), so the transformer MUST
+ * know which fields to add by then (optionally using the model
+ * for that).
+ *
+ * @param MUtil_Model_ModelAbstract $model The parent model
+ * @return array Of filedname => set() values
+ */
+ public function getFieldInfo(MUtil_Model_ModelAbstract $model)
+ {
+ $data = array();
+ foreach ($this->_subModels as $sub) {
+ foreach ($sub->getItemNames() as $name) {
+ if (! $model->has($name)) {
+ $data[$name] = $sub->get($name);
+ }
+ }
+ }
+ return $data;
+ }
+
+ /**
+ * The transform function performs the actual transformation of the data and is called after
+ * the loading of the data in the source model.
+ *
+ * @param MUtil_Model_ModelAbstract $model The parent model
+ * @param array $data Nested array
+ * @return array Nested array containing (optionally) transformed data
+ */
+ public function transformLoad(MUtil_Model_ModelAbstract $model, array $data)
+ {
+ if (! $data) {
+ return $data;
+ }
+
+ foreach ($this->_subModels as $name => $sub) {
+ /* @var $sub MUtil_Model_ModelAbstract */
+
+ if (1 === count($this->_joins[$name])) {
+ $mkey = key($this->_joins[$name]);
+ $skey = reset($this->_joins[$name]);
+
+ $mfor = MUtil_Ra::column($mkey, $data);
+
+ // MUtil_Echo::track($mfor);
+
+ $sdata = $sub->load(array($skey => $mfor));
+ // MUtil_Echo::track($sdata);
+
+ $skeys = array_flip(MUtil_Ra::column($skey, $sdata));
+ $empty = array_fill_keys(array_keys(reset($sdata)), null);
+
+ foreach ($data as &$mrow) {
+ $mfind = $mrow[$mkey];
+
+ if (isset($skeys[$mfind])) {
+ $mrow += $sdata[$skeys[$mfind]];
+ } else {
+ $mrow += $empty;
+ }
+ }
+ }
+ }
+ // MUtil_Echo::track($data);
+
+ return $data;
+ }
+}
Modified: trunk/library/classes/MUtil/Model/Transform/RequiredRowsTransformer.php
===================================================================
--- trunk/library/classes/MUtil/Model/Transform/RequiredRowsTransformer.php 2013-01-14 18:21:45 UTC (rev 1100)
+++ trunk/library/classes/MUtil/Model/Transform/RequiredRowsTransformer.php 2013-01-15 18:02:16 UTC (rev 1101)
@@ -49,22 +49,33 @@
*/
class MUtil_Model_Transform_RequiredRowsTransformer extends MUtil_Model_ModelTransformerAbstract
{
+ /**
+ * Contains default values for all missing row values
+ *
+ * @var mixed Something that can be made into an array using MUtil_Ra::to()
+ */
protected $_defaultRow;
+
+ /**
+ * The number of key values to compare, if empty the number of fields in the first required row
+ *
+ * @var int
+ */
protected $_keyItemCount;
+
+ /**
+ *
+ * @var mixed Something that can be made into an array using MUtil_Ra::to()
+ */
protected $_requiredRows;
- public function __construct($requiredRows, $sourceModel_args = null)
- {
- $args = func_get_args();
- $paramTypes = array(
- 'sourceModel' => 'MUtil_Model_ModelAbstract',
- 'requiredRows' => 'is_ra_array',
- 'keyItemCount' => 'is_int',
- );
-
- parent::__construct($args, $paramTypes);
- }
-
+ /**
+ *
+ * @param array $required
+ * @param array $row
+ * @param int $count
+ * @return boolean True if the rows refer to the same row
+ */
protected function _compareRows($required, $row, $count)
{
if ($row) {
@@ -87,10 +98,16 @@
}
}
- public function getDefaultRow()
+ /**
+ * Returns the required rows set or calculates the rows using the $model and the required rows info
+ *
+ * @param MUtil_Model_ModelAbstract $model Optional model for calculation
+ * @return array
+ * @throws MUtil_Model_ModelException
+ */
+ public function getDefaultRow(MUtil_Model_ModelAbstract $model = null)
{
if (! $this->_defaultRow) {
- $model = $this->getSourceModel();
$requireds = $this->getRequiredRows();
$required = MUtil_Ra::to(reset($requireds));
@@ -98,7 +115,7 @@
$this->setKeyItemCount(count($required));
}
- if ($model && $required) {
+ if ($required && ($model instanceof MUtil_Model_ModelAbstract)) {
$defaults = array();
foreach ($model->getItemNames() as $name) {
if (! array_key_exists($name, $required)) {
@@ -116,6 +133,11 @@
return $this->_defaultRow;
}
+ /**
+ * The number of key values to compare
+ *
+ * @return int
+ */
public function getKeyItemCount()
{
if (! $this->_keyItemCount) {
@@ -126,6 +148,11 @@
return $this->_keyItemCount;
}
+ /**
+ * Array of required rows
+ *
+ * @return array
+ */
public function getRequiredRows()
{
if (! is_array($this->_requiredRows)) {
@@ -135,6 +162,13 @@
return $this->_requiredRows;
}
+ /**
+ * Contains default values for all missing row values
+ *
+ * @param mixed $defaultRow Something that can be made into an array using MUtil_Ra::to()
+ * @return \MUtil_Model_Transform_RequiredRowsTransformer
+ * @throws MUtil_Model_ModelException
+ */
public function setDefaultRow($defaultRow)
{
if (MUtil_Ra::is($defaultRow)) {
@@ -145,12 +179,25 @@
throw new MUtil_Model_ModelException('Invalid parameter type for ' . __FUNCTION__ . ': $rows cannot be converted to an array.');
}
+ /**
+ * The number of key values to compare
+ *
+ * @param int $count
+ * @return \MUtil_Model_Transform_RequiredRowsTransformer
+ */
public function setKeyItemCount($count)
{
$this->_keyItemCount = $count;
return $this;
}
+ /**
+ * The keys for the required rows
+ *
+ * @param mixed $rows Something that can be made into an array using MUtil_Ra::to()
+ * @return \MUtil_Model_Transform_RequiredRowsTransformer
+ * @throws MUtil_Model_ModelException
+ */
public function setRequiredRows($rows)
{
if (MUtil_Ra::is($rows)) {
@@ -161,9 +208,17 @@
throw new MUtil_Model_ModelException('Invalid parameter type for ' . __FUNCTION__ . ': $rows cannot be converted to an array.');
}
- public function transform($data, $filter = true, $sort = true)
+ /**
+ * The transform function performs the actual transformation of the data and is called after
+ * the loading of the data in the source model.
+ *
+ * @param MUtil_Model_ModelAbstract $model The parent model
+ * @param array $data Nested array
+ * @return array Nested array containing (optionally) transformed data
+ */
+ public function transformLoad(MUtil_Model_ModelAbstract $model...
[truncated message content] |