From: Janusz Dobrowolski Date: Fri, 23 Jan 2015 18:28:46 +0000 (+0100) Subject: Rewritten upgrade procedures, added fa_patch class, utf8 collation can be set before... X-Git-Tag: v2.4.2~19^2~258 X-Git-Url: https://delta.frontaccounting.com/gitweb/?p=fa-stable.git;a=commitdiff_plain;h=1ea749c4abfe081bd7f1b4b11c65a61b311a189e Rewritten upgrade procedures, added fa_patch class, utf8 collation can be set before upgrade. --- diff --git a/admin/backups.php b/admin/backups.php index 2831c131..1168b4f2 100644 --- a/admin/backups.php +++ b/admin/backups.php @@ -16,13 +16,11 @@ include_once($path_to_root . "/includes/session.inc"); include_once($path_to_root . "/includes/ui.inc"); include_once($path_to_root . "/admin/db/maintenance_db.inc"); -define("BACKUP_PATH", $SysPrefs->comp_path.'/'.user_company()."/backup/"); - if (get_post('view')) { if (!get_post('backups')) { display_error(_('Select backup file first.')); } else { - $filename = BACKUP_PATH . clean_file_name(get_post('backups')); + $filename = $SysPrefs->backup_dir().clean_file_name(get_post('backups')); if (in_ajax()) $Ajax->popup( $filename ); else { @@ -36,7 +34,7 @@ if (get_post('view')) { }; if (get_post('download')) { if (get_post('backups')) { - download_file(BACKUP_PATH . clean_file_name(get_post('backups'))); + download_file($SysPrefs->backup_dir().clean_file_name(get_post('backups'))); exit; } else display_error(_("Select backup file first.")); @@ -48,10 +46,12 @@ check_paths(); function check_paths() { - if (!file_exists(BACKUP_PATH)) { + global $SysPrefs; + + if (!file_exists($SysPrefs->backup_dir())) { display_error (_("Backup paths have not been set correctly.") ._("Please contact System Administrator.")."
" - . _("cannot find backup directory") . " - " . BACKUP_PATH . "
"); + . _("cannot find backup directory") . " - " . $SysPrefs->backup_dir() . "
"); end_page(); exit; } @@ -59,7 +59,9 @@ function check_paths() function generate_backup($conn, $ext='no', $comm='') { - $filename = db_backup($conn, $ext, $comm, BACKUP_PATH); + global $SysPrefs; + + $filename = db_backup($conn, $ext, $comm, $SysPrefs->backup_dir()); if ($filename) display_notification(_("Backup successfully generated."). ' ' . _("Filename") . ": " . $filename); @@ -72,11 +74,11 @@ function generate_backup($conn, $ext='no', $comm='') function get_backup_file_combo() { - global $path_to_root, $Ajax; + global $path_to_root, $Ajax, $SysPrefs; $ar_files = array(); default_focus('backups'); - $dh = opendir(BACKUP_PATH); + $dh = opendir($SysPrefs->backup_dir()); while (($file = readdir($dh)) !== false) $ar_files[] = $file; closedir($dh); @@ -127,7 +129,7 @@ function download_file($filename) $conn = $db_connections[user_company()]; $backup_name = clean_file_name(get_post('backups')); -$backup_path = BACKUP_PATH . $backup_name; +$backup_path = $SysPrefs->backup_dir() . $backup_name; if (get_post('creat')) { generate_backup($conn, get_post('comp'), get_post('comments')); @@ -165,7 +167,7 @@ if (get_post('upload')) if (!preg_match("/\.sql(\.zip|\.gz)?$/", $fname)) display_error(_("You can only upload *.sql backup files")); elseif (is_uploaded_file($tmpname)) { - rename($tmpname, BACKUP_PATH . $fname); + rename($tmpname, $SysPrefs->backup_dir() . $fname); display_notification(_("File uploaded to backup directory")); $Ajax->activate('backups'); } else diff --git a/admin/db/company_db.inc b/admin/db/company_db.inc index 3f1718ca..a9834360 100644 --- a/admin/db/company_db.inc +++ b/admin/db/company_db.inc @@ -82,8 +82,9 @@ function set_company_pref($pref, $category, $type, $length, $value) function refresh_sys_prefs() { - flush_dir(user_js_cache()); // clear cache +// flush_dir(user_js_cache()); // clear cache unset($_SESSION['SysPrefs']); + $_SESSION['SysPrefs'] = new sys_prefs(); get_company_prefs(); } diff --git a/admin/includes/fa_patch.class.inc b/admin/includes/fa_patch.class.inc new file mode 100644 index 00000000..631df820 --- /dev/null +++ b/admin/includes/fa_patch.class.inc @@ -0,0 +1,256 @@ +. +***********************************************************************/ + +// +// Utility class contains basic database upgrade routines. +// +class fa_patch { + var $previous; // previous database version + var $version; // version after upgrade + var $description; // short patch description + + var $sql; // basic sql file + + var $cur_company; + var $backup; // pre-upgrade backup filename + + var $errors = array(); + var $ma_upgrade_time = 300; + + function fa_patch() + { + global $path_to_root; + + include $path_to_root."/config_db.php"; + + $this->companies = $db_connections; + + return $this->companies; + } + + /* + Collect/log messages generated during upgrade process. + */ + function log_error($msg, $type='Error') + { + if ($type == 'Error') + $this->errors[] = $msg; + error_log(sprintf('[%s] %s', $type, $msg)); + return false; + } + + /* + Pre-install maintenance: login to company, open upgrade log, make a backup + */ + function pre_install($company) + { + global $SysPrefs; + + $this->cur_company = $company; + $this->errors = array(); + $this->backup = null; + + $this->save_log = ini_set('error_log', dirname(__FILE__).'/../../tmp/upgrade.'.$this->cur_company.'.log'); + $this->log_error(sprintf(_("Upgrade started for company %s."), $this->cur_company), 'Info'); + + if (!set_global_connection($this->cur_company)) + return $this->log_error(_("Cannot connect to company database.")); + + $cur_ver = get_company_pref('version_id', true); + if ($cur_ver != $this->previous) + return $this->log_error(sprintf(_("Cannot upgrade company %s: database version is incompatible ('%s' instead of '%s')."), + $this->cur_company, $cur_ver, $this->previous)); + + if (!$this->prepare()) // fetch params, perform additional checks (if any) + return false; + + if (!$this->sql) + return true; // skip security backup if database content is not changed + + $this->backup = db_backup($this->companies[$this->cur_company], 'no', 'Security backup before upgrade', + $SysPrefs->backup_dir($this->cur_company)); + + if (!$this->backup) + return $this->log_error(_("Security backup failed.")); + + $this->log_error(sprintf(_("Security backup in file %s done."), $this->backup), 'Info'); + return true; + } + + /* + Basic install procedure using sql file. + */ + function sql_install($company, $force=false) + { + global $path_to_root; + + if ($this->sql != '') // perform basic upgrade operations defined in sql file + { + $result = true; + + if ($result === true) + $result = db_import($path_to_root. '/sql/'.$this->sql, $this->companies[$company], + $force, true, false, true); + + if ($result !== true) + { + if (is_array($result)) + { + foreach($result as $err) + $this->log_error($err[1] . ':'. $err[0]); + } else + { + $this->log_error($result); + unset($this->backup); // prevent restore (database was not touched due to other errors) + } + return false; + } + } + return true; + } + + /* + Post install procedures: update database version, or restore databse from backup file in case of errors + */ + function post_install($result=true) + { + global $db_version; + + if ($result !== true) + { + if ($this->backup) + { + if (!set_global_connection($this->cur_company)) // reset connection to clear encoding + return $this->log_error(_("Cannot connect to company database for database restore.")); + + set_time_limit($this->max_upgrade_time); + $result = db_import($this->backup, $this->companies[$this->cur_company], true, false); + if ($result) + $this->log_error(_("Upgrade failed. Original database content restored successfully."), 'Info'); + else + $thi->log_error(sprintf(_("Database restore operation failed. Original database content is in %s file."), $this->backup)); + $this->post_fail($this->cur_company); + } + } else { + update_company_prefs(array('version_id' => $this->version)); + } + + $this->log_error(sprintf(_("Upgrade for company %s finished."), $this->cur_company), 'Info'); + + set_global_connection(); + ini_set('error_log', $this->save_log); + + if (db_fixed()) + db_set_encoding(); + + return $result; + } + + /* + Main routine for single company upgrade. + */ + function upgrade_company($comp, $force=false) + { + $result = $this->pre_install($comp) && $this->sql_install($comp, $force) && $this->install($comp, $force); + + $this->post_install($result); + + return count($this->errors) == 0; + } + + /* + Additional version specific php/sql upgrade procedures. + This procedure is performed after basic sql upgrade script is run. + */ + function install($company, $force=false) + { + return true; + } + /* + Optional cleanup procedure. + This procedure is run in case of upgrade failure, before the backup is restored. + */ + function post_fail($company) + { + } + + /* + Present upgrade parameters to administrator + This function presents upgrade choices, after selection company to be upgraded. + */ + function show_params($comp) + { + } + + /* + Fetch & check upgrade parameters, check additional upgrade pre-conditions. + This function is run after successfull switching to target database connection. + */ + function prepare() + { + return true; + } + +} + +/* + Return databases status info. +*/ +function get_site_status($connections) +{ + $info = array(); + + foreach($connections as $i => $conn) + { + $info[$i]['status'] = set_global_connection($i) !== false; + + $info[$i]['name'] = $conn['name']; + $info[$i]['table_set'] = $conn['host'].'/'.$conn['dbname'].':'.$conn['tbpref'].'*'; + if ($info[$i]['status']) + { + $info[$i]['version'] = get_company_pref('version_id'); + } + } + set_global_connection(); + refresh_sys_prefs(); + + return $info; +} + +/* + Creates table of installer objects sorted by applicable db scheme version. +*/ +function get_installers() +{ + global $path_to_root; + + $patchdir = $path_to_root."/sql/"; + $upgrades = array(); + $datadir = @opendir($patchdir); + + if ($datadir) + { + while(false !== ($fname = readdir($datadir))) + { // check all php files but index.php + if (!is_dir($patchdir . $fname) && ($fname != 'index.php') + && stristr($fname, '.php') != false && $fname[0] != '.') + { + unset($install); + include_once($patchdir . $fname); + if (isset($install)) // add installer if found + $upgrades[$install->previous] = $install; + } + } + ksort($upgrades); // sort by file name + } + return $upgrades; +} diff --git a/admin/includes/index.php b/admin/includes/index.php new file mode 100644 index 00000000..e88dc9ed --- /dev/null +++ b/admin/includes/index.php @@ -0,0 +1,2 @@ +use_popup_windows) { $js = get_js_open_window(900, 500); } -page(_($help_context = "Install/Activate extensions")); +page(_($help_context = "Install/Activate extensions"), false, false, "", $js); include_once($path_to_root . "/includes/date_functions.inc"); include_once($path_to_root . "/admin/db/company_db.inc"); diff --git a/admin/inst_upgrade.php b/admin/inst_upgrade.php index 16eee5a7..948594f8 100644 --- a/admin/inst_upgrade.php +++ b/admin/inst_upgrade.php @@ -13,168 +13,107 @@ $page_security = 'SA_SOFTWAREUPGRADE'; $path_to_root=".."; include_once($path_to_root . "/includes/session.inc"); -page(_($help_context = "Software Upgrade")); +if ($SysPrefs->use_popup_windows) { + $js = get_js_open_window(900, 500); +} +page(_($help_context = "Software Upgrade"), false, false, "", $js); include_once($path_to_root . "/includes/date_functions.inc"); include_once($path_to_root . "/admin/db/company_db.inc"); include_once($path_to_root . "/admin/db/maintenance_db.inc"); include_once($path_to_root . "/includes/ui.inc"); +include_once($path_to_root . "/admin/includes/fa_patch.class.inc"); + +$site_status = get_site_status($db_connections); +$installers = get_installers(); -// -// Creates table of installer objects sorted by version. -// -function get_installers() +if (get_post('Upgrade')) { - global $path_to_root; + $comp = get_post('select_comp'); - $patchdir = $path_to_root."/sql/"; - $upgrades = array(); - $datadir = @opendir($patchdir); + if ($comp === '') + display_error(_('Select company to be upgraded.')); + else { + $patch = @$installers[$site_status[$comp]['version']]; + if ($patch) + { + if (!$patch->upgrade_company($comp, check_value('force'))) + display_error(implode('
', $patch->errors)); + else + display_notification(_("Company upgraded successfully.")); - if ($datadir) - { - while(false !== ($fname = readdir($datadir))) - { // check all php files but index.php - if (!is_dir($patchdir . $fname) && ($fname != 'index.php') - && stristr($fname, '.php') != false && $fname[0] != '.') - { - unset($install); - include_once($patchdir . $fname); - if (isset($install)) // add installer if found - $upgrades[$install->version] = $install; - } + $site_status = get_site_status($db_connections); // update info + $Ajax->activate('_page_body'); } - ksort($upgrades); // sort by file name - $upgrades = array_values($upgrades); } - return $upgrades; } -// -// Apply one differential data set. -// -function upgrade_step($inst, $company, $conn, $force) +$i = find_submit('Clear'); +if ($i != -1) { - global $path_to_root; - - $pref = $conn['tbpref']; - $ret = true; + unlink($path_to_root.'/tmp/upgrade.'.$i.'.log'); + $Ajax->activate('_page_body'); +} +if (get_post('_select_comp_update')) +{ + $Ajax->activate('_page_body'); +} - $state = $inst->installed($pref); - if (!$state || $force) - { - if (!$inst->pre_check($pref, $force)) return false; - $sql = $inst->sql; +start_form(); - error_log(sprintf(_("Database upgrade for company '%s' (%s:%s*) started..."), - $conn['name'], $conn['dbname'], $conn['tbpref'])); +$th = array(_("Company"), _("Table set"), _("Current version"), _("Last log"), _('Upgrade')); +start_table(TABLESTYLE); +table_header($th); - if ($sql != '') - $ret &= db_import($path_to_root.'/sql/'.$sql, $conn, $force, true); +$uptodate = true; +foreach($site_status as $i => $comp) +{ + $status = $comp['version']==$db_version; - $ret &= $inst->install($company, $force); + alt_table_row_color($k); - if (!$ret && is_callable(array($inst, 'post_fail'))) - $inst->post_fail($pref); + label_cell($comp['name']); + label_cell($comp['table_set']); - error_log(_("Database upgrade finished.")); - } else - if ($state!==true) { - display_error(_("Upgrade cannot be done because database has been already partially upgraded. Please downgrade database to clean previous version or try forced upgrade.")); - $ret = false; - } - return $ret; -} + label_cell($comp['version'], 'align=center' .($status ? '':' class=redfg')/*, 'class='.( $status ? 'ok' : 'error')*/); -$installers = get_installers(); + $log = $path_to_root.'/tmp/upgrade.'.$i.'.log'; + if (file_exists($log)) + { + label_cell(viewer_link(_('View log'), "admin/view/view_upgrade_log.php?id=$i", null, $i, 'log.png') + .button('Clear'.$i, _('Clear'), _('Clear log'), ICON_DELETE), 'align=center'); + submit_js_confirm('Clear'.$i, _("Do you really want to clear this upgrade log?")); + } else + label_cell('-', 'align=center'); -if (get_post('Upgrade')) -{ - $ret = true; - foreach ($db_connections as $comp => $conn) + if (!$status) { - // connect to database - if (!(set_global_connection($comp))) - { - display_error(_("Cannot connect to database for company") - ." '".$conn['name']."'"); - continue; - } - // create security backup - db_backup($conn, 'no', 'Security backup before upgrade'); - // apply all upgrade data - foreach ($installers as $i => $inst) - { - - $force = get_post('force_'.$i); - if ($force || get_post('install_'.$i)) - $ret = upgrade_step($installers[$i], $comp, $conn, $force); - - if (!$ret) - { - display_error( - sprintf(_("Database upgrade to version %s failed for company '%s'."), - $inst->version, $conn['name']) - .'
' - ._('You should restore company database from latest backup file')); - } - } -// db_close($conn); ? - if (!$ret) break; - } - set_global_connection(); - if($ret) - { // re-read the prefs - global $path_to_root; - include_once($path_to_root . "/admin/db/users_db.inc"); - $user = get_user_by_login($_SESSION["wa_current_user"]->username); - $_SESSION["wa_current_user"]->prefs = new user_prefs($user); - display_notification(_('All companies data has been successfully updated')); - } - refresh_sys_prefs(); // re-read system setup - $Ajax->activate('_page_body'); + label_cell(radio(null, 'select_comp', $i, null, true), 'align=center'); + $uptodate = false; + } else + label_cell(_('Up to date')); + end_row(); } -start_form(); -start_table(TABLESTYLE); -$th = array(_("Version"), _("Description"), _("Sql file"), _("Install"), - _("Force upgrade")); -table_header($th); +end_table(); +br(); -$k = 0; //row colour counter -$partial = 0; -foreach($installers as $i => $inst) +div_start('upgrade_args'); +if (get_post('select_comp') !== '') { - alt_table_row_color($k); - start_row(); - label_cell($inst->version); - label_cell($inst->description); - label_cell($inst->sql ? $inst->sql : ''._('None').'', 'align=center'); -// this is checked only for first (site admin) company, -// but in fact we should always upgrade all data sets after -// source upgrade. - $check = $inst->installed(TB_PREF); - if ($check === true) - label_cell(_("Installed")); - else - if (!$check) - check_cells(null,'install_'.$i, 0); - else { - label_cell("" - . sprintf(_("Partially installed (%s)"), $check) . ""); - $partial++; - } - - check_cells(null,'force_'.$i, 0); - end_row(); + $patch = @$installers[$site_status[get_post('select_comp')]['version']]; + if ($patch) + $patch->show_params(get_post('select_comp')); } -end_table(1); -if ($partial!=0) { - display_note(_("Database upgrades marked as partially installed cannot be installed automatically. -You have to clean database manually to enable them, or try to perform forced upgrade.")); - br(); +div_end(); + +if ($uptodate) + display_note(_('All company database schemes are up to date.')); +else { + if (get_post('select_comp') === '') + display_note(_("Select company for incremental upgrade."), 0, 1, "class='stockmankofg'"); + submit_center('Upgrade', _('Upgrade'), true, _('Save database and perform upgrade'), 'process'); } -submit_center('Upgrade', _('Upgrade system'), true, _('Save database and perform upgrade'), 'process'); end_form(); end_page(); diff --git a/admin/view/view_upgrade_log.php b/admin/view/view_upgrade_log.php new file mode 100644 index 00000000..e1cbd0f4 --- /dev/null +++ b/admin/view/view_upgrade_log.php @@ -0,0 +1,38 @@ +. +***********************************************************************/ +$page_security = 'SA_SOFTWAREUPGRADE'; +$path_to_root = "../.."; +include_once($path_to_root . "/includes/session.inc"); +include_once($path_to_root . "/includes/packages.inc"); + +page(_($help_context = "Log View"), true); + +include_once($path_to_root . "/includes/ui.inc"); + +if (!isset($_GET['id'])) +{ + /*Script was not passed the correct parameters */ + display_note(_("The script must be called with a valid company number.")); + end_page(); +} + +display_heading(sprintf(_("Upgrade log for company '%s'"), $_GET['id'])); +br(); + start_table(); + start_row(); + + $log = strtr(file_get_contents($path_to_root.'/tmp/upgrade.'.$_GET['id'].'.log'), + array('Fatal error' => 'Fatal error')); // prevent misinterpretation in output_handler + label_cells(null, nl2br(html_specials_encode($log))); + end_row(); + end_table(1); +end_page(true); diff --git a/config.default.php b/config.default.php index 02075ef5..57ac00c3 100644 --- a/config.default.php +++ b/config.default.php @@ -91,7 +91,7 @@ if (!isset($path_to_root) || isset($_GET['path_to_root']) || isset($_POST['path_ $help_base_url = null; /* per user data/cache directory */ - $comp_path = $path_to_root.'/company'; + $comp_path = dirname(__FILE__).'/company'; /* Date systems. 0 = traditional, 1 = Jalali used by Iran, nabour countries, Afghanistan and some other Central Asian nations, 2 = Islamic used by other arabic nations. 3 = traditional, but where non-workday is Friday and start of week is Saturday */ @@ -200,3 +200,8 @@ if (!isset($path_to_root) || isset($_GET['path_to_root']) || isset($_POST['path_ */ $clear_trial_balance_opening = false; +/* + Optional backup path. Use %s in place of company number. + If not defined $comp_path/%s/backup/ is used. +*/ +// $backup_path = dirname(__FILE__).'/company/%s/backup/'; diff --git a/includes/db/connect_db.inc b/includes/db/connect_db.inc index 98a18f59..a689946b 100644 --- a/includes/db/connect_db.inc +++ b/includes/db/connect_db.inc @@ -90,7 +90,7 @@ function get_mysql_collation($lang=null) 'it' => 'roman', ); - return 'utf8_'.(isset($db_collation[$lang]) ? $db_collation[$lang] : 'general').'_ci'; + return 'utf8_'.(isset($db_collation[$lang]) ? $db_collation[$lang] : 'unicode').'_ci'; } /* diff --git a/includes/db/connect_db_mysqli.inc b/includes/db/connect_db_mysqli.inc index 7359a85c..45439f04 100644 --- a/includes/db/connect_db_mysqli.inc +++ b/includes/db/connect_db_mysqli.inc @@ -37,6 +37,7 @@ function set_global_connection($company=-1) ///// We are, however, investigating the existing code to be compatible in the future. db_query("SET sql_mode = '".SQL_MODE."'"); ///// + refresh_sys_prefs(); return $db; } diff --git a/includes/prefs/sysprefs.inc b/includes/prefs/sysprefs.inc index ee3fa70b..0ff68cbd 100644 --- a/includes/prefs/sysprefs.inc +++ b/includes/prefs/sysprefs.inc @@ -145,5 +145,16 @@ class sys_prefs { return $this->prefs['suppress_tax_rates']; } + + function backup_dir($comp=null) + { + if (!isset($comp)) + $comp = user_company(); + + if (isset($this->backup_path)) + return sprintf($this->backup_path, $comp); + else + return $this->comp_path.'/'.$comp."/backup/"; + } } diff --git a/includes/ui/ui_input.inc b/includes/ui/ui_input.inc index b3cb79b1..86203285 100644 --- a/includes/ui/ui_input.inc +++ b/includes/ui/ui_input.inc @@ -387,7 +387,7 @@ function check_row($label, $name, $value=null, $submit_on_change=false, $title=f function radio($label, $name, $value, $selected=null, $submit_on_change=false) { if (!isset($selected)) - $selected = get_post($name) == $value; + $selected = get_post($name) === (string)$value; if ($submit_on_change === true) $submit_on_change = diff --git a/includes/ui/view_package.php b/includes/ui/view_package.php index dee8a2f9..6d957720 100644 --- a/includes/ui/view_package.php +++ b/includes/ui/view_package.php @@ -51,7 +51,7 @@ foreach ($pkg as $field => $value) { if ($value == '') continue; start_row(); - label_cells($field, nl2br(htmlentities(is_array($value) ? implode("\n", $value) :$value)), + label_cells($field, nl2br(html_specials_encode(is_array($value) ? implode("\n", $value) :$value)), "class='tableheader2'"); end_row(); } diff --git a/sql/alter2.1.php b/sql/alter2.1.php index cd8eb865..a70f15a3 100644 --- a/sql/alter2.1.php +++ b/sql/alter2.1.php @@ -9,7 +9,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License here . ***********************************************************************/ -class fa2_1 { +class fa2_1 extends fa_patch { + var $previous = ''; // applicable database version var $version = '2.1'; // version installed var $description; var $sql = 'alter2.1.sql'; @@ -21,7 +22,7 @@ class fa2_1 { // Install procedure. All additional changes // not included in sql file should go here. // - function install($company, $force) + function install($company, $force=false) { global $db; @@ -128,13 +129,16 @@ class fa2_1 { return true; } + // // Checking before install // - function pre_check($pref) + function prepare() { // We cannot perform successfull upgrade on system where the - // trans tax details tables was deleted during previous try. + // trans tax details tables was deleted during previous try. + $pref = $this->companies[$company]['tbpref']; + if (check_table($pref, 'debtor_trans_tax_details') || check_table($pref, 'supp_invoice_tax_items')) { display_error(_("Seems that system upgrade to version 2.1 has @@ -143,23 +147,10 @@ class fa2_1 { database restore from last backup file first.")); return false; - } + } return true; // true when ok, fail otherwise } - // - // Test if patch was applied before. - // - function installed($pref) { - $n = 4; // number of features to be installed - if (!check_table($pref, 'item_codes')) $n--; -// if (!check_table($pref, 'company', 'foreign_codes')) $n--; - if (!check_table($pref, 'suppliers', 'credit_limit')) $n--; - if (!check_table($pref, 'bank_trans', 'reconciled', - array('Type'=>'date'))) $n--; - if (!check_table($pref, 'trans_tax_details')) $n--; - return $n == 0 ? true : 5 - $n; - } }; $install = new fa2_1; diff --git a/sql/alter2.2.php b/sql/alter2.2.php index 981079fe..837f44ce 100644 --- a/sql/alter2.2.php +++ b/sql/alter2.2.php @@ -10,12 +10,13 @@ See the License here . ***********************************************************************/ -class fa2_2 { - var $version = '2.2'; // version installed +class fa2_2 extends fa_patch { + var $previous = '2.1'; // applicable database version + var $version = '2.2rc'; // version installed var $description; var $sql = 'alter2.2.sql'; var $preconf = true; - var $beta = false; // upgrade from 2.1 or 2.2beta; set in pre_check + var $beta = false; // upgrade from 2.1 or 2.2beta; set in prepare() function fa2_2() { global $security_groups; @@ -28,10 +29,10 @@ class fa2_2 { // Install procedure. All additional changes // not included in sql file should go here. // - function install($company, $force) + function install($company, $force=false) { global $db, $systypes_array, $db_connections; - + if (!$this->preconf) return false; @@ -101,48 +102,17 @@ class fa2_2 { // // Checking before install // - function pre_check($pref, $force) - { + function prepare() + { global $security_groups; - - if ($this->beta && !$force) + + if ($this->beta) $this->sql = 'alter2.2rc.sql'; // return ok when security groups still defined (upgrade from 2.1) // or usersonline not defined (upgrade from 2.2 beta) - return isset($security_groups) || (check_table($pref, 'usersonline')!=0); - } - // - // Test if patch was applied before. - // - function installed($pref) { - $n = 1; // number of patches to be installed - $patchcnt = 0; - if (!$this->beta) { - $n = 16; - if (check_table($pref, 'company')) // skip in 2.3 - $n -= 3; - else { - if (check_table($pref, 'company', 'custom1_name')) $patchcnt++; - if (!check_table($pref, 'company', 'profit_loss_year_act')) $patchcnt++; - if (!check_table($pref, 'company', 'login_tout')) $patchcnt++; - } - if (!check_table($pref, 'stock_category', 'dflt_no_sale')) $patchcnt++; - if (!check_table($pref, 'users', 'sticky_doc_date')) $patchcnt++; - if (!check_table($pref, 'users', 'startup_tab')) $patchcnt++; - if (!check_table($pref, 'cust_branch', 'inactive')) $patchcnt++; - if (!check_table($pref, 'chart_class', 'ctype')) $patchcnt++; - if (!check_table($pref, 'audit_trail')) $patchcnt++; - if (!check_table($pref, 'currencies', 'auto_update')) $patchcnt++; - if (!check_table($pref, 'stock_master','no_sale')) $patchcnt++; - if (!check_table($pref, 'suppliers', 'supp_ref')) $patchcnt++; - if (!check_table($pref, 'users', 'role_id')) $patchcnt++; - if (!check_table($pref, 'sales_orders', 'reference')) $patchcnt++; - if (!check_table($pref, 'tags')) $patchcnt++; - } - if (!check_table($pref, 'useronline')) $patchcnt++; + $pref = $this->companies[$company]['tbpref']; - $n -= $patchcnt; - return $n == 0 ? true : $patchcnt; + return isset($security_groups) || (check_table($pref, 'usersonline')!=0); } }; diff --git a/sql/alter2.3.php b/sql/alter2.3.php index 0fa5e260..f186ff62 100644 --- a/sql/alter2.3.php +++ b/sql/alter2.3.php @@ -9,8 +9,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License here . ***********************************************************************/ -class fa2_3 { - var $version = '2.3'; // version installed +class fa2_3 extends fa_patch { + var $previous = '2.2rc'; // applicable database version + var $version = '2.3rc'; // version installed var $description; var $sql = 'alter2.3.sql'; var $preconf = true; @@ -24,7 +25,7 @@ class fa2_3 { // Install procedure. All additional changes // not included in sql file should go here. // - function install($company, $force) + function install($company, $force=false) { global $db_version, $dflt_lang; @@ -98,36 +99,19 @@ class fa2_3 { // // Checking before install // - function pre_check($pref, $force) + function prepare() { - if ($this->beta && !$force) + if ($this->beta) $this->sql = 'alter2.3rc.sql'; return true; } - // - // Test if patch was applied before. - // - function installed($pref) { - $this->beta = !check_table($pref, 'suppliers', 'tax_included'); - - $n = 1; // number of patches to be installed - $patchcnt = 0; - if (!$this->beta) { - $n += 3; - if (!check_table($pref, 'comments', 'type', array('Key'=>'MUL'))) $patchcnt++; - if (!check_table($pref, 'sys_prefs')) $patchcnt++; - if (!check_table($pref, 'sales_orders', 'payment_terms')) $patchcnt++; - } - if (!check_table($pref, 'purch_orders', 'tax_included')) $patchcnt++; - return $n == $patchcnt ? true : ($patchcnt ? ($patchcnt.'/'. $n) : 0); - } //========================================================================================= // 2.3 specific update functions // - + /* Update order totals */ @@ -264,11 +248,11 @@ class fa2_3 { } return true; } - + function fix_extensions() { global $path_to_root, $next_extension_id, $installed_languages; - + $lang_chd = false; foreach($installed_languages as $i => $lang) { if (!isset($lang['path'])) { @@ -281,15 +265,14 @@ class fa2_3 { if ($lang_chd) write_lang(); - $installed_extensions= get_company_extensions(); if (!isset($next_extension_id)) $next_extension_id = 1; $new_exts = array(); - + /* Old extension modules are uninstalled - they need manual porting after heavy changes in extension system in FA2.3 - + foreach($installed_extensions as $i => $ext) { if (isset($ext['title'])) // old type entry diff --git a/sql/alter2.4.php b/sql/alter2.4.php index c51f1996..7fc60b38 100644 --- a/sql/alter2.4.php +++ b/sql/alter2.4.php @@ -9,21 +9,81 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License here . ***********************************************************************/ -class fa2_4 { +function collations_list_row($label, $name, $selected_id=null) +{ + +$mysql_collations = array( + 'xx' => 'Unicode (multilanguage)', + 'is' => 'Icelandic', + 'lv' => 'Latvian', + 'ro' => 'Romanian', + 'sl' => 'Slovenian', + 'pl' => 'Polish', + 'et' => 'Estonian', + 'es' => 'Spanish', // or 'spanish2', + 'sw' => 'Swedish', + 'tr' => 'Turkish', + 'cs' => 'Czech', + 'da' => 'Danish', + 'lt' => 'Lithuanian', + 'sk' => 'Slovak', + 'sp' => 'Spanish (alternative)', + 'fa' => 'Persian', + 'hu' => 'Hungarian', + 'fr' => 'French', + 'it' => 'Italian', +); + + echo ""; + if ($label != null) + echo "$label\n"; + echo ""; + + echo array_selector($name, $selected_id, $mysql_collations, + array('select_submit'=> false) ); + echo "\n"; +} + +class fa2_4 extends fa_patch { + var $previous = '2.3rc'; // applicable database version var $version = '2.4.0'; // version installed var $description; var $sql = 'alter2.4.sql'; var $preconf = true; function fa2_4() { + parent::fa_patch(); $this->description = _('Upgrade from version 2.3 to 2.4'); } + /* + Shows parameters to be selected before upgrade (if any) + */ + function show_params($comp) + { + display_note(_('Set optimal parameters and start upgrade:')); + start_table(TABLESTYLE); + start_row(); + collations_list_row(_('Text collation optimization:'), 'collation', substr($_SESSION['language']->code, 0, 2)); + end_row(); + end_table(); + br(); + } + + /* + Fetches selected upgrade parameters. + */ + function prepare() + { + $this->collation = get_mysql_collation(get_post('collation')); + return true; + } + // // Install procedure. All additional changes // not included in sql file should go here. // - function install($company, $force=false) + function install($company, $force=false) { global $db_version, $db_connections; @@ -50,49 +110,17 @@ class fa2_4 { if ($result) $result = $this->do_cleanup(); - //remove obsolete and temporary columns. - // this have to be done here as db_import rearranges alter query order - $dropcol = array( - 'cust_branch' => array('contact_name', 'disable_trans'), - ); - - foreach($dropcol as $table => $columns) - foreach($columns as $col) { - if (db_query("ALTER TABLE `".TB_PREF."{$table}` DROP `$col`")==false) { - display_error("Cannot drop {$table}.{$col} column:
".db_error_msg($db)); - return false; - } - } - - return update_company_prefs(array('version_id'=>$db_version)); - } - // - // Checking before install - // - function pre_check($pref, $force) - { - return true; + return $result; } // // optional procedure done after upgrade fail, before backup is restored // - function post_fail($pref) + function post_fail($company) { + $pref = $this->companies[$company]['tbpref']; db_query("DROP TABLE IF EXISTS " . $pref . 'wo_costing'); } - // - // Test if patch was applied before. - // - function installed($pref) - { - $n = 2; // number of patches to be installed - $patchcnt = 0; - - if (!check_table($pref, 'suppliers', 'tax_algorithm')) $patchcnt++; - if (!check_table($pref, 'wo_costing')) $patchcnt++; - return $n == $patchcnt ? true : ($patchcnt ? ($patchcnt.'/'. $n) : 0); - } function update_workorders() { @@ -102,11 +130,8 @@ class fa2_4 { ." AND person_type_id=1"; $res = db_query($sql); if (!$res) - { - display_error("Cannot update work orders costs" - .':
'. db_error_msg($db)); - return false; - } + return $this->log_error(sprintf(_("Cannot update work orders costs:\n%s"), db_error_msg($db))); + while ($row = db_fetch($res)) { $journal_id = get_next_trans_no(ST_JOURNAL); @@ -116,7 +141,7 @@ class fa2_4 { WHERE `type`=".ST_WORKORDER." AND type_no={$row['type_no']} AND tran_date='{$row['tran_date']}' AND person_id='{$row['person_id']}'"; if (!db_query($sql1)) return false; - + $sql2 = "INSERT INTO ".TB_PREF."wo_costing (workorder_id, cost_type, trans_no) VALUES ({$row['type_no']}, {$row['person_id']}, {$journal_id})"; if (!db_query($sql2)) return false; @@ -135,9 +160,9 @@ class fa2_4 { . for all text/char column: - suppress autorecoding by change of the type to related binary/blob type - change column to utf8 encodding and selected collation. - . change default table encoding to utf8 + . change default table encoding to utf8 and selected collation */ - function switch_database_to_utf($pref, $test = false) { + function switch_database_to_utf($pref, $dbg = false) { global $installed_languages, $dflt_lang; @@ -147,9 +172,8 @@ class fa2_4 { $lang = array_search_value($dflt_lang, $installed_languages, 'code'); $new_encoding = get_mysql_encoding_name(strtoupper($lang['encoding'])); - if ($test) - error_log('Switching database to utf8 encoding from '.$old_encoding); - $collation = get_mysql_collation(); + $this->log_error(sprintf('Switching database to utf8 encoding from %s', $old_encoding), 'Info'); + $collation = $this->collation; $tsql = "SHOW TABLES LIKE '".($pref=='' ? '' : substr($pref, 0, -1).'\\_')."%'"; $tresult = db_query($tsql, "Cannot select all tables with prefix '$pref'"); while($tbl = db_fetch($tresult)) { @@ -170,8 +194,8 @@ class fa2_4 { if ($bintype != $col['Type']) { // this is char/text column, so change encoding to proper encoding - if ($test) - error_log($table.'.'.$col['Field']); + if ($dbg) + $this->log_error(sprintf('%s switched to uft8.', $table.'.'.$col['Field']), 'Debug'); $null = $col['Null'] === 'YES' ? ' NULL ' : ' NOT NULL '; $default = $col['Null'] !== 'YES' && isset($col['Default']) ? ' DEFAULT '.db_escape($col['Default']) : ''; @@ -196,8 +220,7 @@ class fa2_4 { db_query("ALTER TABLE `$table` COLLATE $collation"); } db_query("ALTER DATABASE COLLATE $collation"); - if ($test) - error_log('Convertion to utf8 done.'); + $this->log_error(_('Convertion to utf8 done.'), 'Info'); return true; } @@ -221,19 +244,24 @@ class fa2_4 { function do_cleanup() { + global $db; + + //remove obsolete and temporary columns. + // this have to be done here as db_import rearranges alter query order $dropcol = array( 'tax_group_items' => array('rate'), 'budget_trans' => array('type', 'type_no', 'person_id', 'person_type_id', 'memo_'), + 'cust_branch' => array('contact_name', 'disable_trans'), ); foreach($dropcol as $table => $columns) foreach($columns as $col) { if (db_query("ALTER TABLE `".TB_PREF."{$table}` DROP `$col`") == false) { - display_error("Cannot drop {$table}.{$col} column:
".db_error_msg($db)); - return false; + return $this->log_error(sprintf(_("Cannot drop column in %s table: %s"), $table, db_error_msg($db))); } } - } + return true; + } } $install = new fa2_4; diff --git a/themes/aqua/images/log.png b/themes/aqua/images/log.png new file mode 100644 index 00000000..ef03a4de Binary files /dev/null and b/themes/aqua/images/log.png differ diff --git a/themes/cool/images/log.png b/themes/cool/images/log.png new file mode 100644 index 00000000..ef03a4de Binary files /dev/null and b/themes/cool/images/log.png differ diff --git a/themes/default/images/log.png b/themes/default/images/log.png new file mode 100644 index 00000000..ef03a4de Binary files /dev/null and b/themes/default/images/log.png differ