diff --git a/app.php b/app.php index 34371a4..4654189 100644 --- a/app.php +++ b/app.php @@ -142,9 +142,11 @@ public static function boot() { Router::get()->init(); if (Environment::getCurrentEnvironment() == Environment::DEVELOPMENT) { - // always check for changed migrations on development (except when resetting) - if (!(Router::get()->getCurrentModule() instanceof CoreRoutes_Reset)) + // always check for changed migrations and reset callbacks on development (except when resetting) + if (!(Router::get()->getCurrentModule() instanceof CoreRoutes_Reset)) { Core_MigrationsLoader::load(); + CoreRoutes_Reset::executeCallbacksOnAfterReset(); + } } Router::get()->runCurrentModule(); @@ -427,4 +429,4 @@ function backtrace() { Core_Dump::backtrace(); } -?> \ No newline at end of file +?> diff --git a/core/coreroutes/reset.php b/core/coreroutes/reset.php index 2aa99d4..88a8e0b 100644 --- a/core/coreroutes/reset.php +++ b/core/coreroutes/reset.php @@ -22,6 +22,10 @@ * Resets the project. */ class CoreRoutes_Reset extends Module { + + // path of reset callback logfile, relative to PROJECT_PATH + const RESET_CALLBACK_LOG_FILE = '/config/log/reset_callback.log.xml'; + private static $callbacksOnAfterReset = array(); public function init() { @@ -31,8 +35,12 @@ public function init() { DB_Connection::get()->deleteTables(); // remove migrations log - $file = new IO_File(PROJECT_PATH.Core_MigrationsLoader::MIGRATION_LOG_FILE); - $file->delete(); + $migrationFile = new IO_File(PROJECT_PATH.Core_MigrationsLoader::MIGRATION_LOG_FILE); + $migrationFile->delete(); + + // remove reset callbacks log + $resetCallbacksFile = new IO_File(PROJECT_PATH.self::RESET_CALLBACK_LOG_FILE); + $resetCallbacksFile->delete(); // clear global cache $GLOBALS['cache']->clearAll(); @@ -46,10 +54,8 @@ public function init() { // rebuild database Core_MigrationsLoader::load(); - if (defined('CALLBACK_ONAFTERRESET')) - self::addCallbackOnAfterReset(CALLBACK_ONAFTERRESET); - foreach (self::$callbacksOnAfterReset as $callback) - call_user_func($callback); + // execute registered callbacks + self::executeCallbacksOnAfterReset(); Scriptlet::redirect(PROJECT_ROOTURI); } @@ -57,6 +63,55 @@ public function init() { public static function addCallbackOnAfterReset($callback) { self::$callbacksOnAfterReset[] = $callback; } + + /** + * Executes the callbacks registered by addCallbackOnAfterReset + * or defined by the constant CALLBACK_ONAFTERRESET. + * Execution is only performed if the callbacks haven't been called + * since the last reset. + * This method is intended to be used when there's a reason to execute + * these callbacks once, even when there's no complete reset being performed. + * One such reason is the initial setup and running newly added callbacks + * in development mode. + * Callbacks that differ only in the instance of a class and not in the method called + * will be treated as if they were the same. So if more than one instance of a class + * is used for a callback, each instance needs its unique member function to be executed. + */ + public static function executeCallbacksOnAfterReset() { + + if (defined('CALLBACK_ONAFTERRESET')) + self::addCallbackOnAfterReset(CALLBACK_ONAFTERRESET); + + if (file_exists(PROJECT_PATH.self::RESET_CALLBACK_LOG_FILE)) + $xml = simplexml_load_file(PROJECT_PATH.self::RESET_CALLBACK_LOG_FILE); + else { + $baseResetCallbackLog = ''; + $xml = new SimpleXMLElement($baseResetCallbackLog); + } + + foreach (self::$callbacksOnAfterReset as $callback) { + if (is_array($callback) && isset($callback[0]) && isset($callback[1])) { + // different objects of the same class will be treated as if they were the same + $callbackIdentifier = get_class($callback[0]).'->'.$callback[1]; + } else $callbackIdentifier = $callback; + + // execute reset callbacks if they haven't been before + $result = $xml->xpath(sprintf('/content/callback[@identifier=\'%s\']', $callbackIdentifier)); + if (empty($result)) { + $result = $xml->xpath('/content'); + $child = $result[0]->addChild('callback'); + $child->addAttribute('identifier', $callbackIdentifier); + call_user_func($callback); + } + } + // save reset callback logfile + $doc = new DOMDocument('1.0'); + $doc->preserveWhiteSpace = false; + $doc->loadXML($xml->asXML()); + $doc->formatOutput = true; + $doc->save(PROJECT_PATH.self::RESET_CALLBACK_LOG_FILE); + } + } -?> \ No newline at end of file +?>