ModelConfig2 - create relation filter for virtual fields type relation
authorPaul Mehrer <p.mehrer@metaways.de>
Wed, 19 Jul 2017 10:05:52 +0000 (12:05 +0200)
committerPaul Mehrer <p.mehrer@metaways.de>
Thu, 20 Jul 2017 09:08:49 +0000 (11:08 +0200)
Change-Id: I08b72576d379267eb7a0caba7bb13c8bcda2ba19
Reviewed-on: http://gerrit.tine20.com/customers/5247
Reviewed-by: Paul Mehrer <p.mehrer@metaways.de>
Tested-by: Paul Mehrer <p.mehrer@metaways.de>
tine20/Tinebase/Acl/Roles.php
tine20/Tinebase/Model/Filter/ForeignRecord.php
tine20/Tinebase/Model/Filter/Relation.php
tine20/Tinebase/ModelConfiguration.php

index adc9bde..a4119dd 100644 (file)
@@ -371,6 +371,30 @@ class Tinebase_Acl_Roles extends Tinebase_Controller_Record_Abstract
     }
 
     /**
+     * get list of role members account ids, resolves groups to account ids
+     *
+     * @param   string $_roleId
+     * @return  array with account ids
+     * @throws  Tinebase_Exception_AccessDenied
+     */
+    public function getRoleMembersAccounts($_roleId)
+    {
+        $accountIds = array();
+        foreach ($this->getRoleMembers($_roleId) as $role) {
+                   switch($role['account_type']) {
+                case Tinebase_Acl_Rights::ACCOUNT_TYPE_USER:
+                    $accountIds[] = $role['account_id'];
+                    break;
+                case Tinebase_Acl_Rights::ACCOUNT_TYPE_GROUP:
+                    $accountIds = array_merge($accountIds,
+                        Tinebase_Group::getInstance()->getGroupMembers($role['account_id']));
+                    break;
+            }
+        }
+        return $accountIds;
+    }
+
+    /**
      * get list of role memberships
      *
      * @param int|Tinebase_Model_User $accountId
index 896d808..47fc1c5 100644 (file)
@@ -5,7 +5,7 @@
  * @package     Tinebase
  * @subpackage  Filter
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
- * @copyright   Copyright (c) 2011 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2011-2017 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Philipp Schüle <p.schuele@metaways.de>
  */
 
@@ -48,6 +48,11 @@ abstract class Tinebase_Model_Filter_ForeignRecord extends Tinebase_Model_Filter
      * @var array
      */
     protected $_prefixedFields = array();
+
+    /**
+     * if the value was null
+     */
+    protected $_valueIsNull = false;
         
     /**
      * creates corresponding filtergroup
@@ -56,6 +61,7 @@ abstract class Tinebase_Model_Filter_ForeignRecord extends Tinebase_Model_Filter
      */
     public function setValue($_value) {
         $this->_foreignIds = NULL;
+        $this->_valueIsNull = null === $_value;
         $this->_value = (array)$_value;
         $this->_removePrefixes();
         
index b89c365..d97ef7c 100644 (file)
@@ -54,6 +54,9 @@ class Tinebase_Model_Filter_Relation extends Tinebase_Model_Filter_ForeignRecord
      */
     protected function _setFilterGroup()
     {
+        if ($this->_valueIsNull) {
+            return;
+        }
         $filters = $this->_getRelationFilters();
         $this->_filterGroup = new $this->_options['filtergroup']($filters, $this->_operator);
     }
@@ -65,11 +68,11 @@ class Tinebase_Model_Filter_Relation extends Tinebase_Model_Filter_ForeignRecord
      */
     protected function _setOptions(array $_options)
     {
-        if (! (isset($_options['related_model']) || array_key_exists('related_model', $_options))) {
+        if (! isset($_options['related_model'])) {
             throw new Tinebase_Exception_UnexpectedValue('related model is needed in options');
         }
 
-        if (! (isset($_options['filtergroup']) || array_key_exists('filtergroup', $_options))) {
+        if (! isset($_options['filtergroup'])) {
             $_options['filtergroup'] = $_options['related_model'] . 'Filter';
         }
         
@@ -91,17 +94,27 @@ class Tinebase_Model_Filter_Relation extends Tinebase_Model_Filter_ForeignRecord
         }
         if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' 
             . 'Adding Relation filter: ' . $ownModel . ' <-> ' . $this->_options['related_model']);
-        
-        $this->_resolveForeignIds();
-        $ownIds = $this->_getOwnIds($ownModel);
-        
+
         $idField = (isset($this->_options['idProperty']) || array_key_exists('idProperty', $this->_options)) ? $this->_options['idProperty'] : 'id';
         $db = $_backend->getAdapter();
         $qField = $db->quoteIdentifier($_backend->getTableName() . '.' . $idField);
-        if (empty($ownIds)) {
-            $_select->where('1=0');
+
+        if (!$this->_valueIsNull) {
+            $this->_resolveForeignIds();
+            $ownIds = $this->_getOwnIds($ownModel);
+
+            if (empty($ownIds)) {
+                $_select->where('1=0');
+            } else {
+                $_select->where($db->quoteInto("$qField IN (?)", $ownIds));
+            }
         } else {
-            $_select->where($db->quoteInto("$qField IN (?)", $ownIds));
+            $ownIds = $this->_getOwnIds($ownModel);
+            if (empty($ownIds)) {
+                $_select->where('1=1');
+            } else {
+                $_select->where($db->quoteInto("$qField NOT IN (?)", $ownIds));
+            }
         }
     }
     
@@ -128,11 +141,18 @@ class Tinebase_Model_Filter_Relation extends Tinebase_Model_Filter_ForeignRecord
      */
     protected function _getOwnIds($_modelName)
     {
-        $relationFilter = new Tinebase_Model_RelationFilter(array(
+        $filter = array(
             array('field' => 'own_model',     'operator' => 'equals', 'value' => $_modelName),
-            array('field' => 'related_model', 'operator' => 'equals', 'value' => $this->_options['related_model']),
-            array('field' => 'related_id',    'operator' => 'in'    , 'value' => $this->_foreignIds)
-        ));
+            array('field' => 'related_model', 'operator' => 'equals', 'value' => $this->_options['related_model'])
+        );
+        if (null !== $this->_foreignIds) {
+            $filter[] = array('field' => 'related_id', 'operator' => 'in'    , 'value' => $this->_foreignIds);
+        }
+        if (isset($this->_options['type'])) {
+            $filter[] = array('field' => 'type',       'operator' => 'equals', 'value' => $this->_options['type']);
+        }
+
+        $relationFilter = new Tinebase_Model_RelationFilter($filter);
         
         if ($this->_relationTypeFilter) {
             $typeValue = $this->_relationTypeFilter['value'];
index f13d635..9388b96 100644 (file)
@@ -865,7 +865,7 @@ class Tinebase_ModelConfiguration {
         self::$_availableApplications[$this->_appName] = TRUE;
         
         $this->_modelName   = $modelClassConfiguration['modelName'];
-        $this->_idProperty  = $this->_identifier = (isset($modelClassConfiguration['idProperty']) || array_key_exists('idProperty', $modelClassConfiguration)) ? $modelClassConfiguration['idProperty'] : 'id';
+        $this->_idProperty  = $this->_identifier = isset($modelClassConfiguration['idProperty']) ? $modelClassConfiguration['idProperty'] : 'id';
 
         $this->_table = isset($modelClassConfiguration['table']) ? $modelClassConfiguration['table'] : $this->_table;
         $this->_version = isset($modelClassConfiguration['version']) ? $modelClassConfiguration['version'] : $this->_version;
@@ -995,18 +995,18 @@ class Tinebase_ModelConfiguration {
 
             if ($fieldDef['type'] == 'keyfield') {
                 $fieldDef['length'] = 40;
-            } else if ($fieldDef['type'] == 'virtual') {
-                $fieldDef = isset($fieldDef['config']) ? $fieldDef['config'] : array();
-                $fieldDef['key'] = $fieldKey;
-                $fieldDef['sortable'] = FALSE;
-                if ((isset($fieldDef['default']))) {
+            } elseif ($fieldDef['type'] == 'virtual') {
+                $virtualField = isset($fieldDef['config']) ? $fieldDef['config'] : array();
+                $virtualField['key'] = $fieldKey;
+                $virtualField['sortable'] = FALSE;
+                if ((isset($virtualField['default']))) {
                     // @todo: better handling of virtualfields
-                    $this->_defaultData[$fieldKey] = $fieldDef['default'];
+                    $this->_defaultData[$fieldKey] = $virtualField['default'];
                 }
-                $this->_virtualFields[] = $fieldDef;
-                continue;
+                $this->_virtualFields[] = $virtualField;
+                $fieldDef['modlogOmit'] = true;
 
-            } else if ($fieldDef['type'] == 'numberableStr' || $fieldDef['type'] == 'numberableInt') {
+            } elseif ($fieldDef['type'] == 'numberableStr' || $fieldDef['type'] == 'numberableInt') {
                 $this->_autoincrementFields[] = $fieldDef;
             }
 
@@ -1041,12 +1041,12 @@ class Tinebase_ModelConfiguration {
             
             $this->_setFieldFilterModel($fieldDef, $fieldKey);
 
-            if ((isset($fieldDef['queryFilter']) || array_key_exists('queryFilter', $fieldDef))) {
+            if (isset($fieldDef['queryFilter'])) {
                 $queryFilters[] = $fieldKey;
             }
 
             // set validators
-            if ((isset($fieldDef['validators']) || array_key_exists('validators', $fieldDef))) {
+            if (isset($fieldDef['validators'])) {
                 // use _validators from definition
                 $this->_validators[$fieldKey] = $fieldDef['validators'];
             } else if ((isset($this->_validatorMapping[$fieldDef['type']]) || array_key_exists($fieldDef['type'], $this->_validatorMapping))) {
@@ -1057,7 +1057,7 @@ class Tinebase_ModelConfiguration {
             }
             
             // set input filters, append defined if any or use defaults from _inputFilterDefaultMapping 
-            if ((isset($fieldDef['inputFilters']) || array_key_exists('inputFilters', $fieldDef))) {
+            if (isset($fieldDef['inputFilters'])) {
                 foreach ($fieldDef['inputFilters'] as $if => $val) {
                     if (is_array($val)) {
                         $reflect  = new ReflectionClass($if);
@@ -1066,14 +1066,14 @@ class Tinebase_ModelConfiguration {
                         $this->_filters[$fieldKey][] = $if ? new $if($val) : new $val();
                     }
                 }
-            } else if ((isset($this->_inputFilterDefaultMapping[$fieldDef['type']]) || array_key_exists($fieldDef['type'], $this->_inputFilterDefaultMapping))) {
+            } elseif (isset($this->_inputFilterDefaultMapping[$fieldDef['type']])) {
                 foreach ($this->_inputFilterDefaultMapping[$fieldDef['type']] as $if => $val) {
                     $this->_filters[$fieldKey][] = $if ? new $if($val) : new $val();
                 }
             }
             
             // add field to modlog omit, if configured and modlog is used
-            if ($this->_modlogActive && (isset($fieldDef['modlogOmit']) || array_key_exists('modlogOmit', $fieldDef))) {
+            if ($this->_modlogActive && isset($fieldDef['modlogOmit'])) {
                 $this->_modlogOmitFields[] = $fieldKey;
             }
 
@@ -1106,20 +1106,43 @@ class Tinebase_ModelConfiguration {
      */
     protected function _setFieldFilterModel($fieldDef, $fieldKey)
     {
-        if ((isset($fieldDef['filterDefinition']) || array_key_exists('filterDefinition', $fieldDef))) {
+        if (isset($fieldDef['filterDefinition'])) {
             // use filter from definition
             $key = isset($fieldDef['filterDefinition']['key']) ? $fieldDef['filterDefinition']['key'] : $fieldKey;
+            if (isset($this->_filterModel[$key])) {
+                return;
+            }
             $this->_filterModel[$key] = $fieldDef['filterDefinition'];
-        } else if ((isset($this->_filterModelMapping[$fieldDef['type']]) || array_key_exists($fieldDef['type'], $this->_filterModelMapping))) {
-            // if no filterDefinition is given, try to use the default one
-            $this->_filterModel[$fieldKey] = array('filter' => $this->_filterModelMapping[$fieldDef['type']]);
-            if ((isset($fieldDef['config']) || array_key_exists('config', $fieldDef))) {
-                $this->_filterModel[$fieldKey]['options'] = $fieldDef['config'];
-
-                // set id filter controller
-                if ($fieldDef['type'] == 'record') {
-                    $this->_filterModel[$fieldKey]['options']['filtergroup'] = $fieldDef['config']['appName'] . '_Model_' . $fieldDef['config']['modelName'] . 'Filter';
-                    $this->_filterModel[$fieldKey]['options']['controller']  = $fieldDef['config']['appName'] . '_Controller_' . $fieldDef['config']['modelName'];
+        } else {
+            if (isset($this->_filterModel[$fieldKey])) {
+                return;
+            }
+            $type = $fieldDef['type'];
+            $config = isset($fieldDef['config']) ? $fieldDef['config'] : null;
+            if ('virtual' === $type && isset($fieldDef['config']) && isset($fieldDef['config']['type']) &&
+                    'relation' === $fieldDef['config']['type']) {
+                $type = 'relation';
+                if (isset($config['config'])) {
+                    $config = $config['config'];
+                }
+                if (isset($config['appName']) && isset($config['modelName'])) {
+                    $config['related_model'] = $config['appName'] . '_Model_' . $config['modelName'];
+                }
+                if (!isset($config['own_model'])) {
+                    $config['own_model'] = $this->_getPhpClassName();
+                }
+            }
+            if (isset($this->_filterModelMapping[$type])) {
+                // if no filterDefinition is given, try to use the default one
+                $this->_filterModel[$fieldKey] = array('filter' => $this->_filterModelMapping[$type]);
+                if (null !== $config) {
+                    $this->_filterModel[$fieldKey]['options'] = $config;
+
+                    // set id filter controller
+                    if ($type === 'record') {
+                        $this->_filterModel[$fieldKey]['options']['filtergroup'] = $config['appName'] . '_Model_' . $config['modelName'] . 'Filter';
+                        $this->_filterModel[$fieldKey]['options']['controller']  = $config['appName'] . '_Controller_' . $config['modelName'];
+                    }
                 }
             }
         }
@@ -1226,7 +1249,7 @@ class Tinebase_ModelConfiguration {
         return $this->_version;
     }
 
-    public function getApplName()
+    public function getAppName()
     {
         return $this->_appName;
     }