public function teardown() { AuditEvent::$isTableOptimized = false; parent::teardown(); }
public static function logAuditEvent($moduleName, $eventName, $data = null, RedBeanModel $model = null, User $user = null) { assert('is_string($moduleName) && $moduleName != ""'); assert('is_string($eventName) && $eventName != ""'); if ($user === null) { $user = Yii::app()->user->userModel; if (!$user instanceof User) { throw new NoCurrentUserSecurityException(); } } if ($eventName == "Item Viewed") { AuditEventsRecentlyViewedUtil::resolveNewRecentlyViewedModel($data[1], $model, AuditEventsRecentlyViewedUtil::RECENTLY_VIEWED_COUNT + 1); } if ($eventName == "Item Deleted") { $modelClassName = get_class($model); AuditEventsRecentlyViewedUtil::deleteModelFromRecentlyViewed($modelClassName::getModuleClassName(), $model); } if (!AuditEvent::$isTableOptimized && !AUDITING_OPTIMIZED) { $auditEvent = new AuditEvent(); $auditEvent->dateTime = DateTimeUtil::convertTimestampToDbFormatDateTime(time()); $auditEvent->moduleName = $moduleName; $auditEvent->eventName = $eventName; $auditEvent->user = $user; $auditEvent->modelClassName = $model !== null ? get_class($model) : null; $auditEvent->modelId = $model !== null ? $model->id : null; $auditEvent->serializedData = serialize($data); $saved = $auditEvent->save(); AuditEvent::$isTableOptimized = true; } else { $sql = "insert into auditevent (datetime,\n modulename,\n eventname,\n _user_id,\n modelclassname,\n modelid,\n serializeddata)\n values ('" . DateTimeUtil::convertTimestampToDbFormatDateTime(time()) . "',\n '{$moduleName}',\n '{$eventName}',\n {$user->id}, " . ($model !== null ? "'" . get_class($model) . "', " : 'null, ') . ($model !== null ? "{$model->id}, " : 'null, ') . ":data)"; ZurmoRedBean::exec($sql, array('data' => serialize($data))) !== null; $saved = true; } return $saved; }
/** * Auto building of models (and therefore the database) involves... * * - Creating each model. * - Setting its members to made up values that conform to the rules specified for the member. * - Setting or adding to its relations while avoiding making new objects of the same types * as have already been made. * - Saving it so that the tables and columns are created. * - Deleting it so that it doesn't leave rows behind. * - (The database is now ready for freezing.) * * The aim of the auto build is to populate models in a 'valid enough way' to save them * such that RedBean creates the tables and columns it needs with the right column types. * This means it does not necessarily make models that are valid, for example it will set * a model's parent to itself if model and the parent are of the same type. These kinds of * inconsistencies do not matter for the purpose of auto building the database, and are * semantic information that is not available and not needed for this process. The idea is * to create as few models as possible. * * Call this an empty unfrozen database with all the models required for certain tests, or * all the models required for the production database. Then freeze the database. * * If a model references a non-leaf model in the hierarchy an example of a model subclassed * from that type must be included in the $modelClassNames. eg: 'Opportunity' references * Permitable via its permissions and an abstract 'Permitable' cannot be created, so 'User' * needs be created at the same time since it is concrete and can be used to create an * Opportunity. * ie: $modelClassNames = array('Opportunity', 'User'). */ public static function autoBuildModels(array $modelClassNames, &$messageLogger) { assert('AssertUtil::all($modelClassNames, "is_string")'); assert('$messageLogger instanceof MessageLogger'); if (!self::isAutoBuildStateValid()) { self::deleteAllSampleModelsFromStatePersisterAndDatabase($messageLogger); } self::setAutoBuildStateInStatePersister(self::AUTO_BUILD_STATE_INVALID); AuditEvent::$isTableOptimized = false; self::$modelClassNamesToSampleModels = array(); foreach ($modelClassNames as $modelClassName) { $messages[] = array('info' => "Auto building {$modelClassName}."); self::autoBuildSampleModel($modelClassName, $modelClassNames, $messageLogger); $messageLogger->addInfoMessage("Auto build of {$modelClassName} done."); } foreach (self::$modelClassNamesToSampleModels as $modelClassName => $model) { if (!$model instanceof OwnedModel && !$model instanceof OwnedCustomField && !$model instanceof OwnedMultipleValuesCustomField) { try { $model->setScenario('autoBuildDatabase'); $saved = $model->save(); if ($saved) { self::setSampleModelInStatePersister(get_class($model), $model->id); $metadata = $model->getMetadata(); foreach ($metadata as $unused => $classMetadata) { if (!empty($classMetadata['relations'])) { foreach ($classMetadata['relations'] as $relationName => $relationTypeModelClassNameAndOwns) { $relationType = $relationTypeModelClassNameAndOwns[0]; $relatedModelClassName = $relationTypeModelClassNameAndOwns[1]; $owned = isset($relationTypeModelClassNameAndOwns[2]) && $relationTypeModelClassNameAndOwns[2] == RedBeanModel::OWNED; if (get_class($model) == get_class($model->{$relationName}) && $model->id == $model->{$relationName}->id) { $messageLogger->addInfoMessage("Unset {$modelClassName}->{$relationName} to avoid recursion and thread stack overrun."); $model->{$relationName} = null; $model->save(); } } } } } else { $messageLogger->addErrorMessage("*** Saving the sample {$modelClassName} failed."); $errors = $model->getErrors(); if (count($errors) > 0) { $messageLogger->addErrorMessage('The attributes that did not validate probably need more rules, or are not deletable types.'); $messageLogger->addErrorMessage(print_r($errors, true)); } else { $messageLogger->addErrorMessage('No attributes failed to validate!'); } } $messageLogger->addInfoMessage("Auto built {$modelClassName} saved."); } catch (NotSupportedException $e) { $messageLogger->addErrorMessage("*** Saving the sample {$modelClassName} failed."); if (is_subclass_of($modelClassName, 'OwnedCustomField') || is_subclass_of($modelClassName, 'OwnedMultipleValuesCustomField') || is_subclass_of($modelClassName, 'OwnedModel')) { $messageLogger->addErrorMessage('It is OWNED and was probably not saved via its owner, making it not a root model.'); } else { $messageLogger->addErrorMessage('The save failed but there were no validation errors.'); } } } } foreach (self::$modelClassNamesToSampleModels as $modelClassName => $model) { try { if (!$model->isDeleted()) { if (!$model->delete()) { if ($model->id < 0) { $messageLogger->addInfoMessage(get_class($model) . " Not Deleted but never saved so this is ok. (Most likely it is a - Has Many Owned)"); } else { $messageLogger->addErrorMessage("*** Deleting the sample " . get_class($model) . " failed. It would not delete."); } } else { $messageLogger->addInfoMessage(get_class($model) . " Deleted (Not Owned)."); } } else { $messageLogger->addInfoMessage(get_class($model) . " Deleted Already (Owned)."); } AuditEvent::deleteAllByModel($model); unset(self::$modelClassNamesToSampleModels[$modelClassName]); } catch (NotSupportedException $e) { $messageLogger->addErrorMessage("*** Deleting the sample {$modelClassName} failed. It is marked not deletable."); } } if (count(self::$modelClassNamesToSampleModels)) { $messageLogger->addErrorMessage('*** Deleting of the sample(s) ' . join(', ', array_keys(self::$modelClassNamesToSampleModels)) . " didn't happen."); } AuditEvent::$isTableOptimized = false; self::deleteAllSampleModelsFromStatePersister(); self::setAutoBuildStateInStatePersister(self::AUTO_BUILD_STATE_VALID); }