2 /**********************************************************************
3 Copyright (C) FrontAccounting, LLC.
4 Released under the terms of the GNU General Public License, GPL,
5 as published by the Free Software Foundation, either version 3
6 of the License, or (at your option) any later version.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
11 ***********************************************************************/
12 include_once($path_to_root."/includes/packages.inc");
14 // Utility class contains basic database upgrade routines.
17 var $previous; // previous database version
18 var $version; // version after upgrade
19 var $description; // short patch description
21 var $sql; // basic sql file
24 var $backup; // pre-upgrade backup filename
26 var $errors = array();
27 var $max_upgrade_time = 300;
33 include $path_to_root."/config_db.php";
35 $this->companies = $db_connections;
37 return $this->companies;
41 Collect/log messages generated during upgrade process.
43 function log_error($msg, $type='Error')
46 $this->errors[] = $msg;
47 error_log(sprintf('[%s] %s', $type, $msg));
52 Selectively extends access to selected security areas/sections.
54 function update_security_roles($sec_updates)
56 global $security_areas, $security_sections;
58 $roles = db_query("SELECT * FROM ".TB_PREF."security_roles");
60 while($role = db_fetch($roles))
62 $role['areas'] = explode(';', $role['areas']);
63 $role['sections'] = explode(';', $role['sections']);
64 foreach($sec_updates as $has => $add)
66 if (in_array($security_areas[$has][0], $role['areas']))
69 foreach($add as $area)
71 $role['areas'][] = $security_areas[$area][0];
72 $role['sections'][] = $security_areas[$area][0]&~0xff;
75 update_security_role($role['id'], $role['role'], $role['description'],
76 array_values($role['sections']), array_values($role['areas']));
84 Check and disable incompatible extensions.
86 function update_extensions()
90 $mods = get_company_extensions();
91 $exts = get_company_extensions($this->cur_company);
94 foreach($mods as $key => $ins) {
95 foreach($exts as $ext)
96 if ($ext['name'] == $ins['name'] && (!check_src_ext_version($ins['version']))) {
97 $mods[$key]['active'] = false;
98 $this->log_error(sprintf(_("Uncompatible extension '%s' disabled for company %d."), $ins['name'], $this->cur_company), 'Notice');
104 write_extensions($mods, $this->cur_company);
108 Pre-install maintenance: login to company, open upgrade log, make a backup
110 function pre_install($company)
114 $this->cur_company = $company;
115 $this->errors = array();
116 $this->backup = null;
118 $this->save_log = ini_set('error_log', dirname(__FILE__).'/../../tmp/upgrade.'.$this->cur_company.'.log');
119 $this->log_error(sprintf(_("Upgrade started for company %s."), $this->cur_company), 'Info');
121 if (!set_global_connection($this->cur_company))
122 return $this->log_error(_("Cannot connect to company database."));
124 $cur_ver = get_company_pref('version_id', true);
125 if ($cur_ver != $this->previous)
126 return $this->log_error(sprintf(_("Cannot upgrade company %s: database version is incompatible ('%s' instead of '%s')."),
127 $this->cur_company, $cur_ver, $this->previous));
129 $this->update_extensions(); // disable uncompatible extensions
131 if (!$this->prepare()) // fetch params, perform additional checks (if any)
135 return true; // skip security backup if database content is not changed
137 $this->backup = db_backup($this->companies[$this->cur_company], 'no', 'Security backup before upgrade',
138 $SysPrefs->backup_dir($this->cur_company));
141 return $this->log_error(_("Security backup failed."));
143 $this->log_error(sprintf(_("Security backup in file %s done."), $this->backup), 'Info');
148 Basic install procedure using sql file.
150 function sql_install($company, $force=false)
152 global $path_to_root;
154 if ($this->sql != '') // perform basic upgrade operations defined in sql file
158 if ($result === true)
159 $result = db_import($path_to_root. '/sql/'.$this->sql, $this->companies[$company],
160 $force, true, false, true);
162 if ($result !== true)
164 if (is_array($result))
166 foreach($result as $err)
167 $this->log_error($err[1] . ':'. $err[0]);
170 $this->log_error($result);
171 unset($this->backup); // prevent restore (database was not touched due to other errors)
180 Post install procedures: update database version, or restore databse from backup file in case of errors
182 function post_install($result=true)
186 if ($result !== true)
190 if (!set_global_connection($this->cur_company)) // reset connection to clear encoding
191 return $this->log_error(_("Cannot connect to company database for database restore."));
193 set_time_limit($this->max_upgrade_time);
194 $result = db_import($this->backup, $this->companies[$this->cur_company], true, false);
196 $this->log_error(_("Upgrade failed. Original database content restored successfully."), 'Info');
198 $this->log_error(sprintf(_("Database restore operation failed. Original database content is in %s file."), $this->backup));
199 $this->post_fail($this->cur_company);
202 update_company_prefs(array('version_id' => $this->version));
205 $this->log_error(sprintf(_("Upgrade for company %s finished."), $this->cur_company), 'Info');
207 set_global_connection();
208 ini_set('error_log', $this->save_log);
217 Main routine for single company upgrade.
219 function upgrade_company($comp, $force=false)
221 $result = $this->pre_install($comp) && $this->sql_install($comp, $force) && $this->install($comp, $force);
223 $this->post_install($result);
225 return count($this->errors) == 0;
229 Additional version specific php/sql upgrade procedures.
230 This procedure is performed after basic sql upgrade script is run.
232 function install($company, $force=false)
237 Optional cleanup procedure.
238 This procedure is run in case of upgrade failure, before the backup is restored.
240 function post_fail($company)
245 Present upgrade parameters to administrator
246 This function presents upgrade choices, after selection company to be upgraded.
248 function show_params($comp)
253 Fetch & check upgrade parameters, check additional upgrade pre-conditions.
254 This function is run after successfull switching to target database connection.
264 Return databases status info.
266 function get_site_status($connections)
272 foreach($connections as $i => $conn)
274 $info[$i]['status'] = set_global_connection($i) !== false;
276 $info[$i]['name'] = $conn['name'];
277 $info[$i]['table_set'] = $conn['host'].'/'.$conn['dbname'].':'.$conn['tbpref'].'*';
278 if ($info[$i]['status'])
280 $info[$i]['version'] = get_company_pref('version_id');
283 set_global_connection();
284 $SysPrefs->refresh();
290 Creates table of installer objects sorted by applicable db scheme version.
292 function get_installers()
294 global $path_to_root;
296 $patchdir = $path_to_root."/sql/";
298 $datadir = @opendir($patchdir);
302 while(false !== ($fname = readdir($datadir)))
303 { // check all php files but index.php
304 if (!is_dir($patchdir . $fname) && ($fname != 'index.php')
305 && stristr($fname, '.php') != false && $fname[0] != '.')
308 include_once($patchdir . $fname);
309 if (isset($install)) // add installer if found
310 $upgrades[$install->previous] = $install;
313 ksort($upgrades); // sort by file name