/** * Perform commands to upgrade/downgrade the version of the class from $from_ver to $to_ver * * @param string $from_ver * @param string $to_ver * @return bool TRUE on success, FALSE on nothing to update * @throws exception on command error */ function migrate($from_ver, $to_ver) { if (version_compare($from_ver, $to_ver) > 0) { $this->output("Downgrading from {$from_ver} to {$to_ver}"); // $from_ver is bigger than to_ver - downgrade // Start with the from_ver, and execute each command in reverse order untill // reaching to_ver, but to execute any of the to_var commands // Example: from_ver = 2.1, to_ver = 1.5 $prev_ver = false; foreach (array_reverse($this->log) as $ver => $commands) { if ($prev_ver) { // yeald to the caller - we need to save the installed cache on each mirgated version $this->install->installed[$this->class] = $prev_ver; $this->install->saveInstalled(); } if (version_compare($ver, $to_ver, '<=')) { break; } // Stop at the "to_ver" w/out executing any of the commands // Example - break if ver = 1.5, 1.2, 1.1, but not when ver = 1.8 if (version_compare($ver, $from_ver, '>')) { continue; } // Skip commands in the version before entering the from_ver span // Example - skip if ver = 2.5 or 3.0 or 2.1.1 BUT NOT IF ver is 2.1 or 2.0.1 or 1.6 $this->output("Undoing version {$ver}"); foreach (array_reverse($commands) as $cmd) { if (isset($cmd['down'])) { $this->output("Running {$cmd['callback']}"); call_user_func_array(array($this, $cmd['callback']), $cmd['down']); } } $prev_ver = $ver; } return true; } elseif (version_compare($from_ver, $to_ver) < 0) { $this->output("Upgrading from {$from_ver} to {$to_ver}"); // $to_ver is bigger than from_ver - upgrad // Start with the from_ver, but skip it (it is already executed) and move on untill // reaching the last of the $to_ver commands // Example: from_var = 1.5, to_var=1.9 foreach ($this->log as $ver => $commands) { if (version_compare($ver, $to_ver, '>')) { break; } // The to_ver must be the lastly exeuted command // Example - break if ver = 2.0, 1.9.4, 3.1, but not when ver = 1.8 or 1.0 or 1.9 if (version_compare($ver, $from_ver, '<=')) { continue; } // Skip commands in the version before entering the from_ver span, incl the from_ver // Example - skip if ver = 1.1 or 1.0 or 1.5 BUT NOT IF ver is 1.5.1 or 2.0 or 1.9 foreach ($commands as $cmd) { if (isset($cmd['up'])) { $this->output("Running {$cmd['callback']}"); call_user_func_array(array($this, $cmd['callback']), $cmd['up']); } } $this->output("Updated to version {$ver}"); $this->install->installed[$this->class] = $ver; $this->install->saveInstalled(); } return true; } else { // Versions are equal - nothing to upgrade return false; } }