Exemplo n.º 1
0
 /**
  * Determines if the current entry is a valid SQL update file.
  *
  * @return bool
  */
 public function accept()
 {
     /** @var \DirectoryIterator $this */
     $filename = $this->getFilename();
     if (!$this->isFile() || substr($filename, -4) != '.php' || preg_match('/^sql_(\\d{8}_\\d{6})/', $filename) === 0) {
         return false;
     }
     try {
         $check = Helper::checkFiles($this->getPath(), array($filename));
         if (count($check) == 0) {
             return false;
         }
     } catch (DeployException $exception) {
         return false;
     }
     return true;
 }
Exemplo n.º 2
0
 /**
  * Check if the db_patches table exists, compare it to the locally available patches and ask the user what he wants to do if there's a difference.
  *
  * @param string $action update of rollback
  * @throws \LemonWeb\Deployer\Exceptions\DeployException
  */
 public function check($action)
 {
     $this->logger->log('Check for database updates:', LOG_INFO, true);
     if (empty($this->database_dirs)) {
         return;
     }
     // collect and verify the database login information so the db_patches table can be checked
     $this->getDatabaseLogin(true);
     // make a list of all available patchfiles in de project
     $available_patches = $this->findSQLFiles($action);
     $patches_to_apply = array();
     $patches_to_revert = array();
     $patches_to_register_as_done = array();
     $performed_patches = array();
     $dependencies = array();
     if ($this->patches_table_exists = $this->checkIfPatchTableExists()) {
         // get the list of all performed patches from the database
         list($performed_patches, $dependencies) = $this->findPerformedSQLPatches();
         if (Deploy::UPDATE == $action) {
             // list the patches that have not yet been applied
             $patches_to_apply = array_diff_key($available_patches, $performed_patches);
             // list the patches that have been removed from the project and may need to be reverted
             $patches_to_revert = array_diff_key($performed_patches, $available_patches);
         } elseif (Deploy::ROLLBACK == $action) {
             // find the patches that have been performed on the previous deploy
             foreach ($performed_patches as $datetime => $applied_at) {
                 if (($timestamp = strtotime($applied_at)) && $timestamp > $this->previous_timestamp && $timestamp <= $this->last_timestamp) {
                     $patches_to_revert[$datetime] = $datetime;
                 }
             }
         }
     } else {
         if (Deploy::UPDATE == $action) {
             // make a list of all patches that could be considered as already applied
             $patches_to_apply = $available_patches;
         }
     }
     // nothing needs to be done
     if (empty($patches_to_apply) && empty($patches_to_revert) && empty($patches_to_register_as_done)) {
         $this->logger->log('Database is up to date !');
         return;
     }
     ksort($patches_to_apply, SORT_STRING);
     krsort($patches_to_revert, SORT_STRING);
     ksort($patches_to_register_as_done, SORT_STRING);
     // check if the files all contain SQL patches and filter out inactive patches
     $patches_to_apply = array_intersect($patches_to_apply, array_keys(Helper::checkFiles($this->basedir, $patches_to_apply)));
     $patches_to_apply = $this->checkDependencies($patches_to_apply, $performed_patches);
     $patches_to_revert = $this->checkRevertDependencies($patches_to_revert, $dependencies);
     if (!empty($patches_to_revert)) {
         if (!empty($patches_to_revert)) {
             $this->logger->log('Database patches to revert (' . count($patches_to_revert) . '): ' . PHP_EOL . implode(PHP_EOL, array_keys($patches_to_revert)));
             if (count($patches_to_revert) > 1) {
                 $choice = $this->local_shell->inputPrompt('Revert ? (Y/p/n): ', 'y', false, array('y', 'p', 'n'));
             } else {
                 $choice = $this->local_shell->inputPrompt('Revert ? (Y/n): ', 'y', false, array('y', 'n'));
             }
             if ('y' == $choice) {
                 $this->patches_to_revert += $patches_to_revert;
             } elseif ('p' == $choice) {
                 list($chosen_patches_to_revert) = $this->pickPatches($patches_to_revert, array('y', 'n'));
                 // if the hand-chosen list introduced dependency problems, prompt the user
                 $checked_patches_to_revert = $this->checkRevertDependencies($chosen_patches_to_revert, $dependencies);
                 if (count($checked_patches_to_revert) > 0 && count($checked_patches_to_revert) != count($chosen_patches_to_revert)) {
                     if ('y' == $this->local_shell->inputPrompt('Are you sure ? (y/N): ', 'n', false, array('y', 'n'))) {
                         $this->patches_to_revert += $checked_patches_to_revert;
                     }
                 } else {
                     $this->patches_to_revert += $checked_patches_to_revert;
                 }
             }
         }
     }
     if (!empty($patches_to_apply)) {
         if (!empty($patches_to_apply)) {
             $patches_list = 'Database patches to apply (' . count($patches_to_apply) . '): ' . PHP_EOL;
             foreach ($patches_to_apply as $patch_filename) {
                 $patches_list .= $patch_filename;
                 $patch_classname = Helper::getClassnameFromFilepath($patch_filename);
                 /** @var AbstractSqlUpdate $patch */
                 $patch = new $patch_classname(array('charset' => $this->database_charset));
                 if ($patch->getType() == SqlUpdateInterface::TYPE_LARGE) {
                     $patches_list .= " [Large]";
                 }
                 $patches_list .= PHP_EOL;
             }
             $this->logger->log($patches_list);
             // only offer to register patches as done if the patches table exists
             if ($this->patches_table_exists) {
                 if (count($patches_to_apply) > 1) {
                     $choice = $this->local_shell->inputPrompt('[a]pply, [r]egister as done, [p]ick, [i]gnore (A/r/p/i): ', 'a', false, array('a', 'r', 'p', 'i'));
                 } else {
                     $choice = $this->local_shell->inputPrompt('[a]pply, [r]egister as done, [i]gnore (A/r/i): ', 'a', false, array('a', 'r', 'i'));
                 }
             } else {
                 if (count($patches_to_apply) > 1) {
                     $choice = $this->local_shell->inputPrompt('[a]pply, [p]ick, [i]gnore (A/p/i): ', 'a', false, array('a', 'p', 'i'));
                 } else {
                     $choice = $this->local_shell->inputPrompt('[a]pply, [i]gnore (A/i): ', 'a', false, array('a', 'i'));
                 }
             }
             if ('a' == $choice) {
                 $this->patches_to_apply += $patches_to_apply;
             } elseif ('r' == $choice) {
                 $this->patches_to_register_as_done += $patches_to_apply;
             } elseif ('p' == $choice) {
                 list($picked_apply, $picked_register) = $this->pickPatches($patches_to_apply, array('a', 'r', 'i'), 'a');
                 // if the hand-chosen list introduced dependency problems, prompt the user
                 $checked_patches_to_apply = $this->checkDependencies($picked_apply, $performed_patches + $picked_register);
                 if (count($checked_patches_to_apply) > 0 && count($checked_patches_to_apply) != count($picked_apply)) {
                     if ('y' == $this->local_shell->inputPrompt('Are you sure ? (y/N)', 'n', false, array('y', 'n'))) {
                         $this->patches_to_apply += $picked_apply;
                         $this->patches_to_register_as_done += $picked_register;
                     }
                 } else {
                     $this->patches_to_apply += $checked_patches_to_apply;
                     $this->patches_to_register_as_done += $picked_register;
                 }
             }
         }
     }
     if (!empty($patches_to_register_as_done)) {
         $patches_to_register_as_done = $this->checkDependencies($patches_to_register_as_done, array_keys($this->patches_to_apply) + array_keys($performed_patches));
         if (!empty($patches_to_register_as_done)) {
             $patches_list = 'Other patches found (' . count($patches_to_register_as_done) . '): ' . PHP_EOL;
             foreach ($patches_to_register_as_done as $patch_filename) {
                 $patches_list .= $patch_filename;
                 $patch_classname = Helper::getClassnameFromFilepath($patch_filename);
                 /** @var AbstractSqlUpdate $patch */
                 $patch = new $patch_classname();
                 if ($patch->getType() == SqlUpdateInterface::TYPE_LARGE) {
                     $patches_list .= " [Large]";
                 }
                 $patches_list .= PHP_EOL;
             }
             $this->logger->log($patches_list);
             if (count($patches_to_register_as_done) > 1) {
                 $choice = $this->local_shell->inputPrompt('[a]pply, [r]egister as done, [p]ick, [i]gnore (a/r/p/I): ', 'i', false, array('a', 'r', 'p', 'i'));
             } else {
                 $choice = $this->local_shell->inputPrompt('[a]pply, [r]egister as done, [i]gnore (a/r/I): ', 'i', false, array('a', 'r', 'i'));
             }
             if ('a' == $choice) {
                 $this->patches_to_apply += $patches_to_register_as_done;
             } elseif ('r' == $choice) {
                 $this->patches_to_register_as_done += $patches_to_register_as_done;
             } elseif ('p' == $choice) {
                 list($picked_apply, $picked_register) = $this->pickPatches($patches_to_register_as_done, array('a', 'r', 'i'), 'i');
                 $this->patches_to_apply += $picked_apply;
                 $this->patches_to_register_as_done += $picked_register;
             }
         }
     }
     if (empty($this->patches_to_apply) && empty($this->patches_to_register_as_done) && empty($this->patches_to_revert)) {
         return;
     }
     $this->getDatabaseLogin();
 }
Exemplo n.º 3
0
 /**
  * @param array $files The SQL update files that should be executed
  */
 public function setUpdateFiles($files)
 {
     $this->sql_patch_objects = DatabaseHelper::checkFiles($this->rootpath, $files, $this->patchOptions);
 }
Exemplo n.º 4
0
 /**
  * @param array $files The SQL update files that should be executed
  */
 public function setUpdateFiles($files)
 {
     $this->sql_patch_objects = DatabaseHelper::checkFiles($this->rootpath, $files, array('charset' => $this->charset));
 }