Config::set('app.dir.controllers', dirname(dirname(__FILE__)) . '/controllers'); Config::set('app.dir.ignored', array('.', '..', '.svn', 'cvs')); Config::set('app.docRoot', dirname(dirname(__FILE__))); Config::set('app.domain', 'localhost'); Config::set('app.password', 'password'); Config::set('app.dir.databases', dirname(dirname(__FILE__)) . '/db'); AutoLoader::addClassPath(dirname(dirname(__FILE__)) . '/models'); AutoLoader::addClassPath(dirname(dirname(__FILE__)) . '/models/managers'); /* # Database */ Database::addConnection(array('name' => 'default', 'driver' => 'sqlite', 'dsn' => 'sqlite:' . Config::get('app.dir.databases') . '/model.s3db')); /* Alternative for testing whilst building test on dev machine Database::addConnection(array( 'name'=>'default', 'driver'=>'mysql', 'dsn'=>'mysql:host=localhost;dbname=buan_test', 'username'=>'root', 'password'=>'' ));*/ /* # Model relationships */ ModelRelation::define('Person(1):PersonAddress(M):Address(1)'); ModelRelation::define('Person(1):Account(1)'); ModelRelation::define('Person(1):PersonAlias(M,2)'); ModelRelation::define('Person(1):PersonBook(M):Book(1)'); ModelRelation::define('Library(1):Book(M)'); ModelRelation::define('Category(1):Category(M)'); ModelRelation::define('Person(1):Friend.person_a_id.person_b_id(M):Person(1)');
/** * Removes the specified Model form the database. * * Returns TRUE on successful removal, FALSE otherwise. * * @todo There's question of recursion happening. Suck it and see. * * @param Model $model Model to be deleted * @return bool */ public function delete(Model $model) { // Check if Model is actually in the database // (can't delete Models that are not in persistent storage) if (!$model->isInDatabase()) { SystemLog::add("Attempting to delete non-persistent Model ({$model->modelName} #{$model->getPrimaryKeyValue()}).", SystemLog::CORE); return true; } // Get a DB connection for the given Model and start a transaction. $DB = null; try { $DB = Database::getConnectionByModel($model); // $dbTransactionActive = $DB->getAttribute(PDO::ATTR_AUTOCOMMIT) == 1 ? true : false; $DB->beginTransaction(); $dbTransactionActive = true; } catch (Exception $e) { SystemLog::add($e->getMessage(), SystemLog::NOTICE); $dbTransactionActive = false; } // Delete $original_isInDatabase = $model->isInDatabase(); $original_hasChanged = $model->hasChanged(); try { // Delete the model itself from the db $sql = 'DELETE FROM `' . $model->getDbTableName() . '` WHERE ' . $model->getPrimaryKey() . '=?'; $stmt = $DB->prepare($sql); $stmt->execute([$model->getPrimaryKeyValue()]); // Find all relationships that include $model $relations = ModelRelation::getRelation($model->modelName); foreach ($relations as $relation) { switch ($relation->getCardinality()) { // 1:M (including 1:1, ie. 1:M,1) case ModelRelation::ONE_TO_MANY: // Delete all "M" Models, if cascading is allowed $relatedModels = $model->findRelatives($relation->getTargetModel(), $relation->getReference()); if ($relation->getLimit() == 1) { $relatedModels = $relatedModels->isEmpty() ? [] : $relatedModels->asArray(); } if (!$relation->getOption('nocascade')) { foreach ($relatedModels as $rModel) { $model->disownRelatives($rModel); if (!$rModel->getModelManager()->delete($rModel)) { // TODO: Do we rollback here? } //$model->disownRelatives($rModel); } } else { foreach ($relatedModels as $rModel) { $model->disownRelatives($rModel); $rModel->{$rModel->getForeignKey($model, $relation->getReference())} = 0; if (!$rModel->getModelManager()->save($rModel)) { // TODO: Rollback? } } } // Break break; // M:1 // M:1 case ModelRelation::MANY_TO_ONE: // Break relation between Models //$relatedModel = $model->findRelatives($relation->getTargetModel(), $relation->getReference())->get(0); $relatedModel = $model->findRelatives($relation->getTargetModel(), $relation->getReference()); //if($relatedModel!==NULL) { if (!$relatedModel->isEmpty()) { //$model->disownRelatives($relatedModel); $model->disownRelatives($relatedModel); } break; // M:M // M:M case ModelRelation::MANY_TO_MANY: // M:M relationships should actually already be broken down into 1:M/M:1 // so this case can be ignored. break; // default // default default: break; } } // Return if ($dbTransactionActive) { $DB->commit(); } // Set flags on $model to indicate that it's no longer persistent $model->isInDatabase(false); $model->hasChanged(false); // Result return true; } catch (PDOException $e) { // Set attributes $model->isInDatabase($original_isInDatabase); $model->hasChanged($original_hasChanged); // Log, rollback and return SystemLog::add($e->getMessage(), SystemLog::WARNING); try { if ($dbTransactionActive) { $DB->rollBack(); } } catch (PDOException $e) { SystemLog::add($e->getMessage(), SystemLog::WARNING); } return false; } }