Beispiel #1
0
 /**
  * Applies a series of SQL patches to the database and registers them in the db_patches table.
  *
  * @param bool $register_only Only register the patches as done, don't run their code
  * @throws \LemonWeb\Deployer\Exceptions\DatabaseException
  */
 public function update($register_only = false)
 {
     $this->logger->log('Database update: ' . implode(', ', array_keys($this->sql_patch_objects)), LOG_DEBUG, true);
     if (!count($this->sql_patch_objects)) {
         return;
     }
     foreach ($this->sql_patch_objects as $filename => $sql_patch_object) {
         $patch_name = DatabaseHelper::getClassnameFromFilepath($filename);
         $patch_timestamp = DatabaseHelper::convertFilenameToDateTime($filename);
         // Register the patch in the db_patches table (except for the db_patches table patch itself, that wouldn't be possible yet).
         // Add the revert (down) code to the record so the update can be reverted when the file doesn't exist, which can happen when code is rolled back.
         // Also add the patch' dependencies list so depending patches won't be reverted before it is reverted first.
         if ('19700101000000' != $patch_timestamp) {
             $this->driver->query("\n                    INSERT INTO db_patches (\n                        patch_name,\n                        patch_timestamp,\n                        down_sql,\n                        dependencies\n                    )\n                    VALUES (\n                        '" . $this->driver->escape($patch_name) . "',\n                        '" . $this->driver->escape($patch_timestamp) . "',\n                        " . (trim($sql_patch_object->down()) != '' ? "'" . $this->driver->escape(trim($sql_patch_object->down())) . "'" : 'null') . ",\n                        " . (count($sql_patch_object->getDependencies()) > 0 ? "'" . $this->driver->escape(implode("\n", $sql_patch_object->getDependencies())) . "'" : 'null') . "\n                    );\n                ");
         }
         // apply the patch
         if (!$register_only) {
             $this->driver->startTransaction();
             $result = $this->driver->multiQuery($sql_patch_object->up());
             if (false === $result) {
                 throw new DatabaseException('Error applying patch ' . $patch_name . ': ' . $this->driver->getLastError(), 1);
             }
             $this->driver->doCommit();
         }
         // if there were no errors, mark the patch as applied
         if ('19700101000000' != $patch_timestamp) {
             $this->driver->query("\n                    UPDATE db_patches\n                    SET applied_at = '" . $this->driver->escape($this->timestamp) . "'\n                    WHERE patch_name = '" . $this->driver->escape($patch_name) . "';\n                ");
             if ($register_only) {
                 $this->logger->log("Patch '{$filename}' registered.");
             } else {
                 $this->logger->log("Patch '{$filename}' succeeded.");
             }
         } else {
             // the db_patches patch has no record set, insert it now
             $this->driver->query("\n                    INSERT INTO db_patches (\n                        patch_name,\n                        patch_timestamp,\n                        applied_at\n                    )\n                    VALUES (\n                        '" . $this->driver->escape($patch_name) . "',\n                        '" . $this->driver->escape($patch_timestamp) . "',\n                        '" . $this->driver->escape($this->timestamp) . "'\n                    );\n                ");
             $this->logger->log("Patch '{$filename}' succeeded.");
         }
     }
 }
Beispiel #2
0
 public function key()
 {
     /** @var \DirectoryIterator $this */
     return Helper::getClassnameFromFilepath($this->getFilename());
 }
Beispiel #3
0
 /**
  * Returns all patches that have already been applied and their dependencies.
  *
  * @throws \LemonWeb\Deployer\Exceptions\DeployException When crashed patches (during patching or reverting) are found
  * @return array [array with performed patches, array with their dependencies]
  */
 protected function findPerformedSQLPatches()
 {
     $this->logger->log('findPerformedSQLPatches', LOG_DEBUG);
     $applied_patches = array();
     $crashed_patches = array();
     $reverted_patches = array();
     $dependencies = array();
     $output = array();
     $this->query('
         SELECT patch_name, patch_timestamp, dependencies, applied_at, reverted_at
         FROM db_patches
         ORDER BY patch_timestamp, id
     ', $output);
     foreach ($output as $patch_record) {
         list($patch_name, $patch_timestamp, $patch_dependencies, $applied_at, $reverted_at) = explode("\t", $patch_record);
         if ('NULL' == $applied_at) {
             // this patch crashed while being applied
             $crashed_patches[$patch_name] = $patch_name;
         } elseif ('NULL' != $reverted_at) {
             // this patch crashed while being reverted
             $reverted_patches[$patch_name] = $patch_name;
         } else {
             // this patch was succesfully applied
             $applied_patches[$patch_name] = $applied_at;
             if ('NULL' != $patch_dependencies) {
                 $dependency_names = array();
                 $patch_dependency_names = (array) explode('\\n', $patch_dependencies);
                 foreach ($patch_dependency_names as $dependency_name) {
                     $dependency_names[Helper::convertFilenameToDateTime($dependency_name)] = $dependency_name;
                 }
                 $dependencies[$patch_name] = $dependency_names;
             }
         }
     }
     if (!empty($crashed_patches)) {
         if (count($crashed_patches) > 1) {
             throw new DeployException('Patches ' . implode(', ', $crashed_patches) . ' have crashed at previous update !');
         } else {
             throw new DeployException('Patch ' . implode(', ', $crashed_patches) . ' has crashed at previous update !');
         }
     }
     if (!empty($reverted_patches)) {
         if (count($reverted_patches) > 1) {
             throw new DeployException('Patches ' . implode(', ', $reverted_patches) . ' have crashed at previous rollback !');
         } else {
             throw new DeployException('Patch ' . implode(', ', $reverted_patches) . ' has crashed at previous rollback !');
         }
     }
     return array($applied_patches, $dependencies);
 }