diff --git a/workflow/engine/classes/class.applications.php b/workflow/engine/classes/class.applications.php index 9faf36b8f..1e56c53ac 100644 --- a/workflow/engine/classes/class.applications.php +++ b/workflow/engine/classes/class.applications.php @@ -154,7 +154,7 @@ class Applications $Criteria->add( AppCacheViewPeer::DEL_DELEGATE_DATE, $dateFrom, Criteria::GREATER_EQUAL ); $CriteriaCount->add( AppCacheViewPeer::DEL_DELEGATE_DATE, $dateFrom, Criteria::GREATER_EQUAL ); } - } else if ($dateTo != '') { + } elseif ($dateTo != '') { $Criteria->add( AppCacheViewPeer::DEL_DELEGATE_DATE, $dateTo, Criteria::LESS_EQUAL ); $CriteriaCount->add( AppCacheViewPeer::DEL_DELEGATE_DATE, $dateTo, Criteria::LESS_EQUAL ); } diff --git a/workflow/engine/classes/class.archive.php b/workflow/engine/classes/class.archive.php index 7419ca6c2..746c3baab 100755 --- a/workflow/engine/classes/class.archive.php +++ b/workflow/engine/classes/class.archive.php @@ -79,15 +79,16 @@ class archive $this->error[] = "File {$this->options['name']} already exist."; chdir( $pwd ); return 0; - } else if ($this->archive = @fopen( $this->options['name'] . ($this->options['type'] == "gzip" || $this->options['type'] == "bzip" ? ".tmp" : ""), "wb+" )) { + } elseif ($this->archive = @fopen( $this->options['name'] . ($this->options['type'] == "gzip" || $this->options['type'] == "bzip" ? ".tmp" : ""), "wb+" )) { chdir( $pwd ); } else { $this->error[] = "Could not open {$this->options['name']} for writing."; chdir( $pwd ); return 0; } - } else + } else { $this->archive = ""; + } switch ($this->options['type']) { case "zip": if (! $this->create_zip()) { @@ -139,8 +140,7 @@ class archive { if ($this->options['inmemory'] == 0) { fwrite( $this->archive, $data ); - } - else { + } else { $this->archive .= $data; } } @@ -152,16 +152,24 @@ class archive */ public function make_list () { - if (! empty( $this->exclude )) - foreach ($this->files as $key => $value) - foreach ($this->exclude as $current) - if ($value['name'] == $current['name']) + if (! empty( $this->exclude )) { + foreach ($this->files as $key => $value) { + foreach ($this->exclude as $current) { + if ($value['name'] == $current['name']) { unset( $this->files[$key] ); - if (! empty( $this->storeonly )) - foreach ($this->files as $key => $value) - foreach ($this->storeonly as $current) - if ($value['name'] == $current['name']) + } + } + } + } + if (! empty( $this->storeonly )) { + foreach ($this->files as $key => $value) { + foreach ($this->storeonly as $current) { + if ($value['name'] == $current['name']) { $this->files[$key]['method'] = 0; + } + } + } + } unset( $this->exclude, $this->storeonly ); } @@ -174,8 +182,9 @@ class archive public function add_files ($list) { $temp = $this->list_files( $list ); - foreach ($temp as $current) + foreach ($temp as $current) { $this->files[] = $current; + } } /** @@ -187,8 +196,9 @@ class archive public function exclude_files ($list) { $temp = $this->list_files( $list ); - foreach ($temp as $current) + foreach ($temp as $current) { $this->exclude[] = $current; + } } /** @@ -199,8 +209,9 @@ class archive public function store_files ($list) { $temp = $this->list_files( $list ); - foreach ($temp as $current) + foreach ($temp as $current) { $this->storeonly[] = $current; + } } /** @@ -229,18 +240,22 @@ class archive $regex = str_replace( "*", ".*", $regex ); $dir = strstr( $current, "/" ) ? substr( $current, 0, strrpos( $current, "/" ) ) : "."; $temp = $this->parse_dir( $dir ); - foreach ($temp as $current2) - if (preg_match( "/^{$regex}$/i", $current2['name'] )) + foreach ($temp as $current2) { + if (preg_match( "/^{$regex}$/i", $current2['name'] )) { $files[] = $current2; + } + } unset( $regex, $dir, $temp, $current ); - } else if (@is_dir( $current )) { + } elseif (@is_dir( $current )) { $temp = $this->parse_dir( $current ); - foreach ($temp as $file) + foreach ($temp as $file) { $files[] = $file; + } unset( $temp, $file ); - } else if (@file_exists( $current )) + } elseif (@file_exists( $current )) { $files[] = array ('name' => $current,'name2' => $this->options['prepend'] . preg_replace( "/(\.+\/+)+/", "", ($this->options['storepaths'] == 0 && strstr( $current, "/" )) ? substr( $current, strrpos( $current, "/" ) + 1 ) : $current ),'type' => @is_link( $current ) && $this->options['followlinks'] == 0 ? 2 : 0,'ext' => substr( $current, strrpos( $current, "." ) ),'stat' => stat( $current ) ); + } } chdir( $pwd ); unset( $current, $pwd ); @@ -257,26 +272,30 @@ class archive */ public function parse_dir ($dirname) { - if ($this->options['storepaths'] == 1 && ! preg_match( "/^(\.+\/*)+$/", $dirname )) + if ($this->options['storepaths'] == 1 && ! preg_match( "/^(\.+\/*)+$/", $dirname )) { $files = array (array ('name' => $dirname,'name2' => $this->options['prepend'] . preg_replace( "/(\.+\/+)+/", "", ($this->options['storepaths'] == 0 && strstr( $dirname, "/" )) ? substr( $dirname, strrpos( $dirname, "/" ) + 1 ) : $dirname ),'type' => 5,'stat' => stat( $dirname ) ) ); - else + } else { $files = array (); + } $dir = @opendir( $dirname ); while ($file = @readdir( $dir )) { $fullname = $dirname . "/" . $file; - if ($file == "." || $file == "..") + if ($file == "." || $file == "..") { continue; - else if (@is_dir( $fullname )) { - if (empty( $this->options['recurse'] )) + } elseif (@is_dir( $fullname )) { + if (empty( $this->options['recurse'] )) { continue; + } $temp = $this->parse_dir( $fullname ); - foreach ($temp as $file2) + foreach ($temp as $file2) { $files[] = $file2; - } else if (@file_exists( $fullname )) + } + } elseif (@file_exists( $fullname )) { $files[] = array ('name' => $fullname,'name2' => $this->options['prepend'] . preg_replace( "/(\.+\/+)+/", "", ($this->options['storepaths'] == 0 && strstr( $fullname, "/" )) ? substr( $fullname, strrpos( $fullname, "/" ) + 1 ) : $fullname ),'type' => @is_link( $fullname ) && $this->options['followlinks'] == 0 ? 2 : 0,'ext' => substr( $file, strrpos( $file, "." ) ),'stat' => stat( $fullname ) ); + } } @closedir( $dir ); return $files; @@ -291,19 +310,21 @@ class archive */ public function sort_files ($a, $b) { - if ($a['type'] != $b['type']) - if ($a['type'] == 5 || $b['type'] == 2) + if ($a['type'] != $b['type']) { + if ($a['type'] == 5 || $b['type'] == 2) { return - 1; - else if ($a['type'] == 2 || $b['type'] == 5) + } elseif ($a['type'] == 2 || $b['type'] == 5) { return 1; - else if ($a['type'] == 5) + } elseif ($a['type'] == 5) { return strcmp( strtolower( $a['name'] ), strtolower( $b['name'] ) ); - else if ($a['ext'] != $b['ext']) + } elseif ($a['ext'] != $b['ext']) { return strcmp( $a['ext'], $b['ext'] ); - else if ($a['stat'][7] != $b['stat'][7]) + } elseif ($a['stat'][7] != $b['stat'][7]) { return $a['stat'][7] > $b['stat'][7] ? - 1 : 1; - else + } else { return strcmp( strtolower( $a['name'] ), strtolower( $b['name'] ) ); + } + } return 0; } @@ -375,8 +396,9 @@ class tar_file extends archive $pwd = getcwd(); chdir( $this->options['basedir'] ); foreach ($this->files as $current) { - if ($current['name'] == $this->options['name']) + if ($current['name'] == $this->options['name']) { continue; + } if (strlen( $current['name2'] ) > 99) { $path = substr( $current['name2'], 0, strpos( $current['name2'], "/", strlen( $current['name2'] ) - 100 ) + 1 ); $current['name2'] = substr( $current['name2'], strlen( $path ) ); @@ -387,25 +409,29 @@ class tar_file extends archive } $block = pack( "a100a8a8a8a12a12a8a1a100a6a2a32a32a8a8a155a12", $current['name2'], sprintf( "%07o", $current['stat'][2] ), sprintf( "%07o", $current['stat'][4] ), sprintf( "%07o", $current['stat'][5] ), sprintf( "%011o", $current['type'] == 2 ? 0 : $current['stat'][7] ), sprintf( "%011o", $current['stat'][9] ), " ", $current['type'], $current['type'] == 2 ? @readlink( $current['name'] ) : "", "ustar ", " ", "Unknown", "Unknown", "", "", ! empty( $path ) ? $path : "", "" ); $checksum = 0; - for ($i = 0; $i < 512; $i ++) + for ($i = 0; $i < 512; $i ++) { $checksum += ord( substr( $block, $i, 1 ) ); + } $checksum = pack( "a8", sprintf( "%07o", $checksum ) ); $block = substr_replace( $block, $checksum, 148, 8 ); - if ($current['type'] == 2 || $current['stat'][7] == 0) + if ($current['type'] == 2 || $current['stat'][7] == 0) { $this->add_data( $block ); - else if ($fp = @fopen( $current['name'], "rb" )) { + } elseif ($fp = @fopen( $current['name'], "rb" )) { $this->add_data( $block ); - while ($temp = fread( $fp, 1048576 )) + while ($temp = fread( $fp, 1048576 )) { $this->add_data( $temp ); + } if ($current['stat'][7] % 512 > 0) { $temp = ""; - for ($i = 0; $i < 512 - $current['stat'][7] % 512; $i ++) + for ($i = 0; $i < 512 - $current['stat'][7] % 512; $i ++) { $temp .= "\0"; + } $this->add_data( $temp ); } fclose( $fp ); - } else + } else { $this->error[] = "Could not open file {$current['name']} for reading. It was not added."; + } } $this->add_data( pack( "a1024", "" ) ); chdir( $pwd ); @@ -422,41 +448,45 @@ class tar_file extends archive $pwd = getcwd(); chdir( $this->options['basedir'] ); if ($fp = $this->open_archive()) { - if ($this->options['inmemory'] == 1) + if ($this->options['inmemory'] == 1) { $this->files = array (); + } while ($block = fread( $fp, 512 )) { $temp = unpack( "a100name/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1type/a100symlink/a6magic/a2temp/a32temp/a32temp/a8temp/a8temp/a155prefix/a12temp", $block ); $file = array ('name' => $this->options['basedir'] . '/' . $temp['prefix'] . $temp['name'],'stat' => array (2 => $temp['mode'],4 => octdec( $temp['uid'] ),5 => octdec( $temp['gid'] ),7 => octdec( $temp['size'] ),9 => octdec( $temp['mtime'] ) ),'checksum' => octdec( $temp['checksum'] ),'type' => $temp['type'],'magic' => $temp['magic'] ); - if ($file['checksum'] == 0x00000000) + if ($file['checksum'] == 0x00000000) { break; - else if (substr( $file['magic'], 0, 5 ) != "ustar") { + } elseif (substr( $file['magic'], 0, 5 ) != "ustar") { $this->error[] = "This script does not support extracting this type of tar file."; break; } $block = substr_replace( $block, " ", 148, 8 ); $checksum = 0; - for ($i = 0; $i < 512; $i ++) + for ($i = 0; $i < 512; $i ++) { $checksum += ord( substr( $block, $i, 1 ) ); - if ($file['checksum'] != $checksum) + } + if ($file['checksum'] != $checksum) { $this->error[] = "Could not extract from {$this->options['name']}, it is corrupt."; + } if ($this->options['inmemory'] == 1) { $file['data'] = fread( $fp, $file['stat'][7] ); fread( $fp, (512 - $file['stat'][7] % 512) == 512 ? 0 : (512 - $file['stat'][7] % 512) ); unset( $file['checksum'], $file['magic'] ); $this->files[] = $file; - } else if ($file['type'] == 5) { - if (! is_dir( $file['name'] )) + } elseif ($file['type'] == 5) { + if (! is_dir( $file['name'] )) { //mkdir($file['name'], $file['stat'][2]); mkdir( $file['name'], 0775 ); - } else if ($this->options['overwrite'] == 0 && file_exists( $file['name'] )) { + } + } elseif ($this->options['overwrite'] == 0 && file_exists( $file['name'] )) { $this->error[] = "{$file['name']} already exist."; continue; - } else if ($file['type'] == 2) { + } elseif ($file['type'] == 2) { symlink( $temp['symlink'], $file['name'] ); //chmod($file['name'], $file['stat'][2]); - } else if ($new = @fopen( $file['name'], "wb" )) { + } elseif ($new = @fopen( $file['name'], "wb" )) { fwrite( $new, fread( $fp, $file['stat'][7] ) ); if ((512 - $file['stat'][7] % 512) != 512) { fread( $fp, (512 - $file['stat'][7] % 512) ); @@ -475,8 +505,9 @@ class tar_file extends archive @touch( $file['name'], $file['stat'][9] ); unset( $file ); } - } else + } else { $this->error[] = "Could not open file {$this->options['name']}"; + } chdir( $pwd ); } @@ -526,8 +557,9 @@ class gzip_file extends tar_file chdir( $this->options['basedir'] ); if ($fp = gzopen( $this->options['name'], "wb{$this->options['level']}" )) { fseek( $this->archive, 0 ); - while ($temp = fread( $this->archive, 1048576 )) + while ($temp = fread( $this->archive, 1048576 )) { gzwrite( $fp, $temp ); + } gzclose( $fp ); chdir( $pwd ); } else { @@ -535,8 +567,9 @@ class gzip_file extends tar_file chdir( $pwd ); return 0; } - } else + } else { $this->archive = gzencode( $this->archive, $this->options['level'] ); + } return 1; } @@ -587,8 +620,9 @@ class bzip_file extends tar_file chdir( $this->options['basedir'] ); if ($fp = bzopen( $this->options['name'], "wb" )) { fseek( $this->archive, 0 ); - while ($temp = fread( $this->archive, 1048576 )) + while ($temp = fread( $this->archive, 1048576 )) { bzwrite( $fp, $temp ); + } bzclose( $fp ); chdir( $pwd ); } else { @@ -596,9 +630,9 @@ class bzip_file extends tar_file chdir( $pwd ); return 0; } - } else + } else { $this->archive = bzcompress( $this->archive, $this->options['level'] ); - + } return 1; } @@ -640,20 +674,23 @@ class zip_file extends archive $files = 0; $offset = 0; $central = ""; - if (! empty( $this->options['sfx'] )) + if (! empty( $this->options['sfx'] )) { if ($fp = @fopen( $this->options['sfx'], "rb" )) { $temp = fread( $fp, filesize( $this->options['sfx'] ) ); fclose( $fp ); $this->add_data( $temp ); $offset += strlen( $temp ); unset( $temp ); - } else + } else { $this->error[] = "Could not open sfx module from {$this->options['sfx']}."; + } + } $pwd = getcwd(); chdir( $this->options['basedir'] ); foreach ($this->files as $current) { - if ($current['name'] == $this->options['name']) + if ($current['name'] == $this->options['name']) { continue; + } $timedate = explode( " ", date( "Y n j G i s", $current['stat'][9] ) ); $timedate = ($timedate[0] - 1980 << 25) | ($timedate[1] << 21) | ($timedate[2] << 16) | ($timedate[3] << 11) | ($timedate[4] << 5) | ($timedate[5]); $block = pack( "VvvvV", 0x04034b50, 0x000A, 0x0000, (isset( $current['method'] ) || $this->options['method'] == 0) ? 0x0000 : 0x0008, $timedate ); @@ -665,7 +702,7 @@ class zip_file extends archive $central .= $current['name2'] . "/"; $files ++; $offset += (31 + strlen( $current['name2'] )); - } else if ($current['stat'][7] == 0) { + } elseif ($current['stat'][7] == 0) { $block .= pack( "VVVvv", 0x00000000, 0x00000000, 0x00000000, strlen( $current['name2'] ), 0x0000 ); $block .= $current['name2']; $this->add_data( $block ); @@ -673,7 +710,7 @@ class zip_file extends archive $central .= $current['name2']; $files ++; $offset += (30 + strlen( $current['name2'] )); - } else if ($fp = @fopen( $current['name'], "rb" )) { + } elseif ($fp = @fopen( $current['name'], "rb" )) { $temp = fread( $fp, $current['stat'][7] ); fclose( $fp ); $crc32 = crc32( $temp ); @@ -681,8 +718,9 @@ class zip_file extends archive $temp = gzcompress( $temp, $this->options['level'] ); $size = strlen( $temp ) - 6; $temp = substr( $temp, 2, $size ); - } else + } else { $size = strlen( $temp ); + } $block .= pack( "VVVvv", $crc32, $size, $current['stat'][7], strlen( $current['name2'] ), 0x0000 ); $block .= $current['name2']; $this->add_data( $block ); @@ -692,13 +730,15 @@ class zip_file extends archive $central .= $current['name2']; $files ++; $offset += (30 + strlen( $current['name2'] ) + $size); - } else + } else { $this->error[] = "Could not open file {$current['name']} for reading. It was not added."; + } } $this->add_data( $central ); $this->add_data( pack( "VvvvvVVv", 0x06054b50, 0x0000, 0x0000, $files, $files, strlen( $central ), $offset, ! empty( $this->options['comment'] ) ? strlen( $this->options['comment'] ) : 0x0000 ) ); - if (! empty( $this->options['comment'] )) + if (! empty( $this->options['comment'] )) { $this->add_data( $this->options['comment'] ); + } chdir( $pwd ); return 1; } diff --git a/workflow/engine/classes/class.wsTools.php b/workflow/engine/classes/class.wsTools.php index 3841b45ed..e34d23d23 100755 --- a/workflow/engine/classes/class.wsTools.php +++ b/workflow/engine/classes/class.wsTools.php @@ -5,1113 +5,1149 @@ * @author Alexandre Rosenfeld */ -G::LoadSystem('dbMaintenance'); -G::LoadClass("cli"); -G::LoadClass("multipleFilesBackup"); +G::LoadSystem( 'dbMaintenance' ); +G::LoadClass( "cli" ); +G::LoadClass( "multipleFilesBackup" ); + /** * class workspaceTools + * * @package workflow.engine.classes */ -class workspaceTools { - var $name = NULL; - var $path = NULL; - var $db = NULL; - var $dbPath = NULL; - var $dbInfo = NULL; - var $dbInfoRegExp = "/( *define *\( *'(?P.*?)' *, *\n* *')(?P.*?)(' *\) *;.*)/"; - var $initPropel = false; - var $initPropelRoot = false; +class workspaceTools +{ + var $name = null; + var $path = null; + var $db = null; + var $dbPath = null; + var $dbInfo = null; + var $dbInfoRegExp = "/( *define *\( *'(?P.*?)' *, *\n* *')(?P.*?)(' *\) *;.*)/"; + var $initPropel = false; + var $initPropelRoot = false; - /** - * Create a workspace tools object. Note that workspace might not exist when - * this object is created, however most methods requires that a workspace with - * this name does exists. - * - * @author Alexandre Rosenfeld - * @access public - * @param string $workspaceName name of the workspace - */ - function __construct($workspaceName) { - $this->name = $workspaceName; - $this->path = PATH_DB . $this->name; - $this->dbPath = $this->path . '/db.php'; - if ($this->workspaceExists()) - $this->getDBInfo (); - } + /** + * Create a workspace tools object. + * Note that workspace might not exist when + * this object is created, however most methods requires that a workspace with + * this name does exists. + * + * @author Alexandre Rosenfeld + * @access public + * @param string $workspaceName name of the workspace + */ + function __construct ($workspaceName) + { + $this->name = $workspaceName; + $this->path = PATH_DB . $this->name; + $this->dbPath = $this->path . '/db.php'; + if ($this->workspaceExists()) { + $this->getDBInfo(); + } + } - /** - * Returns true if the workspace already exists - * - * @return bool - */ - public function workspaceExists() { - return (file_exists($this->path) && file_exists($this->dbPath)); - } + /** + * Returns true if the workspace already exists + * + * @return bool + */ + public function workspaceExists () + { + return (file_exists( $this->path ) && file_exists( $this->dbPath )); + } /** * Upgrade this workspace to the latest system version * - * @param bool $first true if this is the first workspace to be upgrade + * @param bool $first true if this is the first workspace to be upgrade */ - public function upgrade($first=false, $buildCacheView=false, $workSpace=SYS_SYS) + public function upgrade ($first = false, $buildCacheView = false, $workSpace = SYS_SYS) { - $start = microtime(true); - CLI::logging("> Updating database...\n"); + $start = microtime( true ); + CLI::logging( "> Updating database...\n" ); $this->upgradeDatabase(); - $stop = microtime(true); + $stop = microtime( true ); $final = $stop - $start; - CLI::logging("<*> Process Updating database carried out in $final seconds.\n"); + CLI::logging( "<*> Process Updating database carried out in $final seconds.\n" ); - $start = microtime(true); - CLI::logging("> Updating translations...\n"); - $this->upgradeTranslation($first); - $stop = microtime(true); + $start = microtime( true ); + CLI::logging( "> Updating translations...\n" ); + $this->upgradeTranslation( $first ); + $stop = microtime( true ); $final = $stop - $start; - CLI::logging("<*> Process Updating translations carried out in $final seconds.\n"); + CLI::logging( "<*> Process Updating translations carried out in $final seconds.\n" ); - $start = microtime(true); - CLI::logging("> Updating Content...\n"); - $this->upgradeContent($workSpace); - $stop = microtime(true); + $start = microtime( true ); + CLI::logging( "> Updating Content...\n" ); + $this->upgradeContent( $workSpace ); + $stop = microtime( true ); $final = $stop - $start; - CLI::logging("<*> Process Updating Content carried out in $final seconds.\n"); + CLI::logging( "<*> Process Updating Content carried out in $final seconds.\n" ); - $start = microtime(true); - CLI::logging("> Updating cache view...\n"); - $this->upgradeCacheView($buildCacheView); - $stop = microtime(true); + $start = microtime( true ); + CLI::logging( "> Updating cache view...\n" ); + $this->upgradeCacheView( $buildCacheView ); + $stop = microtime( true ); $final = $stop - $start; - CLI::logging("<*> Process Updating cache view carried out in $final seconds.\n"); + CLI::logging( "<*> Process Updating cache view carried out in $final seconds.\n" ); } - /** - * Scan the db.php file for database information and return it as an array - * - * @return array with database information - */ - public function getDBInfo() { - if (!$this->workspaceExists()) - throw new Exception("Could not get db.php in workspace " . $this->name); - if (isset($this->dbInfo)) - return $this->dbInfo; - $sDbFile = file_get_contents($this->dbPath); - /* This regular expression will match any "define ('', '');" - * with any combination of whitespace between words. - * Each match will have these groups: - * ((define('()2', ')1 ()3 (');)4 )0 + /** + * Scan the db.php file for database information and return it as an array + * + * @return array with database information */ - preg_match_all($this->dbInfoRegExp, $sDbFile, $matches, PREG_SET_ORDER); - $values = array(); - foreach ($matches as $match) { - $values[$match['key']] = $match['value']; - } - $this->dbAdapter = $values["DB_ADAPTER"]; - $this->dbName = $values["DB_NAME"]; - $this->dbHost = $values["DB_HOST"]; - $this->dbUser = $values["DB_USER"]; - $this->dbPass = $values["DB_PASS"]; - return $this->dbInfo = $values; - } - - private function resetDBInfoCallback($matches) { - /* This function changes the values of defines while keeping their formatting - * intact. - * $matches will contain several groups: - * ((define('()2', ')1 ()3 (');)4 )0 - */ - $dbPrefix = array( - 'DB_NAME' => 'wf_', - 'DB_USER' => 'wf_', - 'DB_RBAC_NAME' => 'rb_', - 'DB_RBAC_USER' => 'rb_', - 'DB_REPORT_NAME' => 'rp_', - 'DB_REPORT_USER' => 'rp_'); - $key = $matches['key']; - $value = $matches['value']; - if (array_search($key, array('DB_HOST', 'DB_RBAC_HOST', 'DB_REPORT_HOST')) !== false) { - /* Change the database hostname for these keys */ - $value = $this->newHost; - } else if (array_key_exists($key, $dbPrefix)) { - if ($this->resetDBNames) { - /* Change the database name to the new workspace, following the standard - * of prefix (either wf_, rp_, rb_) and the workspace name. + public function getDBInfo () + { + if (! $this->workspaceExists()) { + throw new Exception( "Could not get db.php in workspace " . $this->name ); + } + if (isset( $this->dbInfo )) { + return $this->dbInfo; + } + $sDbFile = file_get_contents( $this->dbPath ); + /* This regular expression will match any "define ('', '');" + * with any combination of whitespace between words. + * Each match will have these groups: + * ((define('()2', ')1 ()3 (');)4 )0 */ - $dbName = $dbPrefix[$key] . $this->name; - } else { - $dbName = $value; - } - $this->resetDBDiff[$value] = $dbName; - $value = $dbName; + preg_match_all( $this->dbInfoRegExp, $sDbFile, $matches, PREG_SET_ORDER ); + $values = array (); + foreach ($matches as $match) { + $values[$match['key']] = $match['value']; + } + $this->dbAdapter = $values["DB_ADAPTER"]; + $this->dbName = $values["DB_NAME"]; + $this->dbHost = $values["DB_HOST"]; + $this->dbUser = $values["DB_USER"]; + $this->dbPass = $values["DB_PASS"]; + return $this->dbInfo = $values; } - return $matches[1].$value.$matches[4]; - } - /** - * Reset the database information to that of a newly created workspace. - * - * This assumes this workspace already has a db.php file, which will be changed - * to contain the new information. - * This function will reset the database hostname to the system database. - * If reseting database names, it will also use the the prefixes rp_, - * rb_ and wf_, with the workspace name as database names. - * - * @param string $newHost the new hostname for the database - * @param bool $resetDBNames if true, also reset all database names - * @return array contains the new database names as values - */ - public function resetDBInfo($newHost, $resetDBNames = true) { - if (count(explode(":", $newHost)) < 2) - $newHost .= ':3306'; - $this->newHost = $newHost; - $this->resetDBNames = $resetDBNames; - $this->resetDBDiff = array(); + private function resetDBInfoCallback ($matches) + { + /* This function changes the values of defines while keeping their formatting + * intact. + * $matches will contain several groups: + * ((define('()2', ')1 ()3 (');)4 )0 + */ + $dbPrefix = array ('DB_NAME' => 'wf_','DB_USER' => 'wf_','DB_RBAC_NAME' => 'rb_','DB_RBAC_USER' => 'rb_','DB_REPORT_NAME' => 'rp_','DB_REPORT_USER' => 'rp_' + ); + $key = $matches['key']; + $value = $matches['value']; + if (array_search( $key, array ('DB_HOST','DB_RBAC_HOST','DB_REPORT_HOST' + ) ) !== false) { + /* Change the database hostname for these keys */ + $value = $this->newHost; + } elseif (array_key_exists( $key, $dbPrefix )) { + if ($this->resetDBNames) { + /* Change the database name to the new workspace, following the standard + * of prefix (either wf_, rp_, rb_) and the workspace name. + */ + $dbName = $dbPrefix[$key] . $this->name; + } else { + $dbName = $value; + } + $this->resetDBDiff[$value] = $dbName; + $value = $dbName; + } + return $matches[1] . $value . $matches[4]; + } - if (!$this->workspaceExists()) - throw new Exception("Could not find db.php in the workspace"); - $sDbFile = file_get_contents($this->dbPath); - if ($sDbFile === false) - throw new Exception("Could not read database information from db.php"); - /* Match all defines in the config file. Check updateDBCallback to know what - * keys are changed and what groups are matched. - * This regular expression will match any "define ('', '');" - * with any combination of whitespace between words. + /** + * Reset the database information to that of a newly created workspace. + * + * This assumes this workspace already has a db.php file, which will be changed + * to contain the new information. + * This function will reset the database hostname to the system database. + * If reseting database names, it will also use the the prefixes rp_, + * rb_ and wf_, with the workspace name as database names. + * + * @param string $newHost the new hostname for the database + * @param bool $resetDBNames if true, also reset all database names + * @return array contains the new database names as values */ - $sNewDbFile = preg_replace_callback("/( *define *\( *'(?P.*?)' *, *\n* *')(?P.*?)(' *\) *;.*)/", - array(&$this, 'resetDBInfoCallback'), - $sDbFile); - if (file_put_contents($this->dbPath, $sNewDbFile) === false) - throw new Exception("Could not write database information to db.php"); - $newDBNames = $this->resetDBDiff; - unset($this->resetDBDiff); - unset($this->resetDBNames); - //Clear the cached information about db.php - unset($this->dbInfo); - return $newDBNames; - } + public function resetDBInfo ($newHost, $resetDBNames = true) + { + if (count( explode( ":", $newHost ) ) < 2) { + $newHost .= ':3306'; + } + $this->newHost = $newHost; + $this->resetDBNames = $resetDBNames; + $this->resetDBDiff = array (); - /** - * Get DB information for this workspace, such as hostname, username and password. - * - * @param string $dbName a db name, such as wf, rp and rb - * @return array with all the database information. - */ - public function getDBCredentials($dbName) { - $prefixes = array( - "wf" => "", - "rp" => "REPORT_", - "rb" => "RBAC_" - ); - $prefix = $prefixes[$dbName]; - $dbInfo = $this->getDBInfo(); - return array( - 'adapter' => $dbInfo["DB_ADAPTER"], - 'name' => $dbInfo["DB_".$prefix."NAME"], - 'host' => $dbInfo["DB_".$prefix."HOST"], - 'user' => $dbInfo["DB_".$prefix."USER"], - 'pass' => $dbInfo["DB_".$prefix."PASS"], - 'dsn' => sprintf("%s://%s:%s@%s/%s?encoding=utf8", $dbInfo['DB_ADAPTER'] , - $dbInfo["DB_".$prefix."USER"], $dbInfo["DB_".$prefix."PASS"], - $dbInfo["DB_".$prefix."HOST"], $dbInfo["DB_".$prefix."NAME"]) - ); - } - - /** - * Initialize a Propel connection to the database - * - * @param bool $root wheter to also initialize a root connection - * @return the Propel connection - */ - public function initPropel($root = false) { - if (($this->initPropel && !$root) || ($this->initPropelRoot && $root)) - return; - $wfDetails = $this->getDBCredentials("wf"); - $rbDetails = $this->getDBCredentials("rb"); - $rpDetails = $this->getDBCredentials("rp"); - - $config = array( - 'datasources' => array( - 'workflow' => array( - 'connection' => $wfDetails["dsn"], - 'adapter' => $wfDetails["adapter"] - ), - 'rbac' => array( - 'connection' => $rbDetails["dsn"], - 'adapter' => $rbDetails["adapter"] - ), - 'rp' => array( - 'connection' => $rpDetails["dsn"], - 'adapter' => $rpDetails["adapter"] - ) - ) - ); - - if ($root) { - $dbHash = @explode(SYSTEM_HASH, G::decrypt(HASH_INSTALLATION, SYSTEM_HASH)); - - $dbInfo = $this->getDBInfo(); - $host = $dbHash[0]; - $user = $dbHash[1]; - $pass = $dbHash[2]; - $dbName = $dbInfo["DB_NAME"]; - - $rootConfig = array( - 'datasources' => array( - 'root' => array( - 'connection' => "mysql://$user:$pass@$host/$dbName?encoding=utf8", - 'adapter' => "mysql" - ) - ) - ); - - $config["datasources"] = array_merge($config["datasources"], $rootConfig["datasources"]); - - $this->initPropelRoot = true; + if (! $this->workspaceExists()) { + throw new Exception( "Could not find db.php in the workspace" ); + } + $sDbFile = file_get_contents( $this->dbPath ); + if ($sDbFile === false) { + throw new Exception( "Could not read database information from db.php" ); + } + /* Match all defines in the config file. Check updateDBCallback to know what + * keys are changed and what groups are matched. + * This regular expression will match any "define ('', '');" + * with any combination of whitespace between words. + */ + $sNewDbFile = preg_replace_callback( "/( *define *\( *'(?P.*?)' *, *\n* *')(?P.*?)(' *\) *;.*)/", array (&$this,'resetDBInfoCallback' + ), $sDbFile ); + if (file_put_contents( $this->dbPath, $sNewDbFile ) === false) { + throw new Exception( "Could not write database information to db.php" ); + } + $newDBNames = $this->resetDBDiff; + unset( $this->resetDBDiff ); + unset( $this->resetDBNames ); + //Clear the cached information about db.php + unset( $this->dbInfo ); + return $newDBNames; } - $this->initPropel = true; + /** + * Get DB information for this workspace, such as hostname, username and password. + * + * @param string $dbName a db name, such as wf, rp and rb + * @return array with all the database information. + */ + public function getDBCredentials ($dbName) + { + $prefixes = array ("wf" => "","rp" => "REPORT_","rb" => "RBAC_" + ); + $prefix = $prefixes[$dbName]; + $dbInfo = $this->getDBInfo(); + return array ('adapter' => $dbInfo["DB_ADAPTER"],'name' => $dbInfo["DB_" . $prefix . "NAME"],'host' => $dbInfo["DB_" . $prefix . "HOST"],'user' => $dbInfo["DB_" . $prefix . "USER"],'pass' => $dbInfo["DB_" . $prefix . "PASS"],'dsn' => sprintf( "%s://%s:%s@%s/%s?encoding=utf8", $dbInfo['DB_ADAPTER'], $dbInfo["DB_" . $prefix . "USER"], $dbInfo["DB_" . $prefix . "PASS"], $dbInfo["DB_" . $prefix . "HOST"], $dbInfo["DB_" . $prefix . "NAME"] ) + ); + } - require_once ( "propel/Propel.php" ); - require_once ( "creole/Creole.php" ); + /** + * Initialize a Propel connection to the database + * + * @param bool $root wheter to also initialize a root connection + * @return the Propel connection + */ + public function initPropel ($root = false) + { + if (($this->initPropel && ! $root) || ($this->initPropelRoot && $root)) { + return; + } + $wfDetails = $this->getDBCredentials( "wf" ); + $rbDetails = $this->getDBCredentials( "rb" ); + $rpDetails = $this->getDBCredentials( "rp" ); - Propel::initConfiguration($config); - } + $config = array ('datasources' => array ('workflow' => array ('connection' => $wfDetails["dsn"],'adapter' => $wfDetails["adapter"] + ),'rbac' => array ('connection' => $rbDetails["dsn"],'adapter' => $rbDetails["adapter"] + ),'rp' => array ('connection' => $rpDetails["dsn"],'adapter' => $rpDetails["adapter"] + ) + ) + ); - /** - * Close the propel connection from initPropel - */ - private function closePropel() { - Propel::close(); - $this->initPropel = false; - $this->initPropelRoot = false; - } + if ($root) { + $dbHash = @explode( SYSTEM_HASH, G::decrypt( HASH_INSTALLATION, SYSTEM_HASH ) ); + + $dbInfo = $this->getDBInfo(); + $host = $dbHash[0]; + $user = $dbHash[1]; + $pass = $dbHash[2]; + $dbName = $dbInfo["DB_NAME"]; + + $rootConfig = array ('datasources' => array ('root' => array ('connection' => "mysql://$user:$pass@$host/$dbName?encoding=utf8",'adapter' => "mysql" + ) + ) + ); + + $config["datasources"] = array_merge( $config["datasources"], $rootConfig["datasources"] ); + + $this->initPropelRoot = true; + } + + $this->initPropel = true; + + require_once ("propel/Propel.php"); + require_once ("creole/Creole.php"); + + Propel::initConfiguration( $config ); + } + + /** + * Close the propel connection from initPropel + */ + private function closePropel () + { + Propel::close(); + $this->initPropel = false; + $this->initPropelRoot = false; + } /** * Upgrade this workspace Content. - * */ - public function upgradeContent($workSpace=SYS_SYS) { - $this->initPropel(true); + public function upgradeContent ($workSpace = SYS_SYS) + { + $this->initPropel( true ); require_once 'classes/model/Translation.php'; $translation = new Translation(); $information = $translation->getTranslationEnvironments(); - $arrayLang = array(); + $arrayLang = array (); foreach ($information as $key => $value) { - $arrayLang[] = trim($value['LOCALE']); + $arrayLang[] = trim( $value['LOCALE'] ); } - require_once('classes/model/Content.php'); + require_once ('classes/model/Content.php'); $regenerateContent = new Content(); - $regenerateContent->regenerateContent($arrayLang, $workSpace); + $regenerateContent->regenerateContent( $arrayLang, $workSpace ); } - /** - * Upgrade this workspace translations from all avaliable languages. - * - * @param bool $first if updating a series of workspace, true if the first - */ - public function upgradeTranslation($first = true) { - $this->initPropel(true); - require_once('classes/model/Language.php'); - G::LoadThirdParty('pear/json', 'class.json'); - foreach (System::listPoFiles() as $poFile) { - $poName = basename($poFile); - $names = explode(".", basename($poFile)); - $extension = array_pop($names); - $langid = array_pop($names); - if (strcasecmp($langid, "en") == 0) { - CLI::logging("Updating database translations with $poName\n"); - Language::import($poFile, false, true); - } else if ($first) { - CLI::logging("Updating XML form translations with $poName\n"); - Language::import($poFile, true, false); - } - } - } - - /** - * Get a connection to this workspace wf database - * - * @return database connection - */ - private function getDatabase() { - if (isset($this->db) && $this->db->isConnected()) - return $this->db; - G::LoadSystem( 'database_' . strtolower($this->dbAdapter)); - $this->db = new database($this->dbAdapter, $this->dbHost, $this->dbUser, - $this->dbPass, $this->dbName); - if ( !$this->db->isConnected() ) { - $this->db->logQuery ('No available connection to database!'); - throw new Exception("Could not connect to database"); - } - return $this->db; - } - - /** - * Close any database opened with getDatabase - */ - private function closeDatabase() { - if (!isset($this->db)) - return; - $this->db->close(); - $this->db = NULL; - } - - /** - * Close all currently opened databases - */ - public function close() { - $this->closePropel(); - $this->closeDatabase(); - } - - /** - * Get the current workspace database schema - * - * @return array with the database schema - */ - public function getSchema() { - $oDataBase = $this->getDatabase(); - - $aOldSchema = array(); - - try { - $oDataBase->iFetchType = MYSQL_NUM; - $oDataset1 = $oDataBase->executeQuery($oDataBase->generateShowTablesSQL()); - } catch ( Exception $e ) { - $oDataBase->logQuery ( $e->getmessage() ); - return NULL; - } - - //going thru all tables in current WF_ database - while ($aRow1 = $oDataBase->getRegistry( $oDataset1) ) { - $aPrimaryKeys = array(); - $sTable = strtoupper($aRow1[0]); - - //get description of each table, ( column and primary keys ) - //$oDataset2 = $oDataBase->executeQuery( $oDataBase->generateDescTableSQL($aRow1[0]) ); - $oDataset2 = $oDataBase->executeQuery( $oDataBase->generateDescTableSQL($sTable ) ); - $aOldSchema[ $sTable ] = array(); - $oDataBase->iFetchType = MYSQL_ASSOC; - while ($aRow2 = $oDataBase->getRegistry($oDataset2)) { - $aOldSchema[$sTable][$aRow2['Field']]['Field'] = $aRow2['Field']; - $aOldSchema[$sTable][$aRow2['Field']]['Type'] = $aRow2['Type']; - $aOldSchema[$sTable][$aRow2['Field']]['Null'] = $aRow2['Null']; - $aOldSchema[$sTable][$aRow2['Field']]['Default'] = $aRow2['Default']; - } - - //get indexes of each table SHOW INDEX FROM `ADDITIONAL_TABLES`; -- WHERE Key_name <> 'PRIMARY' - $oDataset2 = $oDataBase->executeQuery($oDataBase->generateTableIndexSQL($aRow1[0])); - $oDataBase->iFetchType = MYSQL_ASSOC; - while ($aRow2 = $oDataBase->getRegistry($oDataset2)) { - if ( !isset($aOldSchema[$sTable]['INDEXES']) ) { - $aOldSchema[$sTable]['INDEXES'] = array(); + /** + * Upgrade this workspace translations from all avaliable languages. + * + * @param bool $first if updating a series of workspace, true if the first + */ + public function upgradeTranslation ($first = true) + { + $this->initPropel( true ); + require_once ('classes/model/Language.php'); + G::LoadThirdParty( 'pear/json', 'class.json' ); + foreach (System::listPoFiles() as $poFile) { + $poName = basename( $poFile ); + $names = explode( ".", basename( $poFile ) ); + $extension = array_pop( $names ); + $langid = array_pop( $names ); + if (strcasecmp( $langid, "en" ) == 0) { + CLI::logging( "Updating database translations with $poName\n" ); + Language::import( $poFile, false, true ); + } elseif ($first) { + CLI::logging( "Updating XML form translations with $poName\n" ); + Language::import( $poFile, true, false ); + } } - if (!isset($aOldSchema[$sTable]['INDEXES'][$aRow2['Key_name']] ) ) { - $aOldSchema[$sTable]['INDEXES'][$aRow2['Key_name']] = array(); + } + + /** + * Get a connection to this workspace wf database + * + * @return database connection + */ + private function getDatabase () + { + if (isset( $this->db ) && $this->db->isConnected()) { + return $this->db; } - $aOldSchema[$sTable]['INDEXES'][$aRow2['Key_name']][] = $aRow2['Column_name']; - } - - $oDataBase->iFetchType = MYSQL_NUM; //this line is neccesary because the next fetch needs to be with MYSQL_NUM - } - //finally return the array with old schema obtained from the Database - if ( count($aOldSchema) == 0 ) $aOldSchema = null; - return $aOldSchema; - } - - /** - * Upgrade the AppCacheView table to the latest system version. - * - * This recreates the table and populates with data. - * - * @param bool $checkOnly only check if the upgrade is needed if true - * @param string $lang not currently used - */ - public function upgradeCacheView($fill=true) { - $this->initPropel(true); - - $lang = "en"; - - require_once('classes/model/AppCacheView.php'); - - //check the language, if no info in config about language, the default is 'en' - G::loadClass('configuration'); - $oConf = new Configurations; - $oConf->loadConfig($x, 'APP_CACHE_VIEW_ENGINE','','','',''); - $appCacheViewEngine = $oConf->aConfig; - - //setup the appcacheview object, and the path for the sql files - $appCache = new AppCacheView(); - $appCache->setPathToAppCacheFiles ( PATH_METHODS . 'setup' . PATH_SEP .'setupSchemas'. PATH_SEP ); - - $userGrants = $appCache->checkGrantsForUser( false ); - - $currentUser = $userGrants['user']; - $currentUserIsSuper = $userGrants['super']; - - //if user does not have the SUPER privilege we need to use the root user and grant the SUPER priv. to normal user. - if (!$currentUserIsSuper) { - $appCache->checkGrantsForUser( true ); - $appCache->setSuperForUser( $currentUser ); - $currentUserIsSuper = true; - } - - CLI::logging("-> Creating table\n"); - //now check if table APPCACHEVIEW exists, and it have correct number of fields, etc. - $res = $appCache->checkAppCacheView(); - - CLI::logging("-> Creating triggers\n"); - //now check if we have the triggers installed - $triggers = array(); - $triggers[] = $appCache->triggerAppDelegationInsert($lang, $checkOnly); - $triggers[] = $appCache->triggerAppDelegationUpdate($lang, $checkOnly); - $triggers[] = $appCache->triggerApplicationUpdate($lang, $checkOnly); - $triggers[] = $appCache->triggerApplicationDelete($lang, $checkOnly); - $triggers[] = $appCache->triggerContentUpdate($lang, $checkOnly); - - if ($fill) { - CLI::logging("-> Rebuild Cache View\n"); - //build using the method in AppCacheView Class - $res = $appCache->fillAppCacheView($lang); - //set status in config table - $confParams = Array( - 'LANG' => $lang, - 'STATUS'=> 'active' - ); - } - $oConf->aConfig = $confParams; - $oConf->saveConfig('APP_CACHE_VIEW_ENGINE', '', '', ''); - - // removing casesList configuration records. TODO: removing these lines that resets all the configurations records - $oCriteria = new Criteria(); - $oCriteria->add(ConfigurationPeer::CFG_UID, "casesList"); - $oCriteria->add(ConfigurationPeer::OBJ_UID, array("todo", "draft", "sent", "unassigned", "paused", "cancelled"), Criteria::NOT_IN); - ConfigurationPeer::doDelete($oCriteria); - // end of reset - } - - /** - * Upgrade this workspace database to the latest plugins schema - */ - public function upgradePluginsDatabase() { - foreach (System::getPlugins() as $pluginName) { - $pluginSchema = System::getPluginSchema($pluginName); - if ($pluginSchema !== false) { - CLI::logging("Updating plugin " . CLI::info($pluginName) . "\n"); - $this->upgradeSchema($pluginSchema); - } - } - } - - /** - * Upgrade this workspace database to the latest system schema - * - * @param bool $checkOnly only check if the upgrade is needed if true - * @return array|bool see upgradeSchema for more information - */ - public function upgradeDatabase($checkOnly = false) { - $systemSchema = System::getSystemSchema(); - $this->upgradeSchema($systemSchema); - $this->upgradeData(); - return true; - } - - - /** - * Upgrade this workspace database from a schema - * - * @param array $schema the schema information, such as returned from getSystemSchema - * @param bool $checkOnly only check if the upgrade is needed if true - * @return array|bool returns the changes if checkOnly is true, else return - * true on success - */ - public function upgradeSchema($schema, $checkOnly = false) { - $dbInfo = $this->getDBInfo(); - - if (strcmp($dbInfo["DB_ADAPTER"], "mysql") != 0) { - throw new Exception("Only MySQL is supported"); - } - - $workspaceSchema = $this->getSchema(); - $changes = System::compareSchema($workspaceSchema, $schema); - $changed = (count($changes['tablesToAdd']) > 0 || - count($changes['tablesToAlter']) > 0 || - count($changes['tablesWithNewIndex']) > 0 || - count($changes['tablesToAlterIndex']) > 0); - if ($checkOnly || (!$changed)) { - if ($changed) { - return $changes; - } else { - CLI::logging("-> Nothing to change in the data base structure\n"); - return $changed; - } - } - - $oDataBase = $this->getDatabase(); - $oDataBase->iFetchType = MYSQL_NUM; - - $oDataBase->logQuery ( count ($changes ) ); - - if (!empty($changes['tablesToAdd'])) - CLI::logging( "-> " . count($changes['tablesToAdd']) . " tables to add\n"); - foreach ($changes['tablesToAdd'] as $sTable => $aColumns) { - $oDataBase->executeQuery($oDataBase->generateCreateTableSQL($sTable, $aColumns)); - if (isset($changes['tablesToAdd'][$sTable]['INDEXES'])) { - foreach ($changes['tablesToAdd'][$sTable]['INDEXES'] as $indexName => $aIndex) { - $oDataBase->executeQuery($oDataBase->generateAddKeysSQL($sTable, $indexName, $aIndex ) ); + G::LoadSystem( 'database_' . strtolower( $this->dbAdapter ) ); + $this->db = new database( $this->dbAdapter, $this->dbHost, $this->dbUser, $this->dbPass, $this->dbName ); + if (! $this->db->isConnected()) { + $this->db->logQuery( 'No available connection to database!' ); + throw new Exception( "Could not connect to database" ); } - } + return $this->db; } - if (!empty($changes['tablesToAlter'])) - CLI::logging("-> " . count($changes['tablesToAlter']) . " tables to alter\n"); - foreach ($changes['tablesToAlter'] as $sTable => $aActions) { - foreach ($aActions as $sAction => $aAction) { - foreach ($aAction as $sColumn => $vData) { - switch ($sAction) { - case 'DROP': - $oDataBase->executeQuery($oDataBase->generateDropColumnSQL($sTable, $vData)); - break; - case 'ADD': - $oDataBase->executeQuery($oDataBase->generateAddColumnSQL($sTable, $sColumn, $vData)); - break; - case 'CHANGE': - $oDataBase->executeQuery($oDataBase->generateChangeColumnSQL($sTable, $sColumn, $vData)); - break; - } + /** + * Close any database opened with getDatabase + */ + private function closeDatabase () + { + if (! isset( $this->db )) { + return; } - } + $this->db->close(); + $this->db = null; } - if (!empty($changes['tablesWithNewIndex'])) - CLI::logging("-> " . count($changes['tablesWithNewIndex']) . " indexes to add\n"); - foreach ($changes['tablesWithNewIndex'] as $sTable => $aIndexes) { - foreach ($aIndexes as $sIndexName => $aIndexFields ) { - $oDataBase->executeQuery($oDataBase->generateAddKeysSQL($sTable, $sIndexName, $aIndexFields )); - } + /** + * Close all currently opened databases + */ + public function close () + { + $this->closePropel(); + $this->closeDatabase(); } - if (!empty($changes['tablesToAlterIndex'])) - CLI::logging("-> " . count($changes['tablesToAlterIndex']) . " indexes to alter\n"); - foreach ($changes['tablesToAlterIndex'] as $sTable => $aIndexes) { - foreach ($aIndexes as $sIndexName => $aIndexFields ) { - $oDataBase->executeQuery($oDataBase->generateDropKeySQL($sTable, $sIndexName )); - $oDataBase->executeQuery($oDataBase->generateAddKeysSQL($sTable, $sIndexName, $aIndexFields )); - } - } - $this->closeDatabase(); - return true; - } + /** + * Get the current workspace database schema + * + * @return array with the database schema + */ + public function getSchema () + { + $oDataBase = $this->getDatabase(); - public function upgradeData() { - if (file_exists(PATH_CORE . 'data' . PATH_SEP . 'check.data')) { - $checkData = unserialize(file_get_contents(PATH_CORE . 'data' . PATH_SEP . 'check.data')); - if (is_array($checkData)) { - foreach ($checkData as $checkThis) { - $this->updateThisRegistry($checkThis); + $aOldSchema = array (); + + try { + $oDataBase->iFetchType = MYSQL_NUM; + $oDataset1 = $oDataBase->executeQuery( $oDataBase->generateShowTablesSQL() ); + } catch (Exception $e) { + $oDataBase->logQuery( $e->getmessage() ); + return null; } - } - } - } - public function updateThisRegistry($data) { - $dataBase = $this->getDatabase(); - $sql = ''; - switch ($data['action']) { - case 1: - $sql = $dataBase->generateInsertSQL($data['table'], $data['data']); - $message = "-> Row added in {$data['table']}\n"; - break; - case 2: - $sql = $dataBase->generateUpdateSQL($data['table'], $data['keys'], $data['data']); - $message = "-> Row updated in {$data['table']}\n"; - break; - case 3: - $sql = $dataBase->generateDeleteSQL($data['table'], $data['keys'], $data['data']); - $message = "-> Row deleted in {$data['table']}\n"; - break; - case 4: - $sql = $dataBase->generateSelectSQL($data['table'], $data['keys'], $data['data']); - $dataset = $dataBase->executeQuery($sql); - if ($dataBase->getRegistry($dataset)) { - $sql = $dataBase->generateDeleteSQL($data['table'], $data['keys'], $data['data']); - $dataBase->executeQuery($sql); + //going thru all tables in current WF_ database + while ($aRow1 = $oDataBase->getRegistry( $oDataset1 )) { + $aPrimaryKeys = array (); + $sTable = strtoupper( $aRow1[0] ); + + //get description of each table, ( column and primary keys ) + //$oDataset2 = $oDataBase->executeQuery( $oDataBase->generateDescTableSQL($aRow1[0]) ); + $oDataset2 = $oDataBase->executeQuery( $oDataBase->generateDescTableSQL( $sTable ) ); + $aOldSchema[$sTable] = array (); + $oDataBase->iFetchType = MYSQL_ASSOC; + while ($aRow2 = $oDataBase->getRegistry( $oDataset2 )) { + $aOldSchema[$sTable][$aRow2['Field']]['Field'] = $aRow2['Field']; + $aOldSchema[$sTable][$aRow2['Field']]['Type'] = $aRow2['Type']; + $aOldSchema[$sTable][$aRow2['Field']]['Null'] = $aRow2['Null']; + $aOldSchema[$sTable][$aRow2['Field']]['Default'] = $aRow2['Default']; + } + + //get indexes of each table SHOW INDEX FROM `ADDITIONAL_TABLES`; -- WHERE Key_name <> 'PRIMARY' + $oDataset2 = $oDataBase->executeQuery( $oDataBase->generateTableIndexSQL( $aRow1[0] ) ); + $oDataBase->iFetchType = MYSQL_ASSOC; + while ($aRow2 = $oDataBase->getRegistry( $oDataset2 )) { + if (! isset( $aOldSchema[$sTable]['INDEXES'] )) { + $aOldSchema[$sTable]['INDEXES'] = array (); + } + if (! isset( $aOldSchema[$sTable]['INDEXES'][$aRow2['Key_name']] )) { + $aOldSchema[$sTable]['INDEXES'][$aRow2['Key_name']] = array (); + } + $aOldSchema[$sTable]['INDEXES'][$aRow2['Key_name']][] = $aRow2['Column_name']; + } + + $oDataBase->iFetchType = MYSQL_NUM; //this line is neccesary because the next fetch needs to be with MYSQL_NUM } - $sql = $dataBase->generateInsertSQL($data['table'], $data['data']); - $message = "-> Row updated in {$data['table']}\n"; - break; - } - if ($sql != '') { - $dataBase->executeQuery($sql); - CLI::logging($message); - } - } - - /** - * Get metadata from this workspace - * - * @param string $path the directory where to create the sql files - * @return array information about this workspace - */ - public function getMetadata() { - $Fields = array_merge(System::getSysInfo(), $this->getDBInfo()); - $Fields['WORKSPACE_NAME'] = $this->name; - - if(isset($this->dbHost)) { - - //TODO: This code stopped working with the refactoring - //require_once ("propel/Propel.php"); - //G::LoadClass('dbConnections'); - //$dbConns = new dbConnections(''); - //$availdb = ''; - //foreach( $dbConns->getDbServicesAvailables() as $key => $val ) { - //if(!empty($availdb)) - // $availdb .= ', '; - // $availdb .= $val['name']; - //} - - G::LoadClass('net'); - $dbNetView = new NET($this->dbHost); - $dbNetView->loginDbServer($this->dbUser, $this->dbPass); - try { - $sMySQLVersion = $dbNetView->getDbServerVersion('mysql'); - } catch( Exception $oException ) { - $sMySQLVersion = 'Unknown'; - } - - $Fields['DATABASE'] = $dbNetView->dbName($this->dbAdapter) . ' (Version ' . $sMySQLVersion . ')'; - $Fields['DATABASE_SERVER'] = $this->dbHost; - $Fields['DATABASE_NAME'] = $this->dbName; - $Fields['AVAILABLE_DB'] = "Not defined"; - //$Fields['AVAILABLE_DB'] = $availdb; - } else { - $Fields['DATABASE'] = "Not defined"; - $Fields['DATABASE_SERVER'] = "Not defined"; - $Fields['DATABASE_NAME'] = "Not defined"; - $Fields['AVAILABLE_DB'] = "Not defined"; + //finally return the array with old schema obtained from the Database + if (count( $aOldSchema ) == 0) { + $aOldSchema = null; + } + return $aOldSchema; } - return $Fields; - } + /** + * Upgrade the AppCacheView table to the latest system version. + * + * This recreates the table and populates with data. + * + * @param bool $checkOnly only check if the upgrade is needed if true + * @param string $lang not currently used + */ + public function upgradeCacheView ($fill = true) + { + $this->initPropel( true ); - /** - * Print the system information gathered from getSysInfo - */ - public static function printSysInfo() { - $fields = System::getSysInfo(); + $lang = "en"; - $info = array( - 'ProcessMaker Version' => $fields['PM_VERSION'], - 'System' => $fields['SYSTEM'], - 'PHP Version' => $fields['PHP'], - 'Server Address' => $fields['SERVER_ADDR'], - 'Client IP Address' => $fields['IP'], - 'Plugins' => (count($fields['PLUGINS_LIST']) > 0) ? $fields['PLUGINS_LIST'][0] : 'None' - ); + require_once ('classes/model/AppCacheView.php'); - foreach( $fields['PLUGINS_LIST'] as $k => $v ) { - if ($k == 0) - continue; - $info[] = $v; + //check the language, if no info in config about language, the default is 'en' + G::loadClass( 'configuration' ); + $oConf = new Configurations(); + $oConf->loadConfig( $x, 'APP_CACHE_VIEW_ENGINE', '', '', '', '' ); + $appCacheViewEngine = $oConf->aConfig; + + //setup the appcacheview object, and the path for the sql files + $appCache = new AppCacheView(); + $appCache->setPathToAppCacheFiles( PATH_METHODS . 'setup' . PATH_SEP . 'setupSchemas' . PATH_SEP ); + + $userGrants = $appCache->checkGrantsForUser( false ); + + $currentUser = $userGrants['user']; + $currentUserIsSuper = $userGrants['super']; + + //if user does not have the SUPER privilege we need to use the root user and grant the SUPER priv. to normal user. + if (! $currentUserIsSuper) { + $appCache->checkGrantsForUser( true ); + $appCache->setSuperForUser( $currentUser ); + $currentUserIsSuper = true; + } + + CLI::logging( "-> Creating table\n" ); + //now check if table APPCACHEVIEW exists, and it have correct number of fields, etc. + $res = $appCache->checkAppCacheView(); + + CLI::logging( "-> Creating triggers\n" ); + //now check if we have the triggers installed + $triggers = array (); + $triggers[] = $appCache->triggerAppDelegationInsert( $lang, $checkOnly ); + $triggers[] = $appCache->triggerAppDelegationUpdate( $lang, $checkOnly ); + $triggers[] = $appCache->triggerApplicationUpdate( $lang, $checkOnly ); + $triggers[] = $appCache->triggerApplicationDelete( $lang, $checkOnly ); + $triggers[] = $appCache->triggerContentUpdate( $lang, $checkOnly ); + + if ($fill) { + CLI::logging( "-> Rebuild Cache View\n" ); + //build using the method in AppCacheView Class + $res = $appCache->fillAppCacheView( $lang ); + //set status in config table + $confParams = Array ('LANG' => $lang,'STATUS' => 'active' + ); + } + $oConf->aConfig = $confParams; + $oConf->saveConfig( 'APP_CACHE_VIEW_ENGINE', '', '', '' ); + + // removing casesList configuration records. TODO: removing these lines that resets all the configurations records + $oCriteria = new Criteria(); + $oCriteria->add( ConfigurationPeer::CFG_UID, "casesList" ); + $oCriteria->add( ConfigurationPeer::OBJ_UID, array ("todo","draft","sent","unassigned","paused","cancelled" + ), Criteria::NOT_IN ); + ConfigurationPeer::doDelete( $oCriteria ); + // end of reset } - foreach ($info as $k => $v) { - if (is_numeric($k)) $k = ""; - CLI::logging(sprintf("%20s %s\n", $k, pakeColor::colorize($v, 'INFO'))); + /** + * Upgrade this workspace database to the latest plugins schema + */ + public function upgradePluginsDatabase () + { + foreach (System::getPlugins() as $pluginName) { + $pluginSchema = System::getPluginSchema( $pluginName ); + if ($pluginSchema !== false) { + CLI::logging( "Updating plugin " . CLI::info( $pluginName ) . "\n" ); + $this->upgradeSchema( $pluginSchema ); + } + } } - } - public function printInfo($fields = NULL) { - if (!$fields) - $fields = $this->getMetadata (); + /** + * Upgrade this workspace database to the latest system schema + * + * @param bool $checkOnly only check if the upgrade is needed if true + * @return array bool upgradeSchema for more information + */ + public function upgradeDatabase ($checkOnly = false) + { + $systemSchema = System::getSystemSchema(); + $this->upgradeSchema( $systemSchema ); + $this->upgradeData(); + return true; + } - $wfDsn = $fields['DB_ADAPTER'] . '://' . $fields['DB_USER'] . ':' . $fields['DB_PASS'] . '@' . $fields['DB_HOST'] . '/' . $fields['DB_NAME']; - $rbDsn = $fields['DB_ADAPTER'] . '://' . $fields['DB_RBAC_USER'] . ':' . $fields['DB_RBAC_PASS'] . '@' . $fields['DB_RBAC_HOST'] . '/' . $fields['DB_RBAC_NAME']; - $rpDsn = $fields['DB_ADAPTER'] . '://' . $fields['DB_REPORT_USER'] . ':' . $fields['DB_REPORT_PASS'] . '@' . $fields['DB_REPORT_HOST'] . '/' . $fields['DB_REPORT_NAME']; + /** + * Upgrade this workspace database from a schema + * + * @param array $schema the schema information, such as returned from getSystemSchema + * @param bool $checkOnly only check if the upgrade is needed if true + * @return array bool the changes if checkOnly is true, else return + * true on success + */ + public function upgradeSchema ($schema, $checkOnly = false) + { + $dbInfo = $this->getDBInfo(); - $info = array( - 'Workspace Name' => $fields['WORKSPACE_NAME'], + if (strcmp( $dbInfo["DB_ADAPTER"], "mysql" ) != 0) { + throw new Exception( "Only MySQL is supported" ); + } + + $workspaceSchema = $this->getSchema(); + $changes = System::compareSchema( $workspaceSchema, $schema ); + $changed = (count( $changes['tablesToAdd'] ) > 0 || count( $changes['tablesToAlter'] ) > 0 || count( $changes['tablesWithNewIndex'] ) > 0 || count( $changes['tablesToAlterIndex'] ) > 0); + if ($checkOnly || (! $changed)) { + if ($changed) { + return $changes; + } else { + CLI::logging( "-> Nothing to change in the data base structure\n" ); + return $changed; + } + } + + $oDataBase = $this->getDatabase(); + $oDataBase->iFetchType = MYSQL_NUM; + + $oDataBase->logQuery( count( $changes ) ); + + if (! empty( $changes['tablesToAdd'] )) { + CLI::logging( "-> " . count( $changes['tablesToAdd'] ) . " tables to add\n" ); + } + foreach ($changes['tablesToAdd'] as $sTable => $aColumns) { + $oDataBase->executeQuery( $oDataBase->generateCreateTableSQL( $sTable, $aColumns ) ); + if (isset( $changes['tablesToAdd'][$sTable]['INDEXES'] )) { + foreach ($changes['tablesToAdd'][$sTable]['INDEXES'] as $indexName => $aIndex) { + $oDataBase->executeQuery( $oDataBase->generateAddKeysSQL( $sTable, $indexName, $aIndex ) ); + } + } + } + + if (! empty( $changes['tablesToAlter'] )) { + CLI::logging( "-> " . count( $changes['tablesToAlter'] ) . " tables to alter\n" ); + } + foreach ($changes['tablesToAlter'] as $sTable => $aActions) { + foreach ($aActions as $sAction => $aAction) { + foreach ($aAction as $sColumn => $vData) { + switch ($sAction) { + case 'DROP': + $oDataBase->executeQuery( $oDataBase->generateDropColumnSQL( $sTable, $vData ) ); + break; + case 'ADD': + $oDataBase->executeQuery( $oDataBase->generateAddColumnSQL( $sTable, $sColumn, $vData ) ); + break; + case 'CHANGE': + $oDataBase->executeQuery( $oDataBase->generateChangeColumnSQL( $sTable, $sColumn, $vData ) ); + break; + } + } + } + } + + if (! empty( $changes['tablesWithNewIndex'] )) { + CLI::logging( "-> " . count( $changes['tablesWithNewIndex'] ) . " indexes to add\n" ); + } + foreach ($changes['tablesWithNewIndex'] as $sTable => $aIndexes) { + foreach ($aIndexes as $sIndexName => $aIndexFields) { + $oDataBase->executeQuery( $oDataBase->generateAddKeysSQL( $sTable, $sIndexName, $aIndexFields ) ); + } + } + + if (! empty( $changes['tablesToAlterIndex'] )) { + CLI::logging( "-> " . count( $changes['tablesToAlterIndex'] ) . " indexes to alter\n" ); + } + foreach ($changes['tablesToAlterIndex'] as $sTable => $aIndexes) { + foreach ($aIndexes as $sIndexName => $aIndexFields) { + $oDataBase->executeQuery( $oDataBase->generateDropKeySQL( $sTable, $sIndexName ) ); + $oDataBase->executeQuery( $oDataBase->generateAddKeysSQL( $sTable, $sIndexName, $aIndexFields ) ); + } + } + $this->closeDatabase(); + return true; + } + + public function upgradeData () + { + if (file_exists( PATH_CORE . 'data' . PATH_SEP . 'check.data' )) { + $checkData = unserialize( file_get_contents( PATH_CORE . 'data' . PATH_SEP . 'check.data' ) ); + if (is_array( $checkData )) { + foreach ($checkData as $checkThis) { + $this->updateThisRegistry( $checkThis ); + } + } + } + } + + public function updateThisRegistry ($data) + { + $dataBase = $this->getDatabase(); + $sql = ''; + switch ($data['action']) { + case 1: + $sql = $dataBase->generateInsertSQL( $data['table'], $data['data'] ); + $message = "-> Row added in {$data['table']}\n"; + break; + case 2: + $sql = $dataBase->generateUpdateSQL( $data['table'], $data['keys'], $data['data'] ); + $message = "-> Row updated in {$data['table']}\n"; + break; + case 3: + $sql = $dataBase->generateDeleteSQL( $data['table'], $data['keys'], $data['data'] ); + $message = "-> Row deleted in {$data['table']}\n"; + break; + case 4: + $sql = $dataBase->generateSelectSQL( $data['table'], $data['keys'], $data['data'] ); + $dataset = $dataBase->executeQuery( $sql ); + if ($dataBase->getRegistry( $dataset )) { + $sql = $dataBase->generateDeleteSQL( $data['table'], $data['keys'], $data['data'] ); + $dataBase->executeQuery( $sql ); + } + $sql = $dataBase->generateInsertSQL( $data['table'], $data['data'] ); + $message = "-> Row updated in {$data['table']}\n"; + break; + } + if ($sql != '') { + $dataBase->executeQuery( $sql ); + CLI::logging( $message ); + } + } + + /** + * Get metadata from this workspace + * + * @param string $path the directory where to create the sql files + * @return array information about this workspace + */ + public function getMetadata () + { + $Fields = array_merge( System::getSysInfo(), $this->getDBInfo() ); + $Fields['WORKSPACE_NAME'] = $this->name; + + if (isset( $this->dbHost )) { + + //TODO: This code stopped working with the refactoring + //require_once ("propel/Propel.php"); + //G::LoadClass('dbConnections'); + //$dbConns = new dbConnections(''); + //$availdb = ''; + //foreach( $dbConns->getDbServicesAvailables() as $key => $val ) { + //if(!empty($availdb)) + // $availdb .= ', '; + // $availdb .= $val['name']; + //} + + + G::LoadClass( 'net' ); + $dbNetView = new NET( $this->dbHost ); + $dbNetView->loginDbServer( $this->dbUser, $this->dbPass ); + try { + $sMySQLVersion = $dbNetView->getDbServerVersion( 'mysql' ); + } catch (Exception $oException) { + $sMySQLVersion = 'Unknown'; + } + + $Fields['DATABASE'] = $dbNetView->dbName( $this->dbAdapter ) . ' (Version ' . $sMySQLVersion . ')'; + $Fields['DATABASE_SERVER'] = $this->dbHost; + $Fields['DATABASE_NAME'] = $this->dbName; + $Fields['AVAILABLE_DB'] = "Not defined"; + //$Fields['AVAILABLE_DB'] = $availdb; + } else { + $Fields['DATABASE'] = "Not defined"; + $Fields['DATABASE_SERVER'] = "Not defined"; + $Fields['DATABASE_NAME'] = "Not defined"; + $Fields['AVAILABLE_DB'] = "Not defined"; + } + + return $Fields; + } + + /** + * Print the system information gathered from getSysInfo + */ + public static function printSysInfo () + { + $fields = System::getSysInfo(); + + $info = array ('ProcessMaker Version' => $fields['PM_VERSION'],'System' => $fields['SYSTEM'],'PHP Version' => $fields['PHP'],'Server Address' => $fields['SERVER_ADDR'],'Client IP Address' => $fields['IP'],'Plugins' => (count( $fields['PLUGINS_LIST'] ) > 0) ? $fields['PLUGINS_LIST'][0] : 'None' + ); + + foreach ($fields['PLUGINS_LIST'] as $k => $v) { + if ($k == 0) { + continue; + } + $info[] = $v; + } + + foreach ($info as $k => $v) { + if (is_numeric( $k )) { + $k = ""; + } + CLI::logging( sprintf( "%20s %s\n", $k, pakeColor::colorize( $v, 'INFO' ) ) ); + } + } + + public function printInfo ($fields = null) + { + if (! $fields) { + $fields = $this->getMetadata(); + } + + $wfDsn = $fields['DB_ADAPTER'] . '://' . $fields['DB_USER'] . ':' . $fields['DB_PASS'] . '@' . $fields['DB_HOST'] . '/' . $fields['DB_NAME']; + $rbDsn = $fields['DB_ADAPTER'] . '://' . $fields['DB_RBAC_USER'] . ':' . $fields['DB_RBAC_PASS'] . '@' . $fields['DB_RBAC_HOST'] . '/' . $fields['DB_RBAC_NAME']; + $rpDsn = $fields['DB_ADAPTER'] . '://' . $fields['DB_REPORT_USER'] . ':' . $fields['DB_REPORT_PASS'] . '@' . $fields['DB_REPORT_HOST'] . '/' . $fields['DB_REPORT_NAME']; + + $info = array ('Workspace Name' => $fields['WORKSPACE_NAME'], //'Available Databases' => $fields['AVAILABLE_DB'], - 'Workflow Database' => sprintf("%s://%s:%s@%s/%s", $fields['DB_ADAPTER'] , $fields['DB_USER'], $fields['DB_PASS'], $fields['DB_HOST'], $fields['DB_NAME']), - 'RBAC Database' => sprintf("%s://%s:%s@%s/%s", $fields['DB_ADAPTER'] , $fields['DB_RBAC_USER'], $fields['DB_RBAC_PASS'], $fields['DB_RBAC_HOST'], $fields['DB_RBAC_NAME']), - 'Report Database' => sprintf("%s://%s:%s@%s/%s", $fields['DB_ADAPTER'] , $fields['DB_REPORT_USER'], $fields['DB_REPORT_PASS'], $fields['DB_REPORT_HOST'], $fields['DB_REPORT_NAME']), - 'MySql Version' => $fields['DATABASE'], - ); + 'Workflow Database' => sprintf( "%s://%s:%s@%s/%s", $fields['DB_ADAPTER'], $fields['DB_USER'], $fields['DB_PASS'], $fields['DB_HOST'], $fields['DB_NAME'] ),'RBAC Database' => sprintf( "%s://%s:%s@%s/%s", $fields['DB_ADAPTER'], $fields['DB_RBAC_USER'], $fields['DB_RBAC_PASS'], $fields['DB_RBAC_HOST'], $fields['DB_RBAC_NAME'] ),'Report Database' => sprintf( "%s://%s:%s@%s/%s", $fields['DB_ADAPTER'], $fields['DB_REPORT_USER'], $fields['DB_REPORT_PASS'], $fields['DB_REPORT_HOST'], $fields['DB_REPORT_NAME'] ),'MySql Version' => $fields['DATABASE'] + ); - foreach ($info as $k => $v) { - if (is_numeric($k)) $k = ""; - CLI::logging(sprintf("%20s %s\n", $k, pakeColor::colorize($v, 'INFO'))); - } - } - - /** - * Print workspace information - * - * @param bool $printSysInfo include sys info as well or not - */ - public function printMetadata($printSysInfo = true) { - if ($printSysInfo) { - workspaceTools::printSysInfo (); - CLI::logging("\n"); + foreach ($info as $k => $v) { + if (is_numeric( $k )) { + $k = ""; + } + CLI::logging( sprintf( "%20s %s\n", $k, pakeColor::colorize( $v, 'INFO' ) ) ); + } } - workspaceTools::printInfo($this->getMetadata()); - } - - /** - * exports this workspace database to the specified path - * - * This function is used mainly for backup purposes. - * - * @param string $path the directory where to create the sql files - */ - public function exportDatabase($path) { - $dbInfo = $this->getDBInfo(); - $databases = array("wf", "rp", "rb"); - $dbNames = array(); - foreach ($databases as $db) { - $dbInfo = $this->getDBCredentials($db); - $oDbMaintainer = new DataBaseMaintenance($dbInfo["host"], $dbInfo["user"], - $dbInfo["pass"]); - CLI::logging("Saving database {$dbInfo["name"]}\n"); - $oDbMaintainer->connect($dbInfo["name"]); - $oDbMaintainer->lockTables(); - $oDbMaintainer->setTempDir($path . "/"); - $oDbMaintainer->backupDataBase($oDbMaintainer->getTempDir() . $dbInfo["name"] . ".sql"); - $oDbMaintainer->unlockTables(); - $dbNames[] = $dbInfo; - } - return $dbNames; - } - - /** - * adds files to the backup archive - */ - private function addToBackup($backup, $filename, $pathRoot, $archiveRoot = "") { - if (is_file($filename)) { - CLI::logging("-> $filename\n"); - $backup->addModify($filename, $archiveRoot, $pathRoot); - } else { - CLI::logging(" + $filename\n"); - $backup->addModify($filename, $archiveRoot, $pathRoot); - //foreach (glob($filename . "/*") as $item) { - // $this->addToBackup($backup, $item, $pathRoot, $archiveRoot); - //} - - } - } - - /** - * Creates a backup archive, which can be used instead of a filename to backup - * - * @param string $filename the backup filename - * @param bool $compress wheter to compress or not - */ - static public function createBackup($filename, $compress = true) { - G::LoadThirdParty('pear/Archive', 'Tar'); - if (!file_exists(dirname($filename))) - mkdir(dirname($filename)); - if (file_exists($filename)) - unlink ($filename); - $backup = new Archive_Tar($filename); - return $backup; - } - - /** - * create a backup of this workspace - * - * Exports the database and copies the files to an archive specified, so this - * workspace can later be restored. - * - * @param string|archive $filename archive filename to use as backup or - * archive object created by createBackup - * @param bool $compress specifies wheter the backup is compressed or not - */ - public function backup($backupFile, $compress = true) { - /* $filename can be a string, in which case it's used as the filename of - * the backup, or it can be a previously created tar, which allows for - * multiple workspaces in one backup. + /** + * Print workspace information + * + * @param bool $printSysInfo include sys info as well or not */ - if (!$this->workspaceExists()) { - throw new Exception("Workspace '{$this->name}' not found"); - } - if (is_string($backupFile)) { - $backup = $this->createBackup($backupFile); - $filename = $backupFile; - } else { - $backup = $backupFile; - $filename = $backup->_tarname; - } - if (!file_exists(PATH_DATA . "upgrade/")) - mkdir(PATH_DATA . "upgrade/"); - $tempDirectory = PATH_DATA . "upgrade/" . basename(tempnam(__FILE__, '')); - mkdir($tempDirectory); - $metadata = $this->getMetadata(); - CLI::logging("Backing up database...\n"); - $metadata["databases"] = $this->exportDatabase($tempDirectory); - $metadata["directories"] = array("{$this->name}.files"); - $metadata["version"] = 1; - $metaFilename = "$tempDirectory/{$this->name}.meta"; - /* Write metadata to file, but make it prettier before. The metadata is just - * a JSON codified array. - */ - if (!file_put_contents($metaFilename, - str_replace(array(",", "{", "}"), array(",\n ", "{\n ", "\n}\n"), - G::json_encode($metadata)))) { - throw new Exception("Could not create backup metadata"); - } - CLI::logging("Copying database to backup...\n"); - $this->addToBackup($backup, $tempDirectory, $tempDirectory); - CLI::logging("Copying files to backup...\n"); - - $this->addToBackup($backup, $this->path, $this->path, "{$this->name}.files"); - //Remove leftovers. - G::rm_dir($tempDirectory); - } - - //TODO: Move to class.dbMaintenance.php - /** - * create a user in the database - * - * Create a user specified by the parameters and grant all priviledges for - * the database specified, when the user connects from the hostname. - * Drops the user if it already exists. - * This function only supports MySQL. - * - * @param string $username username - * @param string $password password - * @param string $hostname the hostname the user will be connecting from - * @param string $database the database to grant permissions - */ - private function createDBUser($username, $password, $hostname, $database) { - mysql_select_db("mysql"); - $hostname = array_shift(explode(":", $hostname)); - $sqlstmt = "SELECT * FROM user WHERE user = '$username' AND host = '$hostname'"; - $result = mysql_query($sqlstmt); - if ($result === false) - throw new Exception("Unable to retrieve users: " . mysql_error ()); - $users = mysql_num_rows($result); - if ($users != 0) { - $result = mysql_query("DROP USER '$username'@'$hostname'"); - if ($result === false) - throw new Exception("Unable to drop user: " . mysql_error ()); - } - CLI::logging("Creating user $username for $hostname\n"); - $result = mysql_query("CREATE USER '$username'@'$hostname' IDENTIFIED BY '$password'"); - if ($result === false) - throw new Exception("Unable to create user $username: " . mysql_error ()); - $result = mysql_query("GRANT ALL ON $database.* TO '$username'@'$hostname'"); - if ($result === false) - throw new Exception("Unable to grant priviledges to user $username: " . mysql_error ()); - } - - //TODO: Move to class.dbMaintenance.php - /** - * executes a mysql script - * - * This function supports scripts with -- comments in the beginning of a line - * and multi-line statements. - * It does not support other forms of comments (such as /*... or {{...}}). - * - * @param string $filename the script filename - * @param string $database the database to execute this script into - */ - private function executeSQLScript($database, $filename) { - mysql_query("CREATE DATABASE IF NOT EXISTS " . mysql_real_escape_string($database)); - mysql_select_db($database); - $script = file_get_contents($filename); - $lines = explode("\n", $script); - $previous = NULL; - foreach ($lines as $j => $line) { - // Remove comments from the script - $line = trim($line); - if (strpos($line, "--") === 0) { - $line = substr($line, 0, strpos($line, "--")); - } - if (empty($line)) - continue; - // Concatenate the previous line, if any, with the current - if ($previous) - $line = $previous . " " . $line; - $previous = NULL; - // If the current line doesnt end with ; then put this line together - // with the next one, thus supporting multi-line statements. - if (strrpos($line, ";") != strlen($line) - 1) { - $previous = $line; - continue; - } - $line = substr($line, 0, strrpos($line, ";")); - $result = mysql_query($line); - if ($result === false) - throw new Exception("Error when running script '$filename', line $j, query '$line': " . mysql_error ()); - } - } - - static public function restoreLegacy($directory) { - throw new Exception("Use gulliver to restore backups from old versions"); - } - - static public function getBackupInfo($filename) { - G::LoadThirdParty('pear/Archive', 'Tar'); - $backup = new Archive_Tar($filename); - //Get a temporary directory in the upgrade directory - $tempDirectory = PATH_DATA . "upgrade/" . basename(tempnam(__FILE__, '')); - mkdir($tempDirectory); - $metafiles = array(); - foreach ($backup->listContent() as $backupFile) { - $filename = $backupFile["filename"]; - if (strpos($filename, "/") === false && substr_compare($filename, ".meta", -5, 5, true) === 0) { - if (!$backup->extractList(array($filename), $tempDirectory)) - throw new Exception("Could not extract backup"); - $metafiles[] = "$tempDirectory/$filename"; - } - } - - CLI::logging("Found " . count($metafiles) . " workspace(s) in backup\n"); - - foreach ($metafiles as $metafile) { - $data = file_get_contents($metafile); - $workspaceData = G::json_decode($data); - CLI::logging("\n"); - workspaceTools::printInfo((array)$workspaceData); - - } - - G::rm_dir($tempDirectory); - } - - static public function dirPerms($filename, $owner, $group, $perms) { - $chown = @chown($filename, $owner); - $chgrp = @chgrp($filename, $group); - $chmod = @chmod($filename, $perms); - if ($chgrp === false || $chmod === false || $chown === false) - CLI::logging (CLI::error ("Failed to set permissions for $filename") . "\n"); - if (is_dir($filename)) { - foreach (array_merge(glob($filename . "/*"), glob($filename . "/.*")) as $item) { - if (basename($item) == "." || basename($item) == "..") - continue; - workspaceTools::dirPerms($item, $owner, $group, $perms); - } - } - } - - /** - * restore an archive into a workspace - * - * Restores any database and files included in the backup, either as a new - * workspace, or overwriting a previous one - * - * @param string $filename the backup filename - * @param string $newWorkspaceName if defined, supplies the name for the - * workspace to restore to - */ - static public function restore($filename, $srcWorkspace, $dstWorkspace = NULL, $overwrite = true) { - G::LoadThirdParty('pear/Archive', 'Tar'); - $backup = new Archive_Tar($filename); - //Get a temporary directory in the upgrade directory - $tempDirectory = PATH_DATA . "upgrade/" . basename(tempnam(__FILE__, '')); - $parentDirectory = PATH_DATA . "upgrade"; - if (is_writable($parentDirectory)) { - mkdir($tempDirectory); - } else { - throw new Exception("Could not create directory:" . $parentDirectory); - } - //Extract all backup files, including database scripts and workspace files - if (!$backup->extract($tempDirectory)) { - throw new Exception("Could not extract backup"); - } - //Search for metafiles in the new standard (the old standard would contain - //txt files). - $metaFiles = glob($tempDirectory . "/*.meta"); - if (empty($metaFiles)) { - $metaFiles = glob($tempDirectory . "/*.txt"); - if (!empty($metaFiles)) - return workspaceTools::restoreLegacy($tempDirectory); - else - throw new Exception("No metadata found in backup"); - } else { - CLI::logging("Found " . count($metaFiles) . " workspaces in backup:\n"); - foreach ($metaFiles as $metafile) - CLI::logging("-> " . basename($metafile) . "\n"); - } - if (count($metaFiles) > 1 && (!isset($srcWorkspace))) - throw new Exception("Multiple workspaces in backup but no workspace specified to restore"); - if (isset($srcWorkspace) && !in_array("$srcWorkspace.meta", array_map(basename, $metaFiles))) - throw new Exception("Workspace $srcWorkspace not found in backup"); - foreach ($metaFiles as $metaFile) { - $metadata = G::json_decode(file_get_contents($metaFile)); - if ($metadata->version != 1) - throw new Exception("Backup version {$metadata->version} not supported"); - $backupWorkspace = $metadata->WORKSPACE_NAME; - if (isset($dstWorkspace)) { - $workspaceName = $dstWorkspace; - $createWorkspace = true; - } else { - $workspaceName = $metadata->WORKSPACE_NAME; - $createWorkspace = false; - } - if (isset($srcWorkspace) && strcmp($metadata->WORKSPACE_NAME, $srcWorkspace) != 0) { - CLI::logging(CLI::warning("> Workspace $backupWorkspace found, but not restoring.") . "\n"); - continue; - } else { - CLI::logging("> Restoring " . CLI::info($backupWorkspace) . " to " . CLI::info($workspaceName) . "\n"); - } - $workspace = new workspaceTools($workspaceName); - if ($workspace->workspaceExists()) - if ($overwrite) - CLI::logging(CLI::warning("> Workspace $workspaceName already exist, overwriting!") . "\n"); - else - throw new Exception("Destination workspace already exist (use -o to overwrite)"); - - if (file_exists($workspace->path)) { - G::rm_dir($workspace->path); - } - foreach ($metadata->directories as $dir) { - CLI::logging("+> Restoring directory '$dir'\n"); - - if (!rename("$tempDirectory/$dir", $workspace->path)) { - throw new Exception("There was an error copying the backup files ($tempDirectory/$dir) to the workspace directory {$workspace->path}."); + public function printMetadata ($printSysInfo = true) + { + if ($printSysInfo) { + workspaceTools::printSysInfo(); + CLI::logging( "\n" ); } - } - - CLI::logging("> Changing file permissions\n"); - $shared_stat = stat(PATH_DATA); - if ($shared_stat !== false) - workspaceTools::dirPerms($workspace->path, $shared_stat['uid'], $shared_stat['gid'], $shared_stat['mode']); - else - CLI::logging(CLI::error ("Could not get the shared folder permissions, not changing workspace permissions") . "\n"); - - list($dbHost, $dbUser, $dbPass) = @explode(SYSTEM_HASH, G::decrypt(HASH_INSTALLATION, SYSTEM_HASH)); - - CLI::logging("> Connecting to system database in '$dbHost'\n"); - $link = mysql_connect($dbHost, $dbUser, $dbPass); - @mysql_query("SET NAMES 'utf8';"); - if (!$link) - throw new Exception('Could not connect to system database: ' . mysql_error()); - - $newDBNames = $workspace->resetDBInfo($dbHost, $createWorkspace); - - foreach ($metadata->databases as $db) { - $dbName = $newDBNames[$db->name]; - CLI::logging("+> Restoring database {$db->name} to $dbName\n"); - $workspace->executeSQLScript($dbName, "$tempDirectory/{$db->name}.sql"); - $workspace->createDBUser($dbName, $db->pass, "localhost", $dbName); - $workspace->createDBUser($dbName, $db->pass, "%", $dbName); - } - - $workspace->upgradeCacheView(false); - - mysql_close($link); - + workspaceTools::printInfo( $this->getMetadata() ); } - CLI::logging("Removing temporary files\n"); + /** + * exports this workspace database to the specified path + * + * This function is used mainly for backup purposes. + * + * @param string $path the directory where to create the sql files + */ + public function exportDatabase ($path) + { + $dbInfo = $this->getDBInfo(); + $databases = array ("wf","rp","rb" + ); + $dbNames = array (); + foreach ($databases as $db) { + $dbInfo = $this->getDBCredentials( $db ); + $oDbMaintainer = new DataBaseMaintenance( $dbInfo["host"], $dbInfo["user"], $dbInfo["pass"] ); + CLI::logging( "Saving database {$dbInfo["name"]}\n" ); + $oDbMaintainer->connect( $dbInfo["name"] ); + $oDbMaintainer->lockTables(); + $oDbMaintainer->setTempDir( $path . "/" ); + $oDbMaintainer->backupDataBase( $oDbMaintainer->getTempDir() . $dbInfo["name"] . ".sql" ); + $oDbMaintainer->unlockTables(); + $dbNames[] = $dbInfo; + } + return $dbNames; + } - G::rm_dir($tempDirectory); + /** + * adds files to the backup archive + */ + private function addToBackup ($backup, $filename, $pathRoot, $archiveRoot = "") + { + if (is_file( $filename )) { + CLI::logging( "-> $filename\n" ); + $backup->addModify( $filename, $archiveRoot, $pathRoot ); + } else { + CLI::logging( " + $filename\n" ); + $backup->addModify( $filename, $archiveRoot, $pathRoot ); + //foreach (glob($filename . "/*") as $item) { + // $this->addToBackup($backup, $item, $pathRoot, $archiveRoot); + //} - CLI::logging(CLI::info("Done restoring") . "\n"); - } + } + } + + /** + * Creates a backup archive, which can be used instead of a filename to backup + * + * @param string $filename the backup filename + * @param bool $compress wheter to compress or not + */ + static public function createBackup ($filename, $compress = true) + { + G::LoadThirdParty( 'pear/Archive', 'Tar' ); + if (! file_exists( dirname( $filename ) )) { + mkdir( dirname( $filename ) ); + } + if (file_exists( $filename )) { + unlink( $filename ); + } + $backup = new Archive_Tar( $filename ); + return $backup; + } + + /** + * create a backup of this workspace + * + * Exports the database and copies the files to an archive specified, so this + * workspace can later be restored. + * + * @param string|archive $filename archive filename to use as backup or + * archive object created by createBackup + * @param bool $compress specifies wheter the backup is compressed or not + */ + public function backup ($backupFile, $compress = true) + { + /* $filename can be a string, in which case it's used as the filename of + * the backup, or it can be a previously created tar, which allows for + * multiple workspaces in one backup. + */ + if (! $this->workspaceExists()) { + throw new Exception( "Workspace '{$this->name}' not found" ); + } + if (is_string( $backupFile )) { + $backup = $this->createBackup( $backupFile ); + $filename = $backupFile; + } else { + $backup = $backupFile; + $filename = $backup->_tarname; + } + if (! file_exists( PATH_DATA . "upgrade/" )) { + mkdir( PATH_DATA . "upgrade/" ); + } + $tempDirectory = PATH_DATA . "upgrade/" . basename( tempnam( __FILE__, '' ) ); + mkdir( $tempDirectory ); + $metadata = $this->getMetadata(); + CLI::logging( "Backing up database...\n" ); + $metadata["databases"] = $this->exportDatabase( $tempDirectory ); + $metadata["directories"] = array ("{$this->name}.files" + ); + $metadata["version"] = 1; + $metaFilename = "$tempDirectory/{$this->name}.meta"; + /* Write metadata to file, but make it prettier before. The metadata is just + * a JSON codified array. + */ + if (! file_put_contents( $metaFilename, str_replace( array (",","{","}" + ), array (",\n ","{\n ","\n}\n" + ), G::json_encode( $metadata ) ) )) { + throw new Exception( "Could not create backup metadata" ); + } + CLI::logging( "Copying database to backup...\n" ); + $this->addToBackup( $backup, $tempDirectory, $tempDirectory ); + CLI::logging( "Copying files to backup...\n" ); + + $this->addToBackup( $backup, $this->path, $this->path, "{$this->name}.files" ); + //Remove leftovers. + G::rm_dir( $tempDirectory ); + } + + //TODO: Move to class.dbMaintenance.php + /** + * create a user in the database + * + * Create a user specified by the parameters and grant all priviledges for + * the database specified, when the user connects from the hostname. + * Drops the user if it already exists. + * This function only supports MySQL. + * + * @param string $username username + * @param string $password password + * @param string $hostname the hostname the user will be connecting from + * @param string $database the database to grant permissions + */ + private function createDBUser ($username, $password, $hostname, $database) + { + mysql_select_db( "mysql" ); + $hostname = array_shift( explode( ":", $hostname ) ); + $sqlstmt = "SELECT * FROM user WHERE user = '$username' AND host = '$hostname'"; + $result = mysql_query( $sqlstmt ); + if ($result === false) { + throw new Exception( "Unable to retrieve users: " . mysql_error() ); + } + $users = mysql_num_rows( $result ); + if ($users != 0) { + $result = mysql_query( "DROP USER '$username'@'$hostname'" ); + if ($result === false) { + throw new Exception( "Unable to drop user: " . mysql_error() ); + } + } + CLI::logging( "Creating user $username for $hostname\n" ); + $result = mysql_query( "CREATE USER '$username'@'$hostname' IDENTIFIED BY '$password'" ); + if ($result === false) { + throw new Exception( "Unable to create user $username: " . mysql_error() ); + } + $result = mysql_query( "GRANT ALL ON $database.* TO '$username'@'$hostname'" ); + if ($result === false) { + throw new Exception( "Unable to grant priviledges to user $username: " . mysql_error() ); + } + } + + //TODO: Move to class.dbMaintenance.php + /** + * executes a mysql script + * + * This function supports scripts with -- comments in the beginning of a line + * and multi-line statements. + * It does not support other forms of comments (such as /*... or {{...}}). + * + * @param string $filename the script filename + * @param string $database the database to execute this script into + */ + private function executeSQLScript ($database, $filename) + { + mysql_query( "CREATE DATABASE IF NOT EXISTS " . mysql_real_escape_string( $database ) ); + mysql_select_db( $database ); + $script = file_get_contents( $filename ); + $lines = explode( "\n", $script ); + $previous = null; + foreach ($lines as $j => $line) { + // Remove comments from the script + $line = trim( $line ); + if (strpos( $line, "--" ) === 0) { + $line = substr( $line, 0, strpos( $line, "--" ) ); + } + if (empty( $line )) { + continue; + } + // Concatenate the previous line, if any, with the current + if ($previous) { + $line = $previous . " " . $line; + } + $previous = null; + // If the current line doesnt end with ; then put this line together + // with the next one, thus supporting multi-line statements. + if (strrpos( $line, ";" ) != strlen( $line ) - 1) { + $previous = $line; + continue; + } + $line = substr( $line, 0, strrpos( $line, ";" ) ); + $result = mysql_query( $line ); + if ($result === false) { + throw new Exception( "Error when running script '$filename', line $j, query '$line': " . mysql_error() ); + } + } + } + + static public function restoreLegacy ($directory) + { + throw new Exception( "Use gulliver to restore backups from old versions" ); + } + + static public function getBackupInfo ($filename) + { + G::LoadThirdParty( 'pear/Archive', 'Tar' ); + $backup = new Archive_Tar( $filename ); + //Get a temporary directory in the upgrade directory + $tempDirectory = PATH_DATA . "upgrade/" . basename( tempnam( __FILE__, '' ) ); + mkdir( $tempDirectory ); + $metafiles = array (); + foreach ($backup->listContent() as $backupFile) { + $filename = $backupFile["filename"]; + if (strpos( $filename, "/" ) === false && substr_compare( $filename, ".meta", - 5, 5, true ) === 0) { + if (! $backup->extractList( array ($filename + ), $tempDirectory )) { + throw new Exception( "Could not extract backup" ); + } + $metafiles[] = "$tempDirectory/$filename"; + } + } + + CLI::logging( "Found " . count( $metafiles ) . " workspace(s) in backup\n" ); + + foreach ($metafiles as $metafile) { + $data = file_get_contents( $metafile ); + $workspaceData = G::json_decode( $data ); + CLI::logging( "\n" ); + workspaceTools::printInfo( (array) $workspaceData ); + + } + + G::rm_dir( $tempDirectory ); + } + + static public function dirPerms ($filename, $owner, $group, $perms) + { + $chown = @chown( $filename, $owner ); + $chgrp = @chgrp( $filename, $group ); + $chmod = @chmod( $filename, $perms ); + if ($chgrp === false || $chmod === false || $chown === false) { + CLI::logging( CLI::error( "Failed to set permissions for $filename" ) . "\n" ); + } + if (is_dir( $filename )) { + foreach (array_merge( glob( $filename . "/*" ), glob( $filename . "/.*" ) ) as $item) { + if (basename( $item ) == "." || basename( $item ) == "..") { + continue; + } + workspaceTools::dirPerms( $item, $owner, $group, $perms ); + } + } + } + + /** + * restore an archive into a workspace + * + * Restores any database and files included in the backup, either as a new + * workspace, or overwriting a previous one + * + * @param string $filename the backup filename + * @param string $newWorkspaceName if defined, supplies the name for the + * workspace to restore to + */ + static public function restore ($filename, $srcWorkspace, $dstWorkspace = null, $overwrite = true) + { + G::LoadThirdParty( 'pear/Archive', 'Tar' ); + $backup = new Archive_Tar( $filename ); + //Get a temporary directory in the upgrade directory + $tempDirectory = PATH_DATA . "upgrade/" . basename( tempnam( __FILE__, '' ) ); + $parentDirectory = PATH_DATA . "upgrade"; + if (is_writable( $parentDirectory )) { + mkdir( $tempDirectory ); + } else { + throw new Exception( "Could not create directory:" . $parentDirectory ); + } + //Extract all backup files, including database scripts and workspace files + if (! $backup->extract( $tempDirectory )) { + throw new Exception( "Could not extract backup" ); + } + //Search for metafiles in the new standard (the old standard would contain + //txt files). + $metaFiles = glob( $tempDirectory . "/*.meta" ); + if (empty( $metaFiles )) { + $metaFiles = glob( $tempDirectory . "/*.txt" ); + if (! empty( $metaFiles )) { + return workspaceTools::restoreLegacy( $tempDirectory ); + } else { + throw new Exception( "No metadata found in backup" ); + } + } else { + CLI::logging( "Found " . count( $metaFiles ) . " workspaces in backup:\n" ); + foreach ($metaFiles as $metafile) { + CLI::logging( "-> " . basename( $metafile ) . "\n" ); + } + } + if (count( $metaFiles ) > 1 && (! isset( $srcWorkspace ))) { + throw new Exception( "Multiple workspaces in backup but no workspace specified to restore" ); + } + if (isset( $srcWorkspace ) && ! in_array( "$srcWorkspace.meta", array_map( BASENAME, $metaFiles ) )) { + throw new Exception( "Workspace $srcWorkspace not found in backup" ); + } + foreach ($metaFiles as $metaFile) { + $metadata = G::json_decode( file_get_contents( $metaFile ) ); + if ($metadata->version != 1) { + throw new Exception( "Backup version {$metadata->version} not supported" ); + } + $backupWorkspace = $metadata->WORKSPACE_NAME; + if (isset( $dstWorkspace )) { + $workspaceName = $dstWorkspace; + $createWorkspace = true; + } else { + $workspaceName = $metadata->WORKSPACE_NAME; + $createWorkspace = false; + } + if (isset( $srcWorkspace ) && strcmp( $metadata->WORKSPACE_NAME, $srcWorkspace ) != 0) { + CLI::logging( CLI::warning( "> Workspace $backupWorkspace found, but not restoring." ) . "\n" ); + continue; + } else { + CLI::logging( "> Restoring " . CLI::info( $backupWorkspace ) . " to " . CLI::info( $workspaceName ) . "\n" ); + } + $workspace = new workspaceTools( $workspaceName ); + if ($workspace->workspaceExists()) { + if ($overwrite) { + CLI::logging( CLI::warning( "> Workspace $workspaceName already exist, overwriting!" ) . "\n" ); + } else { + throw new Exception( "Destination workspace already exist (use -o to overwrite)" ); + } + } + if (file_exists( $workspace->path )) { + G::rm_dir( $workspace->path ); + } + foreach ($metadata->directories as $dir) { + CLI::logging( "+> Restoring directory '$dir'\n" ); + + if (! rename( "$tempDirectory/$dir", $workspace->path )) { + throw new Exception( "There was an error copying the backup files ($tempDirectory/$dir) to the workspace directory {$workspace->path}." ); + } + + } + + CLI::logging( "> Changing file permissions\n" ); + $shared_stat = stat( PATH_DATA ); + if ($shared_stat !== false) { + workspaceTools::dirPerms( $workspace->path, $shared_stat['uid'], $shared_stat['gid'], $shared_stat['mode'] ); + } else { + CLI::logging( CLI::error( "Could not get the shared folder permissions, not changing workspace permissions" ) . "\n" ); + } + list ($dbHost, $dbUser, $dbPass) = @explode( SYSTEM_HASH, G::decrypt( HASH_INSTALLATION, SYSTEM_HASH ) ); + + CLI::logging( "> Connecting to system database in '$dbHost'\n" ); + $link = mysql_connect( $dbHost, $dbUser, $dbPass ); + @mysql_query( "SET NAMES 'utf8';" ); + if (! $link) { + throw new Exception( 'Could not connect to system database: ' . mysql_error() ); + } + + $newDBNames = $workspace->resetDBInfo( $dbHost, $createWorkspace ); + + foreach ($metadata->databases as $db) { + $dbName = $newDBNames[$db->name]; + CLI::logging( "+> Restoring database {$db->name} to $dbName\n" ); + $workspace->executeSQLScript( $dbName, "$tempDirectory/{$db->name}.sql" ); + $workspace->createDBUser( $dbName, $db->pass, "localhost", $dbName ); + $workspace->createDBUser( $dbName, $db->pass, "%", $dbName ); + } + + $workspace->upgradeCacheView( false ); + + mysql_close( $link ); + + } + + CLI::logging( "Removing temporary files\n" ); + + G::rm_dir( $tempDirectory ); + + CLI::logging( CLI::info( "Done restoring" ) . "\n" ); + } } -?> +