Overview

Packages

  • application
    • commands
    • components
      • actions
      • filters
      • leftWidget
      • permissions
      • sortableWidget
      • util
      • webupdater
      • x2flow
        • actions
        • triggers
      • X2GridView
      • X2Settings
    • controllers
    • models
      • embedded
    • modules
      • accounts
        • controllers
        • models
      • actions
        • controllers
        • models
      • calendar
        • controllers
        • models
      • charts
        • models
      • contacts
        • controllers
        • models
      • docs
        • components
        • controllers
        • models
      • groups
        • controllers
        • models
      • marketing
        • components
        • controllers
        • models
      • media
        • controllers
        • models
      • mobile
        • components
      • opportunities
        • controllers
        • models
      • products
        • controllers
        • models
      • quotes
        • controllers
        • models
      • services
        • controllers
        • models
      • template
        • models
      • users
        • controllers
        • models
      • workflow
        • controllers
        • models
      • x2Leads
        • controllers
        • models
  • None
  • system
    • base
    • caching
    • console
    • db
      • ar
      • schema
    • validators
    • web
      • actions
      • auth
      • helpers
      • widgets
        • captcha
        • pagers
  • zii
    • widgets
      • grid

Classes

  • AccountsGridViewProfileWidget
  • ActionMenu
  • ActionsGridViewProfileWidget
  • ActionsQuickCreateRelationshipBehavior
  • ActiveDateRangeInput
  • ApplicationConfigBehavior
  • Attachments
  • ChatBox
  • CommonControllerBehavior
  • ContactMapInlineTags
  • ContactsGridViewProfileWidget
  • CronForm
  • CSaveRelationsBehavior
  • DateRangeInputsWidget
  • DocsGridViewProfileWidget
  • DocViewer
  • DocViewerProfileWidget
  • EButtonColumnWithClearFilters
  • EmailDeliveryBehavior
  • EmailProgressControl
  • EncryptedFieldsBehavior
  • EventsChartProfileWidget
  • FileUploader
  • FontPickerInput
  • Formatter
  • FormView
  • GridViewWidget
  • History
  • IframeWidget
  • ImportExportBehavior
  • InlineActionForm
  • InlineEmailAction
  • InlineEmailForm
  • InlineEmailModelBehavior
  • InlineQuotes
  • JSONEmbeddedModelFieldsBehavior
  • JSONFieldsDefaultValuesBehavior
  • LeadRoutingBehavior
  • LeftWidget
  • LoginThemeHelper
  • LoginThemeHelperBase
  • MarketingGridViewProfileWidget
  • MediaBox
  • MessageBox
  • MobileFormatter
  • MobileFormLayoutRenderer
  • MobileLayoutRenderer
  • MobileLoginThemeHelper
  • MobileViewLayoutRenderer
  • ModelFileUploader
  • NewWebLeadsGridViewProfileWidget
  • NormalizedJSONFieldsBehavior
  • NoteBox
  • OnlineUsers
  • OpportunitiesGridViewProfileWidget
  • Panel
  • ProfileDashboardManager
  • ProfileGridViewWidget
  • ProfileLayoutEditor
  • ProfilesGridViewProfileWidget
  • Publisher
  • PublisherActionTab
  • PublisherCalendarEventTab
  • PublisherCallTab
  • PublisherCommentTab
  • PublisherEventTab
  • PublisherSmallCalendarEventTab
  • PublisherTab
  • PublisherTimeTab
  • QuickContact
  • QuickCreateRelationshipBehavior
  • QuotesGridViewProfileWidget
  • RecordAliasesWidget
  • RecordViewLayoutManager
  • RecordViewWidgetManager
  • RememberPagination
  • Reminders
  • ResponseBehavior
  • ResponsiveHtml
  • SearchIndexBehavior
  • ServicesGridViewProfileWidget
  • SmallCalendar
  • SmartActiveDataProvider
  • SmartDataProviderBehavior
  • SmartSort
  • SocialForm
  • SortableWidgetManager
  • SortableWidgets
  • TagBehavior
  • TagCloud
  • TemplatesGridViewProfileWidget
  • TimeZone
  • TopContacts
  • TopSites
  • TransformedFieldStorageBehavior
  • TranslationLogger
  • TwitterFeed
  • TwoColumnSortableWidgetManager
  • UpdaterBehavior
  • UpdatesForm
  • UserIdentity
  • UsersChartProfileWidget
  • WorkflowBehavior
  • X2ActiveGridView
  • X2ActiveGridViewForSortableWidgets
  • X2AssetManager
  • X2AuthManager
  • X2ChangeLogBehavior
  • X2ClientScript
  • X2Color
  • X2DateUtil
  • X2FixtureManager
  • X2FlowFormatter
  • X2GridView
  • X2GridViewBase
  • X2GridViewForSortableWidgets
  • X2GridViewSortableWidgetsBehavior
  • X2LeadsGridViewProfileWidget
  • X2LinkableBehavior
  • X2ListView
  • X2PillBox
  • X2ProgressBar
  • X2SmartSearchModelBehavior
  • X2TimestampBehavior
  • X2TranslationBehavior
  • X2UrlRule
  • X2WebModule
  • X2Widget
  • X2WidgetList
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: 
  3: /**
  4:  * CSaveRelationsBehavior class.
  5:  * 
  6:  * The CSaveRelationBehavior enables ActiveRecord model to save HasMany and ManyMany 
  7:  * relational active records along with the main model
  8:  * 
  9:  * Requirements:
 10:  * Yii Framework 1.0.4 or later
 11:  * 
 12:  * Installation:
 13:  * Extract the release file under `protected/components`
 14:  * 
 15:  * Usage:
 16:  * - Add the following code to the models you wish to add this behavior to:
 17:  * public function behaviors(){
 18:  *      return array('CSaveRelationsBehavior' => array('class' => 'application.components.CSaveRelationsBehavior'));
 19:  * }
 20:  * In your controler, to save the relations data, simply call
 21:  * $model->setRelationRecords('relationName',$data);
 22:  * $model->save();
 23:  * - For ManyMany relations, $data is either an array of foreign key values (ie. array(2,5,43)) or
 24:  * an array of associative arrays giving the composite foreign keys values of the related model
 25:  * (ie. array(array('pk1'=>2,'pk2'=>'fr'),array('pk1'=>5,'pk2'=>'en'))
 26:  * You will typically get this data from some checkboxes values listing the ids of the related model
 27:  * - For HasMany relations, $data should be set as an array of associative arrays giving the attributes values
 28:  * of the related model (ie. array(array('id'=>123, 'name'=>'someValue', 'visible'=>true),
 29:  * array('id'=>456, 'name'=>'someOtherValue', 'visible'=>false));
 30:  * You can get this data by using the tabular input technique within the form of the main model 
 31:  * (http://www.yiiframework.com/doc/guide/form.table)
 32:  * 
 33:  * In both cases, the foreign keys related to the main model will automatically be populated
 34:  * with its primary key(s) value(s).
 35:  * Most of the time, you will call the setRelationRecords that way:
 36:  * $model->setRelationRecords('relationName',is_array(@$_POST['ModelName']) ? $_POST['ModelName'] : array());
 37:  * 
 38:  * By default, the behavior will handle the save operation in a transactional way
 39:  * so that if anything goes wrong during the save of some related data
 40:  * your relational integrity will not be affected.
 41:  * If you prefer to handle this yourself, you can set the 'transactional' property of the behavior to false.
 42:  * Also, if any error occurs during the save process, the hasError property will be set to true.
 43:  * 
 44:  * Additional features:
 45:  * - $model->addSaveRelation('relationName'[,'customErrorMessage'])
 46:  * You can use this method to force the save of some relation. 
 47:  * You can also set the error message of the relation by using the second parameter (see setSaveRelationMessage below)
 48:  * - $model->removeSaveRelation('relationName')
 49:  * Simply do the oposite
 50:  * - $model->setSaveRelationMessage('relationName','customErrorMessage')
 51:  * Set the message to be shown in the error summary of the main model
 52:  *
 53:  * @author Alban Jubert <alban.jubert@trinidev.fr>
 54:  * @link http://www.trinidev.fr/
 55:  * @license CSaveRelationsBehavior
 56:  * @package application.components 
 57:  * @version 1.0.3
 58:  */
 59: 
 60: class CSaveRelationsBehavior extends CActiveRecordBehavior {
 61:     
 62:     public $relations = array();
 63:     public $transactional = true;
 64:     public $hasError = false;
 65:     public $deleteRelatedRecords = true;
 66:     private $transaction;
 67:     
 68:     private function initSaveRelation($relation){
 69:         $model = $this->owner;
 70:         if(!array_key_exists($relation,$model->relations())) 
 71:             throw new CDbException('CSaveRelatedBehavior could not find the "'.$relation.'" relation in the model.');
 72:         if(!array_key_exists($relation,$this->relations)) {
 73:             Yii::trace("Init {$relation} relation",'application.components.CSaveRelatedBehavior');
 74:             $this->relations[$relation]=array();
 75:         }
 76:     }
 77:     
 78:     public function setRelationRecords($relation,$data=null,$merge=false) {
 79:         // TODO - Make fewer SQL requests to validate and load related models data
 80:         $this->addSaveRelation($relation);
 81:         $model = $this->owner;
 82:         $activeRelation = $model->getActiveRelation($relation);
 83:         if($activeRelation instanceOf CHasManyRelation || $activeRelation instanceOf CManyManyRelation) {
 84:             if(!$merge) $model->{$relation} = array();
 85:             $relationClassName = $activeRelation->className;
 86:             $relationForeignKey = $activeRelation->foreignKey;
 87:             $criteria = array();
 88:             if($activeRelation instanceOf CManyManyRelation) {
 89:                 $schema = $model->getCommandBuilder()->getSchema();
 90:                 preg_match('/^\s*(.*?)\((.*)\)\s*$/',$relationForeignKey,$matches);
 91:                 $joinTable=$schema->getTable($matches[1]);
 92:                 $fks=preg_split('/[\s,]+/',$matches[2],-1,PREG_SPLIT_NO_EMPTY);
 93:                 $relModel = new $relationClassName;
 94:                 $pks = array();
 95:                 $fkDefined=true;
 96:                 foreach($fks as $i=>$fk) {
 97:                     if(isset($joinTable->foreignKeys[$fk])) {
 98:                         list($tableName,$pk)=$joinTable->foreignKeys[$fk];
 99:                         if($schema->compareTableNames($relModel->tableSchema->rawName,$tableName)) {
100:                             $pks[] = $pk;
101:                         }
102:                     }
103:                     else {
104:                         $fkDefined=false;
105:                         break;
106:                     }
107:                 }
108:                 if(!$fkDefined) {
109:                     $pks = array();
110:                     foreach($fks as $i=>$fk)
111:                     {
112:                         if($i<count($model->tableSchema->primaryKey))
113:                         {
114:                             $pks[] = is_array($model->tableSchema->primaryKey) ? $model->tableSchema->primaryKey[$i] : $model->tableSchema->primaryKey;
115:                         }
116:                     }
117:                 }
118:                 if(!is_null($data)) {
119:                     foreach($data as $key=>$value) {
120:                         $relobj = null;
121:                         $relModel = new $relationClassName;
122:                         if(is_array($value)) {
123:                             foreach($pks as $pk) {
124:                                 $criteria[$pk] = $value[$pk];
125:                             }
126:                         }
127:                         else {
128:                             $criteria[$pks[0]] = $value;
129:                         }
130:                         $relobj = $relModel->findByAttributes($criteria);
131:                         if(!($relobj instanceof $relationClassName)) $relobj = new $relationClassName;
132:                         $relobj->attributes = $value;
133:                         $model->addRelatedRecord($relation,$relobj,$key);
134:                     }
135:                 }
136:             }
137:             else {
138:                 $fks=preg_split('/[\s,]+/',$relationForeignKey,-1,PREG_SPLIT_NO_EMPTY);
139:                 if(!is_null($data)) {
140:                     foreach($data as $key=>$value) {
141:                         $relobj = null;
142:                         if(!$model->isNewRecord) {
143:                             $criteria = array();
144:                             $relModel = new $relationClassName;
145:                             $relationPrimaryKeys = $relModel->tableSchema->primaryKey;
146:                             if(is_array($value)) {
147:                                 if(is_array($relationPrimaryKeys)) {
148:                                     foreach($relationPrimaryKeys as $relationPrimaryKey){
149:                                         if(!in_array($relationPrimaryKey,$fks)) {
150:                                             if(isset($value[$relationPrimaryKey])) $criteria[$relationPrimaryKey] = $value[$relationPrimaryKey];
151:                                         }
152:                                         else {
153:                                             $criteria[$relationPrimaryKey] = $model->primaryKey;
154:                                         }
155:                                     }
156:                                 }
157:                                 else{
158:                                     if(!in_array($relationPrimaryKeys,$fks)) {
159:                                         if(isset($value[$relationPrimaryKeys])) $criteria[$relationPrimaryKeys] = $value[$relationPrimaryKeys];
160:                                     }
161:                                     else {
162:                                         $criteria[$relationPrimaryKeys] = $model->primaryKey;
163:                                     }
164:                                 }
165:                             }
166:                             else {
167:                                 $criteria = array($relationPrimaryKeys=>$value);
168:                             }
169:                             if(count($criteria)) $relobj = $relModel->findByAttributes($criteria);
170:                         }
171:                         if(!($relobj instanceof $relationClassName)) $relobj = new $relationClassName;
172:                         foreach($value as $prop=>$val) $relobj->{$prop} = $val;
173:                         $model->addRelatedRecord($relation,$relobj,$key);
174:                     }
175:                 }
176:             }
177:         }
178:     }
179:     
180:     public function addSaveRelation($relation,$message=null){
181:         $this->initSaveRelation($relation);
182:         $this->relations[$relation] = CMap::mergeArray($this->relations[$relation],array('save'=>true));
183:         if(!is_null($message)) $this->setSaveRelationMessage($relation,$message);
184:     }
185:     
186:     public function removeSaveRelation($relation){
187:         $model = $this->owner;
188:         if(!array_key_exists($relation,$model->relations())) 
189:             throw new CDbException('CSaveRelatedBehavior could not find the "'.$relation.'" relation in the model.');
190:         if(array_key_exists($relation,$this->relations)) {
191:             Yii::trace("Removing {$relation} relation to save",'application.components.CSaveRelatedBehavior');
192:             $this->relations[$relation] = CMap::mergeArray($this->relations[$relation],array('save'=>false));
193:         }
194:     }
195:     
196:     public function setRelationScenario($relation,$scenario){
197:         $this->initSaveRelation($relation);
198:         $this->relations[$relation] = CMap::mergeArray($this->relations[$relation],array('scenario'=>$scenario));   
199:     }
200:     
201:     public function setSaveRelationMessage($relation,$message) {
202:         $this->initSaveRelation($relation);
203:         $this->relations[$relation] = CMap::mergeArray($this->relations[$relation],array('message'=>$message));
204:     }
205:     
206:     public function beforeValidate($event) {
207:         $model = $this->owner;
208:         foreach($this->relations as $relation=>$params) {
209:             if(isset($params['save']) && $params['save']==true) {
210:                 $activeRelation = $model->getActiveRelation($relation);
211:                 $validRelation = true;
212:                 if(!$activeRelation instanceOf CManyManyRelation) {
213:                     foreach($model->{$relation} as $relatedRecord) {
214:                         if(isset($params['scenario'])) $relatedRecord->scenario = $params['scenario'];
215:                         $validRelation = $validRelation && $relatedRecord->validate();
216:                     }
217:                     if(!$validRelation) 
218:                         $model->addError($relation,isset($params['message']) ? $params['message'] : "An error occured during the save of {$relation}");             
219:                 }
220:                 $this->relations[$relation]['valid'] = $validRelation;
221:             }
222:         }
223:     }
224:     
225:     public function beforeSave($event) {
226:         $model = $this->owner;
227:         $valid =  true;
228:         foreach($this->relations as $relation=>$params) {
229:             if(isset($params['save']) && $params['save']==true) {
230:                 $valid = $valid && $this->relations[$relation]['valid'];
231:             }
232:         }
233:         if($valid && $this->transactional && !$model->dbConnection->currentTransaction) {
234:             Yii::trace("beforeSave start transaction",'application.components.CSaveRelatedBehavior');
235:             $this->transaction=$model->dbConnection->beginTransaction();
236:         }
237:         $event->isValid = $valid;
238:     }
239:     
240:     public function afterSave($event) {
241:         $model = $this->owner;
242:         try{
243:             foreach($this->relations as $relation=>$params) {
244:                 if(isset($params['save']) && $params['save']==true) {
245:                     Yii::trace("saving {$relation} related records.",'application.components.CSaveRelatedBehavior');
246:                     $activeRelation = $model->getActiveRelation($relation);
247:                     $relationClassName = $activeRelation->className;
248:                     $relationForeignKey = $activeRelation->foreignKey;
249:                     $keysToKeep = array();
250:                     if($activeRelation instanceOf CManyManyRelation) {
251:                         // ManyMany relation : save relation to the many to many relation table
252:                         $schema = $model->getCommandBuilder()->getSchema();
253:                         preg_match('/^\s*(.*?)\((.*)\)\s*$/',$relationForeignKey,$matches);
254:                         $joinTable=$schema->getTable($matches[1]);
255:                         $fks=preg_split('/[\s,]+/',$matches[2],-1,PREG_SPLIT_NO_EMPTY);
256:                         $fksFieldNames = array();
257:                         $fksParamNames = array();
258:                         foreach($fks as $fk) {
259:                             $fksFieldNames[] = $schema->quoteColumnName($fk);
260:                             $fksParamNames[] = ':'.$fk;
261:                         }
262:                         $sql="INSERT IGNORE INTO ".$joinTable->rawName." (".implode(', ',$fksFieldNames).") VALUES(".implode(', ',$fksParamNames).")";
263:                         $baseParams = array();
264:                         $baseCriteriaCondition = array();
265:                         reset($fks);
266:                         foreach($fks as $i=>$fk) {
267:                             if(isset($joinTable->foreignKeys[$fk])) {
268:                                 list($tableName,$pk)=$joinTable->foreignKeys[$fk];
269:                                 if($schema->compareTableNames($model->tableSchema->rawName,$tableName)) {
270:                                     $baseCriteriaCondition[$fk] = $baseParams[':'.$fk] = $model->{$pk};
271:                                 }
272:                             }
273:                         }
274:                         $relModel = new $relationClassName;
275:                         foreach($model->{$relation} as $idx=>$relatedRecord) {
276:                             $relParams = array();
277:                             reset($fks);
278:                             foreach($fks as $i=>$fk) {
279:                                 if(isset($joinTable->foreignKeys[$fk])) {
280:                                     list($tableName,$pk)=$joinTable->foreignKeys[$fk];
281:                                     if($schema->compareTableNames($relModel->tableSchema->rawName,$tableName)) {
282:                                         $keysToKeep[$fk][] = $relParams[':'.$fk] = $relatedRecord->{$pk};
283:                                     }
284:                                 }
285:                             }
286:                             $model->getCommandBuilder()->createSqlCommand($sql,$baseParams+$relParams)->execute();
287:                         }
288:                         // Delete removed records
289:                         $criteria = new CDbCriteria;
290:                         $criteria->addColumnCondition($baseCriteriaCondition);
291:                         foreach($keysToKeep as $fk=>$values)
292:                             $criteria->addInCondition($fk,$values,'AND NOT');
293:                         $model->getCommandBuilder()->createDeleteCommand($joinTable->name,$criteria)->execute();
294:                     }
295:                     else {
296:                         // HasMany relation : save related models
297:                         foreach($model->{$relation} as $relatedRecord) {
298:                             if($relatedRecord->isNewRecord) {
299:                                 if(is_array($relationForeignKey)) {
300:                                     foreach($relationForeignKey as $fk) {
301:                                         $relatedRecord->{$fk} = $model->primaryKey[$fk];
302:                                     }
303:                                 }
304:                                 else {
305:                                     $relatedRecord->{$relationForeignKey} = $model->primaryKey;
306:                                 }
307:                             }
308:                             if($relatedRecord->save()) {
309:                                 $relationPrimaryKeys = $relatedRecord->tableSchema->primaryKey;
310:                                 if(is_array($relationPrimaryKeys)) {
311:                                     foreach($relationPrimaryKeys as $relationPrimaryKey){
312:                                         if($relationPrimaryKey!=$relationForeignKey) $keysToKeep[$relationPrimaryKey][] = $relatedRecord->{$relationPrimaryKey};
313:                                     }
314:                                 }
315:                                 else{
316:                                     $keysToKeep[$relationPrimaryKeys][] = $relatedRecord->{$relationPrimaryKeys};
317:                                 }
318:                             }
319:                             else {
320:                                 throw new CException("Invalid related record");
321:                             }
322:                         }
323:                         $relatedRecord = new $relationClassName;
324:                         $criteria = new CDbCriteria;
325:                         $criteria->addColumnCondition(array($relationForeignKey=>$model->primaryKey));
326:                         foreach($keysToKeep as $fk=>$values)
327:                             $criteria->addInCondition($fk,$values,'AND NOT');
328:                         $relatedRecord->deleteAll($criteria);
329:                     }
330:                 }
331:             }
332:             unset($relation);
333:             if($this->transactional && $this->transaction) $this->transaction->commit();
334:         }
335:         catch(Exception $e)
336:         {
337:             Yii::trace("An error occured during the save operation for related records : ".$e->getMessage(),'application.components.CSaveRelatedBehavior');
338:             $this->hasError = true;
339:             if(isset($relation)) $model->addError($relation,isset($this->relations[$relation]['message']) ? $this->relations[$relation]['message'] : "An error occured during the save of {$relation}");
340:             if($this->transactional && $this->transaction) $this->transaction->rollBack();
341:         }
342:     }
343:     
344:     public function beforeDelete($event) {
345:         $model = $this->owner;
346:         if($this->transactional && !$model->dbConnection->currentTransaction) {
347:             Yii::trace("beforeDelete start transaction",'application.components.CSaveRelatedBehavior');
348:             $this->transaction=$model->dbConnection->beginTransaction();
349:         }
350:     }
351:     
352:     public function afterDelete($event) {
353:         if($this->deleteRelatedRecords) {
354:             $model = $this->owner;
355:             try{
356:                 foreach($model->relations() as $relation=>$params) {
357:                     $activeRelation = $model->getActiveRelation($relation);
358:                     if(is_object($activeRelation) && ($activeRelation instanceOf CManyManyRelation || $activeRelation instanceOf CHasManyRelation || $activeRelation instanceOf CHasOneRelation)) {
359:                         Yii::trace("deleting {$relation} related records.",'application.components.CSaveRelatedBehavior');
360:                         $relationClassName = $activeRelation->className;
361:                         $relationForeignKey = $activeRelation->foreignKey;
362:                         if($activeRelation instanceOf CManyManyRelation) {
363:                             // ManyMany relation : delete related records from the many to many relation table
364:                             $schema = $model->getCommandBuilder()->getSchema();
365:                             preg_match('/^\s*(.*?)\((.*)\)\s*$/',$relationForeignKey,$matches);
366:                             $joinTable=$schema->getTable($matches[1]);
367:                             $fks=preg_split('/[\s,]+/',$matches[2],-1,PREG_SPLIT_NO_EMPTY);
368:                             $baseParams = array();
369:                             $baseCriteriaCondition = array();
370:                             reset($fks);
371:                             foreach($fks as $i=>$fk) {
372:                                 if(isset($joinTable->foreignKeys[$fk])) {
373:                                     list($tableName,$pk)=$joinTable->foreignKeys[$fk];
374:                                     if($schema->compareTableNames($model->tableSchema->rawName,$tableName)) {
375:                                         $baseCriteriaCondition[$fk] = $baseParams[':'.$fk] = $model->{$pk};
376:                                     }
377:                                 }
378:                             }
379:                             // Delete records
380:                             $criteria = new CDbCriteria;
381:                             $criteria->addColumnCondition($baseCriteriaCondition);
382:                             $model->getCommandBuilder()->createDeleteCommand($joinTable->name,$criteria)->execute();
383:                         }
384:                         else {
385:                             // HasMany & HasOne relation : delete related records
386:                             $relatedRecord = new $relationClassName;
387:                             $criteria = new CDbCriteria;
388:                             $criteria->addColumnCondition(array($relationForeignKey=>$model->primaryKey));
389:                             $relatedRecord->deleteAll($criteria);
390:                         }
391:                     }
392:                 }
393:                 unset($relation);
394:                 if($this->transactional && $this->transaction) $this->transaction->commit();
395:             }
396:             catch(Exception $e)
397:             {
398:                 Yii::trace("An error occured during the delete operation for related records : ".$e->getMessage(),'application.components.CSaveRelatedBehavior');
399:                 $this->hasError = true;
400:                 if(isset($relation)) $model->addError($relation,"An error occured during the delete operation of {$relation}");
401:                 if($this->transactional && $this->transaction) $this->transaction->rollBack();
402:             }
403:         }
404:     }
405: }
X2CRM Documentation API documentation generated by ApiGen 2.8.0