/**
  * Returns all relatable models for this app
  * 
  * @return array
  */
 public function getRelatableModels()
 {
     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' This method is deprecated and will be removed. Please use Tinebase_ModelFactory with Tinebase_ModelConfiguration!');
     }
     if (property_exists($this, '_relatableModels') && is_array($this->_relatableModels)) {
         return Tinebase_Relations::getConstraintsConfigs($this->_relatableModels);
     } else {
         return array();
     }
 }
 /**
  * handles relations on update multiple
  * 
  * @param string $key
  * @param string $value
  * @throws Tinebase_Exception_Record_DefinitionFailure
  */
 protected function _handleRelationsOnUpdateMultiple($key, $value)
 {
     $getRelations = true;
     preg_match('/%(.+)-((.+)_Model_(.+))/', $key, $a);
     if (count($a) < 4) {
         throw new Tinebase_Exception_Record_DefinitionFailure('The relation to delete/set is not configured properly!');
     }
     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Handle relations for ' . $this->_modelName);
     }
     $relConfig = Tinebase_Relations::getConstraintsConfigs(array($this->_modelName, $a[2]));
     $constraintsConfig = NULL;
     if ($relConfig) {
         foreach ($relConfig as $config) {
             if ($config['relatedApp'] == $a[3] && $config['relatedModel'] == $a[4] && isset($config['config']) && is_array($config['config'])) {
                 foreach ($config['config'] as $constraint) {
                     if ($constraint['type'] == $a[1]) {
                         $constraintsConfig = $constraint;
                         break 2;
                     }
                 }
             }
         }
     }
     // update multiple is not possible without having a constraints config
     if (!$constraintsConfig) {
         throw new Tinebase_Exception_Record_DefinitionFailure('No relation definition could be found for this model!');
     }
     $rel = array('own_model' => $this->_modelName, 'own_backend' => 'Sql', 'own_degree' => isset($constraintsConfig['sibling']) ? $constraintsConfig['sibling'] : 'sibling', 'related_model' => $a[2], 'related_backend' => 'Sql', 'type' => isset($constraintsConfig['type']) ? $constraintsConfig['type'] : ' ', 'remark' => isset($constraintsConfig['defaultRemark']) ? $constraintsConfig['defaultRemark'] : ' ');
     if (!$this->_removeRelations) {
         $this->_removeRelations = array($rel);
     } else {
         $this->_removeRelations[] = $rel;
     }
     if (!empty($value)) {
         // delete relations in iterator
         $rel['related_id'] = $value;
         if (!$this->_newRelations) {
             $this->_newRelations = array($rel);
         } else {
             $this->_newRelations[] = $rel;
         }
     }
     if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) {
         Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' New relations: ' . print_r($this->_newRelations, true) . ' Remove relations: ' . print_r($this->_removeRelations, true));
     }
 }
 /**
  * tests if constraints config is called properly
  * 
  * @see #8840: relations config - constraints from the other side
  *      - validate in backend
  *      
  *      https://forge.tine20.org/mantisbt/view.php?id=8840
  */
 public function testGetConstraintsConfigs()
 {
     $result = Tinebase_Relations::getConstraintsConfigs('Sales_Model_Contract');
     $this->assertEquals(12, count($result));
     foreach ($result as $item) {
         if ($item['ownRecordClassName'] == 'Sales_Model_Contract' && $item['relatedRecordClassName'] == 'Timetracker_Model_Timeaccount') {
             $this->assertEquals('Contract', $item['ownModel']);
             $this->assertEquals('Timeaccount', $item['relatedModel']);
             $this->assertEquals('', $item['defaultType']);
             $this->assertEquals('TIME_ACCOUNT', $item['config'][0]['type']);
             $this->assertSame(0, $item['config'][0]['max']);
         } elseif ($item['ownRecordClassName'] == 'Timetracker_Model_Timeaccount' && $item['relatedRecordClassName'] == 'Sales_Model_Contract') {
             $this->assertEquals('Contract', $item['relatedModel']);
             $this->assertEquals('Timeaccount', $item['ownModel']);
             $this->assertEquals('TIME_ACCOUNT', $item['config'][0]['type']);
             $this->assertEquals(TRUE, $item['reverted']);
             $this->assertSame(1, $item['config'][0]['max']);
         }
     }
 }
 /**
  * handles relations on update multiple
  *
  * Syntax 1 (old): key: '%<type>-<related_model>', value: <related_id>
  * Syntax 2      : key: '%<add|remove|replace>', value: <relation json>
  * 
  * @param string $key
  * @param string $value
  * @throws Tinebase_Exception_Record_DefinitionFailure
  */
 protected function _handleRelationsOnUpdateMultiple($key, $value)
 {
     if (preg_match('/%(add|remove|replace)/', $key, $matches)) {
         $action = $matches[1];
         $rel = json_decode($value, true);
     } else {
         if (preg_match('/%(.+)-((.+)_Model_(.+))/', $key, $a)) {
             $action = $value ? 'replace' : 'remove';
             $rel = array('related_model' => $a[2], 'type' => $a[1], 'related_id' => $value);
         } else {
             throw new Tinebase_Exception_Record_DefinitionFailure('The relation to delete/set is not configured properly!');
         }
     }
     // find constraint config
     $constraintsConfig = array();
     $relConfig = Tinebase_Relations::getConstraintsConfigs(array($this->_modelName, $rel['related_model']));
     if ($relConfig) {
         foreach ($relConfig as $config) {
             if ($rel['related_model'] == "{$config['relatedApp']}_Model_{$config['relatedModel']}" && isset($config['config']) && is_array($config['config'])) {
                 foreach ($config['config'] as $constraint) {
                     if (isset($rel['type']) && isset($constraint['type']) && $constraint['type'] == $rel['type']) {
                         $constraintsConfig = $constraint;
                         break 2;
                     }
                 }
             }
         }
     }
     // apply defaults
     $rel = array_merge($rel, array('own_model' => $this->_modelName, 'own_backend' => 'Sql', 'related_backend' => 'Sql', 'related_degree' => isset($rel['related_degree']) ? $rel['related_degree'] : (isset($constraintsConfig['sibling']) ? isset($constraintsConfig['sibling']) : 'sibling'), 'type' => isset($rel['type']) ? $rel['type'] : (isset($constraintsConfig['type']) ? isset($constraintsConfig['type']) : ' '), 'remark' => isset($rel['remark']) ? $rel['remark'] : (isset($constraintsConfig['defaultRemark']) ? isset($constraintsConfig['defaultRemark']) : ' ')));
     if (in_array($action, array('remove', 'replace'))) {
         $this->_removeRelations ?: array();
         $this->_removeRelations[] = $rel;
     }
     if (in_array($action, array('add', 'replace'))) {
         $this->_newRelations ?: array();
         $this->_newRelations[] = $rel;
     }
     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' New relations: ' . print_r($this->_newRelations, true) . ' Remove relations: ' . print_r($this->_removeRelations, true));
     }
 }