1*a1a3b679SAndreas Boehler#!/usr/bin/env php 2*a1a3b679SAndreas Boehler<?php 3*a1a3b679SAndreas Boehler 4*a1a3b679SAndreas Boehlerecho "SabreDAV migrate script for version 3.0\n"; 5*a1a3b679SAndreas Boehler 6*a1a3b679SAndreas Boehlerif ($argc<2) { 7*a1a3b679SAndreas Boehler 8*a1a3b679SAndreas Boehler echo <<<HELLO 9*a1a3b679SAndreas Boehler 10*a1a3b679SAndreas BoehlerThis script help you migrate from a pre-3.0 database to 3.0 and later 11*a1a3b679SAndreas Boehler 12*a1a3b679SAndreas BoehlerChanges: 13*a1a3b679SAndreas Boehler * The propertystorage table has changed to allow storage of complex 14*a1a3b679SAndreas Boehler properties. 15*a1a3b679SAndreas Boehler * the vcardurl field in the principals table is no more. This was moved to 16*a1a3b679SAndreas Boehler the propertystorage table. 17*a1a3b679SAndreas Boehler 18*a1a3b679SAndreas BoehlerKeep in mind that ALTER TABLE commands will be executed. If you have a large 19*a1a3b679SAndreas Boehlerdataset this may mean that this process takes a while. 20*a1a3b679SAndreas Boehler 21*a1a3b679SAndreas BoehlerLastly: Make a back-up first. This script has been tested, but the amount of 22*a1a3b679SAndreas Boehlerpotential variants are extremely high, so it's impossible to deal with every 23*a1a3b679SAndreas Boehlerpossible situation. 24*a1a3b679SAndreas Boehler 25*a1a3b679SAndreas BoehlerIn the worst case, you will lose all your data. This is not an overstatement. 26*a1a3b679SAndreas Boehler 27*a1a3b679SAndreas BoehlerUsage: 28*a1a3b679SAndreas Boehler 29*a1a3b679SAndreas Boehlerphp {$argv[0]} [pdo-dsn] [username] [password] 30*a1a3b679SAndreas Boehler 31*a1a3b679SAndreas BoehlerFor example: 32*a1a3b679SAndreas Boehler 33*a1a3b679SAndreas Boehlerphp {$argv[0]} "mysql:host=localhost;dbname=sabredav" root password 34*a1a3b679SAndreas Boehlerphp {$argv[0]} sqlite:data/sabredav.db 35*a1a3b679SAndreas Boehler 36*a1a3b679SAndreas BoehlerHELLO; 37*a1a3b679SAndreas Boehler 38*a1a3b679SAndreas Boehler exit(); 39*a1a3b679SAndreas Boehler 40*a1a3b679SAndreas Boehler} 41*a1a3b679SAndreas Boehler 42*a1a3b679SAndreas Boehler// There's a bunch of places where the autoloader could be, so we'll try all of 43*a1a3b679SAndreas Boehler// them. 44*a1a3b679SAndreas Boehler$paths = [ 45*a1a3b679SAndreas Boehler __DIR__ . '/../vendor/autoload.php', 46*a1a3b679SAndreas Boehler __DIR__ . '/../../../autoload.php', 47*a1a3b679SAndreas Boehler]; 48*a1a3b679SAndreas Boehler 49*a1a3b679SAndreas Boehlerforeach($paths as $path) { 50*a1a3b679SAndreas Boehler if (file_exists($path)) { 51*a1a3b679SAndreas Boehler include $path; 52*a1a3b679SAndreas Boehler break; 53*a1a3b679SAndreas Boehler } 54*a1a3b679SAndreas Boehler} 55*a1a3b679SAndreas Boehler 56*a1a3b679SAndreas Boehler$dsn = $argv[1]; 57*a1a3b679SAndreas Boehler$user = isset($argv[2])?$argv[2]:null; 58*a1a3b679SAndreas Boehler$pass = isset($argv[3])?$argv[3]:null; 59*a1a3b679SAndreas Boehler 60*a1a3b679SAndreas Boehlerecho "Connecting to database: " . $dsn . "\n"; 61*a1a3b679SAndreas Boehler 62*a1a3b679SAndreas Boehler$pdo = new PDO($dsn, $user, $pass); 63*a1a3b679SAndreas Boehler$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 64*a1a3b679SAndreas Boehler$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); 65*a1a3b679SAndreas Boehler 66*a1a3b679SAndreas Boehler$driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME); 67*a1a3b679SAndreas Boehler 68*a1a3b679SAndreas Boehlerswitch($driver) { 69*a1a3b679SAndreas Boehler 70*a1a3b679SAndreas Boehler case 'mysql' : 71*a1a3b679SAndreas Boehler echo "Detected MySQL.\n"; 72*a1a3b679SAndreas Boehler break; 73*a1a3b679SAndreas Boehler case 'sqlite' : 74*a1a3b679SAndreas Boehler echo "Detected SQLite.\n"; 75*a1a3b679SAndreas Boehler break; 76*a1a3b679SAndreas Boehler default : 77*a1a3b679SAndreas Boehler echo "Error: unsupported driver: " . $driver . "\n"; 78*a1a3b679SAndreas Boehler die(-1); 79*a1a3b679SAndreas Boehler} 80*a1a3b679SAndreas Boehler 81*a1a3b679SAndreas Boehlerecho "Upgrading 'propertystorage'\n"; 82*a1a3b679SAndreas Boehler$addValueType = false; 83*a1a3b679SAndreas Boehlertry { 84*a1a3b679SAndreas Boehler $result = $pdo->query('SELECT * FROM propertystorage LIMIT 1'); 85*a1a3b679SAndreas Boehler $row = $result->fetch(\PDO::FETCH_ASSOC); 86*a1a3b679SAndreas Boehler 87*a1a3b679SAndreas Boehler if (!$row) { 88*a1a3b679SAndreas Boehler echo "No data in table. Going to re-create the table.\n"; 89*a1a3b679SAndreas Boehler $random = mt_rand(1000,9999); 90*a1a3b679SAndreas Boehler echo "Renaming propertystorage -> propertystorage_old$random and creating new table.\n"; 91*a1a3b679SAndreas Boehler 92*a1a3b679SAndreas Boehler switch($driver) { 93*a1a3b679SAndreas Boehler 94*a1a3b679SAndreas Boehler case 'mysql' : 95*a1a3b679SAndreas Boehler $pdo->exec('RENAME TABLE propertystorage TO propertystorage_old' . $random); 96*a1a3b679SAndreas Boehler $pdo->exec(' 97*a1a3b679SAndreas Boehler CREATE TABLE propertystorage ( 98*a1a3b679SAndreas Boehler id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, 99*a1a3b679SAndreas Boehler path VARBINARY(1024) NOT NULL, 100*a1a3b679SAndreas Boehler name VARBINARY(100) NOT NULL, 101*a1a3b679SAndreas Boehler valuetype INT UNSIGNED, 102*a1a3b679SAndreas Boehler value MEDIUMBLOB 103*a1a3b679SAndreas Boehler ); 104*a1a3b679SAndreas Boehler '); 105*a1a3b679SAndreas Boehler $pdo->exec('CREATE UNIQUE INDEX path_property_' . $random . ' ON propertystorage (path(600), name(100));'); 106*a1a3b679SAndreas Boehler break; 107*a1a3b679SAndreas Boehler case 'sqlite' : 108*a1a3b679SAndreas Boehler $pdo->exec('ALTER TABLE propertystorage RENAME TO propertystorage_old' . $random); 109*a1a3b679SAndreas Boehler $pdo->exec(' 110*a1a3b679SAndreas BoehlerCREATE TABLE propertystorage ( 111*a1a3b679SAndreas Boehler id integer primary key asc, 112*a1a3b679SAndreas Boehler path text, 113*a1a3b679SAndreas Boehler name text, 114*a1a3b679SAndreas Boehler valuetype integer, 115*a1a3b679SAndreas Boehler value blob 116*a1a3b679SAndreas Boehler);'); 117*a1a3b679SAndreas Boehler 118*a1a3b679SAndreas Boehler $pdo->exec('CREATE UNIQUE INDEX path_property_' . $random . ' ON propertystorage (path, name);'); 119*a1a3b679SAndreas Boehler break; 120*a1a3b679SAndreas Boehler 121*a1a3b679SAndreas Boehler } 122*a1a3b679SAndreas Boehler } elseif (array_key_exists('valuetype', $row)) { 123*a1a3b679SAndreas Boehler echo "valuetype field exists. Assuming that this part of the migration has\n"; 124*a1a3b679SAndreas Boehler echo "Already been completed.\n"; 125*a1a3b679SAndreas Boehler } else { 126*a1a3b679SAndreas Boehler echo "2.1 schema detected. Going to perform upgrade.\n"; 127*a1a3b679SAndreas Boehler $addValueType = true; 128*a1a3b679SAndreas Boehler } 129*a1a3b679SAndreas Boehler 130*a1a3b679SAndreas Boehler} catch (Exception $e) { 131*a1a3b679SAndreas Boehler echo "Could not find a propertystorage table. Skipping this part of the\n"; 132*a1a3b679SAndreas Boehler echo "upgrade.\n"; 133*a1a3b679SAndreas Boehler echo $e->getMessage(), "\n"; 134*a1a3b679SAndreas Boehler} 135*a1a3b679SAndreas Boehler 136*a1a3b679SAndreas Boehlerif ($addValueType) { 137*a1a3b679SAndreas Boehler 138*a1a3b679SAndreas Boehler switch($driver) { 139*a1a3b679SAndreas Boehler case 'mysql' : 140*a1a3b679SAndreas Boehler $pdo->exec('ALTER TABLE propertystorage ADD valuetype INT UNSIGNED'); 141*a1a3b679SAndreas Boehler break; 142*a1a3b679SAndreas Boehler case 'sqlite' : 143*a1a3b679SAndreas Boehler $pdo->exec('ALTER TABLE propertystorage ADD valuetype INT'); 144*a1a3b679SAndreas Boehler 145*a1a3b679SAndreas Boehler break; 146*a1a3b679SAndreas Boehler } 147*a1a3b679SAndreas Boehler 148*a1a3b679SAndreas Boehler $pdo->exec('UPDATE propertystorage SET valuetype = 1 WHERE valuetype IS NULL '); 149*a1a3b679SAndreas Boehler 150*a1a3b679SAndreas Boehler} 151*a1a3b679SAndreas Boehler 152*a1a3b679SAndreas Boehlerecho "Migrating vcardurl\n"; 153*a1a3b679SAndreas Boehler 154*a1a3b679SAndreas Boehler$result = $pdo->query('SELECT id, uri, vcardurl FROM principals WHERE vcardurl IS NOT NULL'); 155*a1a3b679SAndreas Boehler$stmt1 = $pdo->prepare('INSERT INTO propertystorage (path, name, valuetype, value) VALUES (?, ?, 3, ?)'); 156*a1a3b679SAndreas Boehler 157*a1a3b679SAndreas Boehlerwhile($row = $result->fetch(\PDO::FETCH_ASSOC)) { 158*a1a3b679SAndreas Boehler 159*a1a3b679SAndreas Boehler // Inserting the new record 160*a1a3b679SAndreas Boehler $stmt1->execute([ 161*a1a3b679SAndreas Boehler 'addressbooks/' . basename($row['uri']), 162*a1a3b679SAndreas Boehler '{http://calendarserver.org/ns/}me-card', 163*a1a3b679SAndreas Boehler serialize(new Sabre\DAV\Xml\Property\Href($row['vcardurl'])) 164*a1a3b679SAndreas Boehler ]); 165*a1a3b679SAndreas Boehler 166*a1a3b679SAndreas Boehler echo serialize(new Sabre\DAV\Xml\Property\Href($row['vcardurl'])); 167*a1a3b679SAndreas Boehler 168*a1a3b679SAndreas Boehler} 169*a1a3b679SAndreas Boehler 170*a1a3b679SAndreas Boehlerecho "Done.\n"; 171*a1a3b679SAndreas Boehlerecho "Upgrade to 3.0 schema completed.\n"; 172