Source of file ModuleUpgrader.php
Size: 17,982 Bytes - Last Modified: 2020-07-03T12:08:09+00:00
/var/www/docs.ssmods.com/process/src/src/ModuleUpgrader.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 | <?php namespace Sunnysideup\UpgradeToSilverstripe4; use Sunnysideup\PHP2CommandLine\PHP2CommandLineSingleton; use Sunnysideup\UpgradeToSilverstripe4\Traits\Creator; class ModuleUpgrader extends ModuleUpgraderBaseWithVariables { use Creator; ############################### # USEFUL COMMANDS ############################### /** * Executes given operations on the PHP2CommandLineSingleton instance * Documentation for this can be found in the PHP2CommandLineSingleton module * * @param string $newDir root dir for ommand * @param string $command actual command * @param string $comment comment * @param boolean $alwaysRun run even if you are just preparing a real run. Default FALSE * @param string $keyNotesLogFileLocation * * @return array */ public function execMe( string $newDir, string $command, string $comment, ?bool $alwaysRun = false, ?string $keyNotesLogFileLocation = '', ?bool $verbose = true ) { if ($keyNotesLogFileLocation) { $this->commandLineExec ->setMakeKeyNotes(true) ->setKeyNotesFileLocation($keyNotesLogFileLocation); } else { $this->commandLineExec ->setMakeKeyNotes(false); } $this->commandLineExec->setErrorMessage(''); if ($this->getBreakOnAllErrors()) { $this->commandLineExec->setErrorMessage(' ------------------------------------------------------------------------ To continue, please use the following parameter: startFrom=' . $this->currentlyRunning . ' e.g. php runme.php startFrom=' . $this->currentlyRunning . ' ------------------------------------------------------------------------ '); } return $this->commandLineExec->execMe($newDir, $command, $comment, $alwaysRun, $verbose); } /** * Executes given operations on the PHP2CommandLineSingleton instance * Documentation for this can be found in the PHP2CommandLineSingleton module */ public function colourPrint($mixedVar, string $colour = 'dark_gray', $newLineCount = 1) { return $this->commandLineExec->colourPrint($mixedVar, $colour, $newLineCount); } ############################### # RUN ############################### /** * Starts the command line output and prints some opening information to the output * also initalises various environment variables */ public function run() { $this->applyRecipe(); $this->colourPrint( '===================== START ======================', 'white', 5 ); $this->loadNextStepInstructions(); $this->loadGlobalVariables(); $this->loadCustomVariablesForTasks(); foreach ($this->arrayOfModules as $moduleDetails) { $hasRun = false; $nextStep = ''; $this->loadVarsForModule($moduleDetails); $this->workOutMethodsToRun(); $this->printVarsForModule($moduleDetails); foreach ($this->listOfTasks as $class => $params) { //get class without number $properClass = current(explode('-', $class)); $nameSpacesArray = explode('\\', $properClass); $shortClassCode = end($nameSpacesArray); if (! class_exists($properClass)) { $properClass = $this->defaultNamespaceForTasks . '\\' . $properClass; } if (class_exists($properClass)) { $runItNow = $this->shouldWeRunIt((string) $class); $params['taskName'] = $shortClassCode; $obj = $properClass::create($this, $params); $taskName = $obj->getTaskName(); if ($taskName) { $params['taskName'] = $taskName; } if ($hasRun && ! $nextStep) { $nextStep = $params['taskName']; } if ($runItNow) { $this->currentlyRunning = $class; $this->colourPrint('# --------------------', 'yellow', 3); $this->colourPrint('# ' . $obj->getTitle() . ' (' . $params['taskName'] . ')', 'yellow'); $this->colourPrint('# --------------------', 'yellow'); $this->colourPrint('# ' . $obj->getDescriptionNice(), 'dark_grey'); $this->colourPrint('# --------------------', 'dark_grey'); $obj->run(); if ($this->runInteractively) { $hasRun = true; if ($this->outOfOrderTask === false) { $this->getSessionManager()->setSessionValue('Completed', $class); } } } else { if (! $this->runInteractively) { $this->colourPrint('# --------------------', 'yellow', 3); $this->colourPrint('# ' . $obj->getTitle() . ' (' . $params['taskName'] . ')', 'yellow'); $this->colourPrint('# --------------------', 'yellow'); $this->colourPrint('# skipped', 'yellow'); $this->colourPrint('# --------------------', 'yellow'); } } $obj = $properClass::deleteTask($params); } else { user_error( $properClass . ' could not be found as class. You can add namespacing to include your own classes.', E_USER_ERROR ); } } $this->colourPrint( '===================== END =======================', 'white', 5 ); $this->colourPrint( 'Next: ' . $nextStep, 'yellow', 5 ); } $this->endPHP2CommandLine(); } public function applyRecipe(?string $recipeName = null) { if ($recipeName === null) { $recipeName = $this->getRecipe(); } if ($recipeName) { if (isset($this->availableRecipes[$recipeName])) { $recipeClass = $this->availableRecipes[$recipeName]; $obj = new $recipeClass(); $vars = $obj->getVariables(); foreach ($vars as $variable => $value) { $methodSet = 'set' . ucwords($variable); $this->{$methodSet}($value); } } else { user_error( 'Recipe ' . $recipeName . ' not available. Available Recipes are: ' . print_r($this->getAvailableRecipes()) ); } } } public function getLastMethodRun(): string { return $this->getSessionManager()->getSessionValue('Completed'); } protected function loadNextStepInstructions() { $this->restartSession = $this->getCommandLineOrArgumentAsBoolean('restart'); $this->runLastOneAgain = $this->getCommandLineOrArgumentAsBoolean('again'); if ($this->getCommandLineOrArgumentAsString('startFrom')) { $this->startFrom = $this->getCommandLineOrArgumentAsString('startFrom'); } if ($this->getCommandLineOrArgumentAsString('endWith')) { $this->endWith = $this->getCommandLineOrArgumentAsString('endWith'); } if ($this->getCommandLineOrArgumentAsString('task')) { $this->onlyRun = $this->getCommandLineOrArgumentAsString('task'); } if ($this->onlyRun) { $this->outOfOrderTask = true; } } protected function loadGlobalVariables() { $this->aboveWebRootDirLocation = $this->checkIfPathExistsAndCleanItUp( $this->aboveWebRootDirLocation ); $this->webRootDirLocation = $this->checkIfPathExistsAndCleanItUp( $this->aboveWebRootDirLocation . '/' . $this->webRootName, true ); $this->themeDirLocation = $this->checkIfPathExistsAndCleanItUp( $this->webRootDirLocation . '/themes', true ); } protected function loadCustomVariablesForTasks() { foreach ($this->customVariablesForTasks as $taskName => $variableAndValue) { foreach ($variableAndValue as $variableName => $variableValue) { $key = $this->positionForTask($taskName); if ($key !== false) { $this->listOfTasks[$taskName][$variableName] = $variableValue; } else { user_error( 'Could not find ' . $taskName . '. Choose from ' . implode(', ', array_keys($this->listOfTasks)) ); die('----'); } } } } /** * Loads in and sets all the meta data for a module from the inputed array * @param array $moduleDetails */ protected function loadVarsForModule($moduleDetails) { //Is Module Upgrade //do this first as a lot of other functions rely on it ... $this->isModuleUpgrade = isset($moduleDetails['IsModuleUpgrade']) ? $moduleDetails['IsModuleUpgrade'] : true; //VendorName $this->vendorName = $moduleDetails['VendorName']; //VendorNamespace if (isset($moduleDetails['VendorNamespace'])) { $this->vendorNamespace = $moduleDetails['VendorNamespace']; } else { $this->vendorNamespace = $this->cleanCamelCase($this->vendorName); } //PackageName $this->packageName = $moduleDetails['PackageName']; //PackageNamespace if (isset($moduleDetails['PackageNamespace'])) { $this->packageNamespace = $moduleDetails['PackageNamespace']; } else { $this->packageNamespace = $this->cleanCamelCase($this->packageName); } if (isset($moduleDetails['GitLink'])) { $this->gitLink = $moduleDetails['GitLink']; } else { $this->gitLink = 'git@github.com:' . $this->vendorName . '/silverstripe-' . $this->packageName . '.git'; } //see: https://stackoverflow.com/questions/5573334/remove-a-part-of-a-string-but-only-when-it-is-at-the-end-of-the-string $gitLinkWithoutExtension = preg_replace('/' . preg_quote('.git', '/') . '$/', '', $this->gitLink); $this->gitLinkAsHTTPS = str_replace( 'git@github.com:', 'https://github.com/', $gitLinkWithoutExtension ); $this->gitLinkAsRawHTTPS = str_replace( 'git@github.com:', 'https://raw.githubusercontent.com/', $gitLinkWithoutExtension ); //Origin Composer FileLocation $this->originComposerFileLocation = $moduleDetails['OriginComposerFileLocation'] ?? ''; $this->workoutPackageFolderName($moduleDetails); //ss4 location if (isset($moduleDetails['VendorAndPackageFolderNameForInstall'])) { $this->vendorAndPackageFolderNameForInstall = $moduleDetails['VendorAndPackageFolderNameForInstall']; } else { $this->vendorAndPackageFolderNameForInstall = strtolower($this->vendorName . '/' . $this->packageName); } //UpgradeAsFork $this->upgradeAsFork = empty($moduleDetails['UpgradeAsFork']) ? false : true; //NameOfBranchForBaseCode $this->nameOfBranchForBaseCode = $moduleDetails['NameOfBranchForBaseCode'] ?? $this->nameOfBranchForBaseCode; //LogFileLocation $this->logFileLocation = ''; if ($this->logFolderDirLocation) { $this->logFileLocation = $this->logFolderDirLocation . '/' . $this->packageName . '-upgrade-log-' . date('Y-m-d') . '.txt'; $this->commandLineExec->setLogFileLocation($this->logFileLocation); } else { $this->commandLineExec->setLogFileLocation(''); } if ($this->restartSession) { $this->getSessionManager()->deleteSession(); } } protected function vendorModuleLocation(): string { return $this->webRootDirLocation . '/vendor/' . $this->vendorName . '/' . $this->packageName; } protected function workoutPackageFolderName(array $moduleDetails) { $this->packageFolderNameForInstall = trim($this->packageFolderNameForInstall); if ($this->packageFolderNameForInstall) { //do nothing } else { $packageFolderNameForInstall = $this->getSessionManager()->getSessionValue( 'PackageFolderNameForInstall' ); if ($packageFolderNameForInstall) { $this->packageFolderNameForInstall = $packageFolderNameForInstall; } else { if (isset($moduleDetails['PackageFolderNameForInstall'])) { $this->packageFolderNameForInstall = $moduleDetails['PackageFolderNameForInstall']; } else { if (! $this->originComposerFileLocation) { $this->originComposerFileLocation = $this->gitLinkAsRawHTTPS . '/master/composer.json'; } if ($this->URLExists($this->originComposerFileLocation)) { $json = file_get_contents($this->originComposerFileLocation); $array = json_decode($json, true); if (isset($array['extra']['installer-name'])) { $this->packageFolderNameForInstall = $array['extra']['installer-name']; } else { $this->packageFolderNameForInstall = $this->getPackageFolderNameBasic(); } } else { $this->packageFolderNameForInstall = $this->getPackageFolderNameBasic(); } } } $this->getSessionManager()->setSessionValue( 'PackageFolderNameForInstall', $this->packageFolderNameForInstall ); } } protected function printVarsForModule(array $moduleDetails) { $obj = new ModuleUpgraderInfo(); return $obj->printVarsForModule($this, $moduleDetails); } /** * work out the current one to run! * @return string */ protected function workOutMethodsToRun() { if ($this->runInteractively) { if ($this->startFrom || $this->endWith) { user_error('In interactive mode you can not set StartFrom / EndWith / OnlyRun.'); } if ($this->onlyRun) { } else { $lastMethod = $this->getLastMethodRun(); if ($lastMethod) { $this->verbose = false; $arrayKeys = array_keys($this->listOfTasks); $found = false; foreach ($arrayKeys as $index => $key) { if ($key === $lastMethod) { $found = true; if ($this->runLastOneAgain) { $this->onlyRun = $arrayKeys[$index]; } else { if (isset($arrayKeys[$index + 1])) { if (isset($this->listOfTasks[$arrayKeys[$index + 1]])) { $this->onlyRun = $arrayKeys[$index + 1]; } else { user_error('Can not find next task: ' . $arrayKeys[$index + 1]); } } else { $this->getSessionManager()->deleteSession(); die(' ========================================== Session has completed. ========================================== '); } } } } if (! $found) { user_error('Did not find next step.'); } } else { $this->verbose = true; reset($this->listOfTasks); $this->onlyRun = key($this->listOfTasks); } } } return $this->onlyRun; } /** * start the method ... * - should we run it? * * @param string $name whatever is listed in the listOfTasks * @return bool */ protected function shouldWeRunIt(string $name): bool { $runMe = true; if ($this->onlyRun) { return $name === $this->onlyRun ? true : false; } if ($this->lastMethodHasBeenRun) { $runMe = false; } else { if ($this->startFrom) { $runMe = false; if ($name === $this->startFrom) { $this->startFrom = ''; $runMe = true; } } if ($this->endWith) { if ($name === $this->endWith) { $this->lastMethodHasBeenRun = true; } } } //here we call the PHP2CommandLine return $runMe; } } |