public function save($deep = true) { // run before save foreach (static::$_classBeforeSave as $beforeSave) { if (is_callable($beforeSave)) { $beforeSave($this); } } if (static::isVersioned()) { $wasDirty = false; if ($this->isDirty && static::$createRevisionOnSave) { // update creation time $this->Created = time(); $wasDirty = true; } } // set created if (static::_fieldExists('Created') && (!$this->Created || $this->Created == 'CURRENT_TIMESTAMP')) { $this->Created = time(); } // validate if (!$this->validate($deep)) { throw new RecordValidationException($this, 'Cannot save invalid record'); } // clear caches foreach ($this->getClassFields() as $field => $options) { if (!empty($options['unique']) || !empty($options['primary'])) { $key = sprintf('%s/%s:%s', static::$tableName, $field, $this->getValue($field)); DB::clearCachedRecord($key); } } // traverse relationships if ($deep) { $this->_saveRelationships(); } if ($this->isDirty) { // prepare record values $recordValues = $this->_prepareRecordValues(); // transform record to set array $set = static::_mapValuesToSet($recordValues); // create new or update existing if ($this->_isPhantom) { DB::nonQuery('INSERT INTO `%s` SET %s', array(static::$tableName, join(',', $set)), array(static::$rootClass, 'handleError')); $this->_record[static::$primaryKey ? static::$primaryKey : 'ID'] = DB::insertID(); $this->_isPhantom = false; $this->_isNew = true; } elseif (count($set)) { DB::nonQuery('UPDATE `%s` SET %s WHERE `%s` = %u', array(static::$tableName, join(',', $set), static::_cn(static::$primaryKey ? static::$primaryKey : 'ID'), $this->getPrimaryKey()), array(static::$rootClass, 'handleError')); $this->_isUpdated = true; } // update state $this->_isDirty = false; if (static::isVersioned()) { if ($wasDirty && static::$createRevisionOnSave) { // save a copy to history table $recordValues = $this->_prepareRecordValues(); $set = static::_mapValuesToSet($recordValues); DB::nonQuery('INSERT INTO `%s` SET %s', array(static::getHistoryTable(), join(',', $set))); } } } // run after save foreach (static::$_classAfterSave as $afterSave) { if (is_callable($afterSave)) { $afterSave($this); } } // traverse relationships again if ($deep) { $this->_postSaveRelationships(); } }