00001 <?php
00002
00003
00004
00005 class SystemUpdateExecutor {
00006
00007
00008
00009
00010
00011 public function execute_updates() {
00012 Load::components('systemupdateconnectionmapper');
00013 Load::models('systemupdates');
00014 $ret = $this->check_systemupdate_is_uptodate();
00015 $dirs = Load::get_base_directories(Load::ORDER_DECORATORS);
00016 foreach($dirs as $dir) {
00017 $component = $this->extract_component($dir);
00018 $connection = SystemUpdateConnectionMapper::get_module_connection($component);
00019 $err_prerequisites = $this->check_component_preconditions($component, $dir);
00020 if ($err_prerequisites->is_ok()) {
00021 $update_entry = SystemUpdates::get($component, $connection);
00022 if ($update_entry === false) {
00023
00024 $ret = array_merge($ret, $this->install_component($component, $dir, $connection, $update_entry));
00025 }
00026 if ($update_entry) {
00027 $ret = array_merge($ret, $this->update_component($component, $dir, $connection, $update_entry));
00028 }
00029 }
00030 else {
00031 $ret[] = $this->create_log_entry($component, 'preconditions', $err_prerequisites);
00032 }
00033 }
00034 foreach($dirs as $dir) {
00035 $component = $this->extract_component($dir);
00036 $ret = array_merge($ret, $this->check_component_postconditions($component, $dir));
00037 }
00038
00039
00040 Load::commands('generics/clearcache');
00041 $cmd = new ClearCacheCommand(null);
00042 $cmd->execute();
00043
00044 return $ret;
00045 }
00046
00047
00048
00049
00050
00051
00052 protected function check_systemupdate_is_uptodate() {
00053 $ret = array();
00054 $component = 'systemupdate';
00055 $dir = Load::get_module_dir('systemupdate');
00056
00057 foreach(SystemUpdateConnectionMapper::get_all_connections() as $connection) {
00058 try {
00059 $update_entry = SystemUpdates::get($component, $connection);
00060 if ($update_entry === false) {
00061
00062 $ret = array_merge($ret, $this->install_component($component, $dir, $connection, $update_entry));
00063 }
00064 }
00065 catch (Exception $ex) {
00066
00067 $ret = $this->install_component($component, $dir, $connection, $update_entry);
00068 }
00069 $ret = array_merge($ret, $this->update_component($component, $dir, $connection, $update_entry));
00070 }
00071 return $ret;
00072 }
00073
00074
00075
00076
00077
00078
00079
00080
00081 protected function check_component_preconditions($component, $dir) {
00082 $check_php = $dir . 'install/check_preconditions.php';
00083 $err = new Status();
00084
00085 if (file_exists($check_php)) {
00086 $func = $this->make_func_name($component, 'check_preconditions');
00087 $err->merge($this->execute_php_script($check_php, $func));
00088 }
00089
00090 return $err;
00091 }
00092
00093
00094
00095
00096
00097
00098
00099
00100 protected function check_component_postconditions($component, $dir) {
00101 $ret = array();
00102
00103 $check_php = $dir . 'install/check_postconditions.php';
00104 $err = new Status();
00105
00106 if (file_exists($check_php)) {
00107 $func = $this->make_func_name($component, 'check_postconditions');
00108 $err->merge($this->execute_php_script($check_php, $func));
00109 $ret[] = $this->create_log_entry($component, 'check postconditions', $err);
00110 }
00111
00112 return $ret;
00113 }
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 protected function install_component($component, $dir, $connection, &$update_entry) {
00124 $install_dir = $dir . 'install/';
00125 $install_sql = $install_dir . 'install.sql';
00126 $install_php = $install_dir . 'install.php';
00127
00128 $ret = array();
00129 $err = new Status();
00130
00131 if (file_exists($install_sql)) {
00132 $err->merge($this->execute_sql_script($install_sql, $connection));
00133 $ret[] = $this->create_log_entry($component, $install_sql, $err);
00134 }
00135
00136 if ($err->is_ok() && file_exists($install_php)) {
00137 $func = $this->make_func_name($component, 'install');
00138 $err = $this->execute_php_script($install_php, $func);
00139 $ret[] = $this->create_log_entry($component, $install_php, $err);
00140 }
00141
00142 if ($err->is_ok()) {
00143 $err->merge(SystemUpdates::create($component, $connection, $update_entry));
00144 }
00145
00146 $ret[] = $this->create_log_entry($component, 'install', $err);
00147 return $ret;
00148 }
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 protected function update_component($component, $dir, $connection, $update_entry) {
00159 $updates_dir = $dir . 'install/updates/';
00160 $ret = array();
00161 if (!file_exists($updates_dir)) {
00162 return $ret;
00163 }
00164
00165 $err = new Status();
00166 $files = scandir($updates_dir);
00167
00168 foreach($files as $file) {
00169 $version = intval($file);
00170 if ($version > $update_entry->version) {
00171
00172 $err->merge($this->update_from_file($updates_dir . $file, $component, $version, $connection));
00173 $ret[] = $this->create_log_entry($component, $file, $err);
00174 if ($err->is_ok()) {
00175 $update_entry->version = $version;
00176 $err->merge(SystemUpdates::update($update_entry, $connection));
00177 }
00178 }
00179 if ($err->is_error()) {
00180 break;
00181 }
00182 }
00183
00184
00185 if (count($ret) > 0) {
00186 $ret[] = $this->create_log_entry($component, 'updates', $err);
00187 }
00188
00189 return $ret;
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199 protected function update_from_file($file, $component, $version, $connection) {
00200 $ret = new Status();
00201 $fileinfo = pathinfo($file);
00202 $extension = strtolower(Arr::get_item($fileinfo, 'extension', ''));
00203 switch ($extension) {
00204 case 'sql':
00205 $ret->merge($this->execute_sql_script($file, $connection));
00206 break;
00207 case 'php':
00208 $func = $this->make_func_name($component, 'update_' . $version);
00209 $ret->merge($this->execute_php_script($file, $func));
00210 break;
00211 default:
00212 $ret->append(tr('Could not process file: Unknown file type', 'systemupdate'));
00213 break;
00214 }
00215 return $ret;
00216 }
00217
00218
00219
00220
00221
00222
00223
00224 protected function execute_sql_script($file, $connection) {
00225 $ret = new Status();
00226 try {
00227 $ret->merge(DB::execute_script($file, $connection));
00228 }
00229 catch (Exception $ex) {
00230 $ret->merge($ex);
00231 }
00232 return $ret;
00233 }
00234
00235
00236
00237
00238
00239
00240
00241
00242 protected function execute_php_script($file, $func) {
00243 $ret = new Status();
00244 require_once($file);
00245 if (function_exists($func)) {
00246 $ret->merge($func());
00247 }
00248 else {
00249
00250 $ret->append(tr('Function %func not found!', 'systemupdate', array('%func' => $func)));
00251 }
00252 return $ret;
00253 }
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263 protected function create_log_entry($component, $task, $err) {
00264 return array(
00265 'component' => $component,
00266 'task' => $task,
00267 'status' => $err
00268 );
00269 }
00270
00271
00272
00273
00274
00275
00276
00277 protected function extract_component(&$dir) {
00278
00279 $tmp = explode('/', trim($dir, '/'));
00280 $ret = array_pop($tmp);
00281 if ($ret === 'core') {
00282 $dir .= '../';
00283 }
00284 return $ret;
00285 }
00286
00287 protected function make_func_name($component, $func_postfix) {
00288 return String::plain_ascii($component, '_', true) . '_' . $func_postfix;
00289 }
00290 }