Spaces:
Sleeping
Sleeping
| #!/usr/bin/env php | |
| $scriptDir = dirname(__FILE__) . '/'; | |
| class Patch { | |
| /** | |
| * Install the patch specified | |
| * @param type $address Location hotfix file | |
| * @param type $patch Name of the hotfix file | |
| * @return int Return 0 when an error occurs | |
| */ | |
| public function add_patch($address = '', $patch = '') { | |
| echo "Add patch on Processmaker ...\n"; | |
| if ($address != '') { | |
| if(! $this->copy_patch(trim($address))){ | |
| return; | |
| } | |
| } | |
| $this->remove_temporals(); | |
| if ($patch == '') { | |
| $patch = basename($address); | |
| } | |
| if (!$this->untar_patch($patch)) { | |
| return false; | |
| } | |
| // Backup files listed on changes.log file | |
| echo "Backup files\n"; | |
| $changeLog = fopen(PROCESSMAKER_PATH . 'shared/patches/processmaker/changes.log', 'r'); | |
| while (!feof($changeLog)) { | |
| $linea = trim(fgets($changeLog)); | |
| // Backup file and then replace | |
| $s1 = substr(PROCESSMAKER_PATH, 0, strpos(PROCESSMAKER_PATH, 'processmaker')) | |
| . $linea; | |
| // Location where must be the original | |
| $s2 = PROCESSMAKER_PATH . 'shared/patches/original/' . $linea; | |
| if (!is_file($s2)) { | |
| if (!is_dir(substr($s2, 0, strrpos($s2, "/")))) { | |
| mkdir(substr($s2, 0, strrpos($s2, "/")), 0777, true); | |
| } | |
| if (is_file($s1)) { | |
| echo $s1."\n"; | |
| copy($s1, $s2); | |
| } | |
| } | |
| } | |
| fclose($changeLog); | |
| echo "Apply changes ...\n"; | |
| $this->copy_directory(PROCESSMAKER_PATH | |
| . '/shared/patches/processmaker', PROCESSMAKER_PATH); | |
| $this->remove_temporals(); | |
| echo "Patch installed sucessfully\n"; | |
| } | |
| /** | |
| * Utar the hotfix file | |
| * @return boolean true or false | |
| */ | |
| public function untar_patch($patch) { | |
| echo "Untar patch file\n"; | |
| $p = new PharData(PROCESSMAKER_PATH . 'shared/patches/'.$patch); | |
| if ($p->extractTo(PROCESSMAKER_PATH . 'shared/patches')) { | |
| echo "Untar sucessfull\n"; | |
| return true; | |
| } else { | |
| echo "Error to untar patch file.\n"; | |
| return false; | |
| } | |
| } | |
| /** | |
| * This method list of origin version and patches | |
| */ | |
| public function list_patches() { | |
| echo "The available versions are:\n"; | |
| $original_version = ''; | |
| if (is_file(PROCESSMAKER_PATH . | |
| 'shared/patches/original/processmaker/workflow/engine/' . | |
| 'methods/login/version-pmos.php')) { | |
| $original_version = $this->get_version(PROCESSMAKER_PATH . | |
| 'shared/patches/original/processmaker/workflow/engine/' . | |
| 'methods/login/version-pmos.php'); | |
| } else { | |
| $original_version = $this->get_version(PROCESSMAKER_PATH . | |
| 'workflow/engine/methods/login/version-pmos.php'); | |
| } | |
| $current_installation = $this->get_version(PROCESSMAKER_PATH . | |
| 'workflow/engine/methods/login/version-pmos.php'); | |
| echo "Original version:\n"; | |
| echo $original_version . "\n"; | |
| echo "Patch installed:\n"; | |
| $directory = opendir(PROCESSMAKER_PATH . 'shared/patches'); | |
| while ($file = readdir($directory)) { | |
| if (!is_dir($file) && strpos($file,'.tar')) { | |
| if ( str_replace($file,'.tar','')==$current_installation) { | |
| echo $file . " *\n"; | |
| } else { | |
| echo $file . "\n"; | |
| } | |
| } | |
| } | |
| } | |
| /** | |
| * This method is used to obtain the current version or the original | |
| * @param type $address File location with version | |
| * @return type Returns the version of ProcessMaker requested | |
| */ | |
| private function get_version($address) { | |
| $result = ''; | |
| $file = fopen($address, 'r'); | |
| while (!feof($file)) { | |
| $linea = trim(fgets($file)); | |
| if (strpos($linea, 'PM_VERSION')) { | |
| $result = substr($linea, strpos($linea, ", ") + 3); | |
| $result = substr($result,0,strlen($result)-3); | |
| } | |
| } | |
| fclose($file); | |
| return $result; | |
| } | |
| /** | |
| * You change the version of a hotfix available | |
| * @param type $hotfix_version | |
| */ | |
| public function rollback_patch($patch_version) { | |
| echo "Rollback to ".$patch_version."\n"; | |
| $this->register('rollback_patch ' . $patch_version); | |
| $this->rollback_origin(); | |
| if (strpos($patch_version, '.tar')) { | |
| $this->add_patch('', $patch_version); | |
| } | |
| } | |
| /** | |
| * Installation returns to its original state. | |
| */ | |
| private function rollback_origin() { | |
| echo "Rollback to original state\n"; | |
| $this->copy_directory(PROCESSMAKER_PATH . | |
| '/shared/patches/original/processmaker', PROCESSMAKER_PATH); | |
| echo "Rollback to original state sucessfull\n"; | |
| } | |
| /** | |
| * Copy a entire directory | |
| * @param type $source Location of files to copy | |
| * @param type $target Destination to be copied | |
| */ | |
| private function copy_directory($source, $target) { | |
| if (is_dir($source)) { | |
| @mkdir($target); | |
| $d = dir($source); | |
| while (FALSE !== ( $entry = $d->read() )) { | |
| if ($entry == '.' || $entry == '..') { | |
| continue; | |
| } | |
| $Entry = $source . '/' . $entry; | |
| if (is_dir($Entry)) { | |
| $this->copy_directory($Entry, $target . '/' . $entry); | |
| continue; | |
| } | |
| copy($Entry, $target . '/' . $entry); | |
| } | |
| $d->close(); | |
| } else { | |
| copy($source, $target); | |
| } | |
| } | |
| /** | |
| * This function remove a folder complete | |
| * @param type $address Folder to remove | |
| * @return type true or false | |
| */ | |
| private function delete_directory($address) { | |
| $files = array_diff(scandir($address), array('.', '..')); | |
| foreach ($files as $file) { | |
| (is_dir("$address/$file")) ? | |
| $this->delete_directory("$address/$file") : | |
| unlink("$address/$file"); | |
| } | |
| return rmdir($address); | |
| } | |
| /** | |
| * Remove the temporal folder for install hotfix | |
| */ | |
| private function remove_temporals() { | |
| echo "Removing temporals files\n"; | |
| if (is_Dir(PROCESSMAKER_PATH . "shared/patches/processmaker")) { | |
| $this->delete_directory(PROCESSMAKER_PATH . "shared/patches/processmaker"); | |
| } | |
| } | |
| /** | |
| * Copy the hotfix and create shared/hotfixes | |
| * @param type $address Ubicación del hotfix | |
| * @return boolean falso en caso de q no exista el archivo hotfix | |
| */ | |
| private function copy_patch($address) { | |
| echo "Copy hotfix file to shared/hotfixes\n"; | |
| $this->verify_directory(); | |
| // Verify that the address is correct hotfix | |
| if (is_file($address)) { | |
| copy($address, PROCESSMAKER_PATH . "shared/patches/" . basename($address)); | |
| } else { | |
| echo 'The file route is incorrect, please check the route\n'; | |
| return false; | |
| } | |
| return true; | |
| } | |
| private function verify_directory(){ | |
| // Verify that there is a shared/hotfixes directory exist | |
| if (!is_Dir(PROCESSMAKER_PATH . "shared/patches")) { | |
| mkdir(PROCESSMAKER_PATH . "shared/patches", 0777); | |
| } | |
| } | |
| /** | |
| * Add a log message in the patches.log file | |
| * @param type $log | |
| */ | |
| private function register($log) { | |
| $this->verify_directory(); | |
| $file = fopen(PROCESSMAKER_PATH . 'shared/patches/patches.log', "a"); | |
| $message = date('l jS \of F Y h:i:s A') . ' ' . $log . PHP_EOL; | |
| fwrite($file, $message); | |
| fclose($file); | |
| } | |
| } | |
| define('PROCESSMAKER_PATH', $scriptDir); | |
| $p = new Patch(); | |
| switch (isset($argv[1]) ? $argv[1] : "-h") { | |
| case "-l": | |
| $p->list_patches(); | |
| break; | |
| case "-a": | |
| $p->add_patch($argv[2]); | |
| break; | |
| case "-r": | |
| $p->rollback_patch($argv[2]); | |
| break; | |
| case "-h": | |
| default: | |
| echo "-a <directory>/patch.tar _add/install a patch from a file parameter\n"; | |
| echo "-r patch_name _remove/uninstall a patch\n"; | |
| echo "-l _list all patches installed in processmaker\n"; | |
| echo "-h _help list the options in the patch tool\n"; | |
| } | |