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 }