public function handleCheckAutoBuildCompleted($event)
 {
     if (!RedBeanDatabaseBuilderUtil::isAutoBuildStateValid()) {
         echo Zurmo::t('ZurmoModule', 'Database upgrade not completed. Please try again later.');
         Yii::app()->end(0, false);
     }
 }
Beispiel #2
0
 /**
  * Auto builds the database.  Must manually set AuditEvent first to avoid issues building the AuditEvent
  * table. This is because AuditEvent is specially optimized during this build process to reduce how
  * long this takes to do.
  */
 public static function autoBuildDatabase(&$messageLogger)
 {
     $rootModels = array();
     $rootModels[] = 'AuditEvent';
     foreach (Module::getModuleObjects() as $module) {
         $moduleAndDependenciesRootModelNames = $module->getRootModelNamesIncludingDependencies();
         $rootModels = array_merge($rootModels, array_diff($moduleAndDependenciesRootModelNames, $rootModels));
     }
     ZurmoDatabaseCompatibilityUtil::createStoredFunctionsAndProcedures();
     RedBeanDatabaseBuilderUtil::autoBuildModels($rootModels, $messageLogger);
     ZurmoDatabaseCompatibilityUtil::createIndexes();
 }
 public function resolveDatabaseSchemaForModel($modelClassName)
 {
     assert('is_string($modelClassName) && $modelClassName != ""');
     if (RedBeanDatabase::isFrozen()) {
         Yii::app()->gameHelper->muteScoringModelsOnSave();
         $messageLogger = new MessageLogger();
         RedBeanDatabaseBuilderUtil::manageFrozenStateAndAutoBuildModels(array('User', $modelClassName), $messageLogger);
         Yii::app()->gameHelper->unmuteScoringModelsOnSave();
         if ($messageLogger->isErrorMessagePresent()) {
             throw new FailedDatabaseSchemaChangeException($messageLogger->printMessages(true, true));
         }
     }
 }
 /**
  * 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);
 }