diff --git a/include/class.migrater.php b/include/class.migrater.php index 3dfaf268324e2d4d8533e11fbf031c5b2ee9b98d..b6bce93cc2293159ee6e83973cd6f2f4c61b964f 100644 --- a/include/class.migrater.php +++ b/include/class.migrater.php @@ -71,13 +71,13 @@ class DatabaseMigrater { return array_filter($patches); } - /** + /** * Reads update stream information from UPGRADE_DIR/<streams>/streams.cfg. * Each declared stream folder should contain a file under the name of the - * stream with an 'md5' extension. The file will be the md5 of the + * stream with an 'sig' extension. The file will be the hash of the * signature of the tip of the stream. A corresponding config variable * 'schema_signature' should exist in the namespace of the stream itself. - * If the md5 file doesn't match the schema_signature on record, then an + * If the hash file doesn't match the schema_signature on record, then an * update is triggered and the patches in the stream folder are used to * upgrade the database. */ @@ -85,17 +85,18 @@ class DatabaseMigrater { static $streams = array(); if ($streams) return $streams; - $config = file_get_contents($basedir.'/streams.cfg'); + $config = @file_get_contents($basedir.'/streams.cfg'); + if (!$config) $config = 'core'; foreach (explode("\n", $config) as $line) { $line = trim(preg_replace('/#.*$/', '', $line)); if (!$line) continue; - else if (file_exists($basedir."$line.md5") && is_dir($basedir.$line)) - $streams[$line] = - trim(file_get_contents($basedir."$line.md5")); + else if (file_exists($basedir."$line.sig") && is_dir($basedir.$line)) + $streams[$line] = + trim(file_get_contents($basedir."$line.sig")); } - return $streams; - } + return $streams; + } } diff --git a/include/class.upgrader.php b/include/class.upgrader.php index dc9aba33fce4209686018b333daa8526f1fa6249..e17b0a4b2626bb21cc3e7b2103c48b5a3a9c4568 100644 --- a/include/class.upgrader.php +++ b/include/class.upgrader.php @@ -22,7 +22,7 @@ class Upgrader { global $ost; $this->streams = array(); - foreach (DatabaseMigrater::getUpgradeStreams($basedir) as $stream=>$hash) { + foreach (DatabaseMigrater::getUpgradeStreams($basedir) as $stream=>$hash) { $signature = $ost->getConfig()->getSchemaSignature($stream); $this->streams[$stream] = new StreamUpgrader($signature, $hash, $stream, $prefix, $basedir.$stream.'/', $this); @@ -151,10 +151,10 @@ class StreamUpgrader extends SetupWizard { /** * Parameters: - * schema_signature - (string<md5-hex>) Current database-reflected (via + * schema_signature - (string<hash-hex>) Current database-reflected (via * config table) version of the stream - * target - (stream<md5-hex>) Current stream tip, as reflected by - * streams/<stream>.md5 + * target - (stream<hash-hex>) Current stream tip, as reflected by + * streams/<stream>.sig * stream - (string) Name of the stream (folder) * prefix - (string) Database table prefix * sqldir - (string<path>) Path of sql patches diff --git a/include/upgrader/streams/core.md5 b/include/upgrader/streams/core.sig similarity index 100% rename from include/upgrader/streams/core.md5 rename to include/upgrader/streams/core.sig diff --git a/setup/doc/streams.md b/setup/doc/streams.md new file mode 100644 index 0000000000000000000000000000000000000000..823e7ee5c3921f7c3b226161884dc66312b4b04c --- /dev/null +++ b/setup/doc/streams.md @@ -0,0 +1,114 @@ +osTicket Database Migration +=========================== + +Database Upgrade Streams +------------------------ +Database upgrade streams are registered in the +`INCLUDE_DIR/upgrader/streams/streams.cfg`. This file contains the names of +the upgrade streams in the order the streams should be applied in. The stock +osTicket install does not ship with a `streams.cfg`, so that updates to the +source code base will not destroy your `streams.cfg` file. If the file does +not exist, only the osTicket `core` stream will be updated. + +Streams folders +--------------- +Stream folders are created in the `INCLUDE_DIR/upgrader/streams` folder. The +name of the stream will be the name of the folder. For instance, the core +osTicket stream exists in the `core` folder, and so is called `core`. Each +stream folder should also have an accompanying hash file which gives the md5 +hash of the tip of the stream. How you generate the hashes is up to you. For +the core stream, we use the md5 hash of the install SQL file. Changes made +to the main install file result in changes to the md5 hash of the file. +Then, the update file placed in the upgrade stream will have the changes +between to two hashes. + +Upgrade Streams +--------------- +Upgrade patches are used to migrate the database from snapshot to snapshot. +The system will start upgrading by consulting the `schema_signature` +configuration setting in the `config` table in the namespace of your stream +name. It will look for an upgrade patch file that starts with the first +eight characters of the current signature. + +Each upgrade in a stream should set the `schema_signature` configuration +option in the `config` when completed. The plan is to make this automatic, +but currently, it is still a manual process. Whatever the hash of then last +executed patch is, it should be reflected in the config table at the +completion of the upgrade patch. + +The migration process will continue until the hash reflected in the +`schema_signature` setting is the same as the value given in the stream +signature file. If no patch files are given to migrate from the current +`schema_signature` value to the value listed in the md5 file, then the +migrater will fail and complain that the system is not upgradeable. + +Patch Files +----------- +Patch files should live in your stream folder and should have the name of + + 12345678-00abcdef.patch.sql + +and should contain only SQL text. Double-dash comments are only supported if +started at the beginning of a line. For instance, do not write then inline +as part of a long running SQL statement. The filename format is the first +eight chars of the starting and ending database `schema_signature` values. + +Your patch process can be separated into two parts if you like. A cleanup file can be used to cleanup database objects after the completion of the patch process. Cleanup files must have the name of + + 12345678-00abcdef.cleanup.sql + +Where the starting and ending hashes are listed with a hyphen in between. +The idea is that PHP code can be run between the two SQL patch files. +//Currently, support for this is hardcoded, but will hopefully be redesigned +to include a `patch.php` file at some point in the future.// + +If you want to use numeric serial numbers, make sure the first eight digits +change for every upgrade. For instance, use 00000001-00000002. Technically, +there is no current requirement for the hash file to be an actual md5 or even +have 32 hex chars in it. + +Patch files should contain a header with some common information about the +patch. The header should be formatted similar to + + /* osTicket database migration patch + * + * @version 0.0.0 + * @signature 0123456789abcdef0000000000000000 + * + * Details about the migration patch are listed here + */ + +Eventually the `@signature` line will be automatically inspected and forced +into the config table for the `schema_signature` setting in the namespace of +your stream at the completion of the patch process. Please add it to your +patches to keep them future-minded. The `@version` is a string that will be +shown to clients during the upgrade process indicating the version numbers +as each patch is applied. + +Customizing osTicket +==================== +osTicket now supports database customizations using a separation technique +called *streams*. Separating the database upgrade path into streams allows +the upstream osTicket database upgrades to be kept separate from your own, +custom upgrade streams. Streams are registered in `streams.cfg` located in +the `UPGRADE_DIR/streams`. + +Example streams.cfg +------------------- + # Write the names of the stream folders to be enabled in this file. + # The order is significant. The upgrade process will run updates for the + # respective streams in the order they are listed in this file. + + core # The upstream osTicket upgrade stream + + # Add custom upgrade streams here, which will be applied in the order + # listed in this file + +Database Customization Rules +--------------------------- +1. Leave the upstream osTicket tables unchanged. If your customization makes + changes to the main osTicket tables, you will likely get merge conflicts + when the *core* stream is updated. If you need to add columns to an + upstream table, add another table with the extra columns and link the + data to the upstream table using the primary key of the upstream table. + This will keep your data model separate from the upstream data model. diff --git a/setup/inc/class.installer.php b/setup/inc/class.installer.php index 40d9137dc6ea723ea5c4cd9d357b4523bc234a43..d0741fe72503dd80cc454b41ba7eb9c06fd6773a 100644 --- a/setup/inc/class.installer.php +++ b/setup/inc/class.installer.php @@ -116,7 +116,7 @@ class Installer extends SetupWizard { if(!file_exists($schemaFile) || !($fp = fopen($schemaFile, 'rb'))) $this->errors['err']='Internal Error - please make sure your download is the latest (#1)'; elseif( - !($signature=trim(file_get_contents("$schemaFile.md5"))) + !($signature=trim(file_get_contents("$schemaFile.sig"))) || !($hash=md5(fread($fp, filesize($schemaFile)))) || strcasecmp($signature, $hash)) $this->errors['err']='Unknown or invalid schema signature (' diff --git a/setup/inc/sql/osTicket-mysql.sql.md5 b/setup/inc/sql/osTicket-mysql.sql.sig similarity index 100% rename from setup/inc/sql/osTicket-mysql.sql.md5 rename to setup/inc/sql/osTicket-mysql.sql.sig