1*a1a3b679SAndreas Boehler#!/usr/bin/env php 2*a1a3b679SAndreas Boehler<?php 3*a1a3b679SAndreas Boehler 4*a1a3b679SAndreas Boehlerecho "SabreDAV migrate script for version 2.1\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-2.1 database to 2.1. 11*a1a3b679SAndreas Boehler 12*a1a3b679SAndreas BoehlerChanges: 13*a1a3b679SAndreas Boehler The 'calendarobjects' table will be upgraded. 14*a1a3b679SAndreas Boehler 'schedulingobjects' will be created. 15*a1a3b679SAndreas Boehler 16*a1a3b679SAndreas BoehlerIf you don't use the default PDO CalDAV or CardDAV backend, it's pointless to 17*a1a3b679SAndreas Boehlerrun this script. 18*a1a3b679SAndreas Boehler 19*a1a3b679SAndreas BoehlerKeep in mind that ALTER TABLE commands will be executed. If you have a large 20*a1a3b679SAndreas Boehlerdataset this may mean that this process takes a while. 21*a1a3b679SAndreas Boehler 22*a1a3b679SAndreas BoehlerLastly: Make a back-up first. This script has been tested, but the amount of 23*a1a3b679SAndreas Boehlerpotential variants are extremely high, so it's impossible to deal with every 24*a1a3b679SAndreas Boehlerpossible situation. 25*a1a3b679SAndreas Boehler 26*a1a3b679SAndreas BoehlerIn the worst case, you will lose all your data. This is not an overstatement. 27*a1a3b679SAndreas Boehler 28*a1a3b679SAndreas BoehlerUsage: 29*a1a3b679SAndreas Boehler 30*a1a3b679SAndreas Boehlerphp {$argv[0]} [pdo-dsn] [username] [password] 31*a1a3b679SAndreas Boehler 32*a1a3b679SAndreas BoehlerFor example: 33*a1a3b679SAndreas Boehler 34*a1a3b679SAndreas Boehlerphp {$argv[0]} "mysql:host=localhost;dbname=sabredav" root password 35*a1a3b679SAndreas Boehlerphp {$argv[0]} sqlite:data/sabredav.db 36*a1a3b679SAndreas Boehler 37*a1a3b679SAndreas BoehlerHELLO; 38*a1a3b679SAndreas Boehler 39*a1a3b679SAndreas Boehler exit(); 40*a1a3b679SAndreas Boehler 41*a1a3b679SAndreas Boehler} 42*a1a3b679SAndreas Boehler 43*a1a3b679SAndreas Boehler// There's a bunch of places where the autoloader could be, so we'll try all of 44*a1a3b679SAndreas Boehler// them. 45*a1a3b679SAndreas Boehler$paths = [ 46*a1a3b679SAndreas Boehler __DIR__ . '/../vendor/autoload.php', 47*a1a3b679SAndreas Boehler __DIR__ . '/../../../autoload.php', 48*a1a3b679SAndreas Boehler]; 49*a1a3b679SAndreas Boehler 50*a1a3b679SAndreas Boehlerforeach($paths as $path) { 51*a1a3b679SAndreas Boehler if (file_exists($path)) { 52*a1a3b679SAndreas Boehler include $path; 53*a1a3b679SAndreas Boehler break; 54*a1a3b679SAndreas Boehler } 55*a1a3b679SAndreas Boehler} 56*a1a3b679SAndreas Boehler 57*a1a3b679SAndreas Boehler$dsn = $argv[1]; 58*a1a3b679SAndreas Boehler$user = isset($argv[2])?$argv[2]:null; 59*a1a3b679SAndreas Boehler$pass = isset($argv[3])?$argv[3]:null; 60*a1a3b679SAndreas Boehler 61*a1a3b679SAndreas Boehlerecho "Connecting to database: " . $dsn . "\n"; 62*a1a3b679SAndreas Boehler 63*a1a3b679SAndreas Boehler$pdo = new PDO($dsn, $user, $pass); 64*a1a3b679SAndreas Boehler$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 65*a1a3b679SAndreas Boehler$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); 66*a1a3b679SAndreas Boehler 67*a1a3b679SAndreas Boehler$driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME); 68*a1a3b679SAndreas Boehler 69*a1a3b679SAndreas Boehlerswitch($driver) { 70*a1a3b679SAndreas Boehler 71*a1a3b679SAndreas Boehler case 'mysql' : 72*a1a3b679SAndreas Boehler echo "Detected MySQL.\n"; 73*a1a3b679SAndreas Boehler break; 74*a1a3b679SAndreas Boehler case 'sqlite' : 75*a1a3b679SAndreas Boehler echo "Detected SQLite.\n"; 76*a1a3b679SAndreas Boehler break; 77*a1a3b679SAndreas Boehler default : 78*a1a3b679SAndreas Boehler echo "Error: unsupported driver: " . $driver . "\n"; 79*a1a3b679SAndreas Boehler die(-1); 80*a1a3b679SAndreas Boehler} 81*a1a3b679SAndreas Boehler 82*a1a3b679SAndreas Boehlerecho "Upgrading 'calendarobjects'\n"; 83*a1a3b679SAndreas Boehler$addUid = false; 84*a1a3b679SAndreas Boehlertry { 85*a1a3b679SAndreas Boehler $result = $pdo->query('SELECT * FROM calendarobjects LIMIT 1'); 86*a1a3b679SAndreas Boehler $row = $result->fetch(\PDO::FETCH_ASSOC); 87*a1a3b679SAndreas Boehler 88*a1a3b679SAndreas Boehler if (!$row) { 89*a1a3b679SAndreas Boehler echo "No data in table. Going to try to add the uid field anyway.\n"; 90*a1a3b679SAndreas Boehler $addUid = true; 91*a1a3b679SAndreas Boehler } elseif (array_key_exists('uid', $row)) { 92*a1a3b679SAndreas Boehler echo "uid field exists. Assuming that this part of the migration has\n"; 93*a1a3b679SAndreas Boehler echo "Already been completed.\n"; 94*a1a3b679SAndreas Boehler } else { 95*a1a3b679SAndreas Boehler echo "2.0 schema detected.\n"; 96*a1a3b679SAndreas Boehler $addUid = true; 97*a1a3b679SAndreas Boehler } 98*a1a3b679SAndreas Boehler 99*a1a3b679SAndreas Boehler} catch (Exception $e) { 100*a1a3b679SAndreas Boehler echo "Could not find a calendarobjects table. Skipping this part of the\n"; 101*a1a3b679SAndreas Boehler echo "upgrade.\n"; 102*a1a3b679SAndreas Boehler} 103*a1a3b679SAndreas Boehler 104*a1a3b679SAndreas Boehlerif ($addUid) { 105*a1a3b679SAndreas Boehler 106*a1a3b679SAndreas Boehler switch($driver) { 107*a1a3b679SAndreas Boehler case 'mysql' : 108*a1a3b679SAndreas Boehler $pdo->exec('ALTER TABLE calendarobjects ADD uid VARCHAR(200)'); 109*a1a3b679SAndreas Boehler break; 110*a1a3b679SAndreas Boehler case 'sqlite' : 111*a1a3b679SAndreas Boehler $pdo->exec('ALTER TABLE calendarobjects ADD uid TEXT'); 112*a1a3b679SAndreas Boehler break; 113*a1a3b679SAndreas Boehler } 114*a1a3b679SAndreas Boehler 115*a1a3b679SAndreas Boehler $result = $pdo->query('SELECT id, calendardata FROM calendarobjects'); 116*a1a3b679SAndreas Boehler $stmt = $pdo->prepare('UPDATE calendarobjects SET uid = ? WHERE id = ?'); 117*a1a3b679SAndreas Boehler $counter = 0; 118*a1a3b679SAndreas Boehler 119*a1a3b679SAndreas Boehler while($row = $result->fetch(\PDO::FETCH_ASSOC)) { 120*a1a3b679SAndreas Boehler 121*a1a3b679SAndreas Boehler try { 122*a1a3b679SAndreas Boehler $vobj = \Sabre\VObject\Reader::read($row['calendardata']); 123*a1a3b679SAndreas Boehler } catch (\Exception $e) { 124*a1a3b679SAndreas Boehler echo "Warning! Item with id $row[id] could not be parsed!\n"; 125*a1a3b679SAndreas Boehler continue; 126*a1a3b679SAndreas Boehler } 127*a1a3b679SAndreas Boehler $uid = null; 128*a1a3b679SAndreas Boehler $item = $vobj->getBaseComponent(); 129*a1a3b679SAndreas Boehler if (!isset($item->UID)) { 130*a1a3b679SAndreas Boehler echo "Warning! Item with id $item[id] does NOT have a UID property and this is required.\n"; 131*a1a3b679SAndreas Boehler continue; 132*a1a3b679SAndreas Boehler } 133*a1a3b679SAndreas Boehler $uid = (string)$item->UID; 134*a1a3b679SAndreas Boehler $stmt->execute([$uid, $row['id']]); 135*a1a3b679SAndreas Boehler $counter++; 136*a1a3b679SAndreas Boehler 137*a1a3b679SAndreas Boehler } 138*a1a3b679SAndreas Boehler 139*a1a3b679SAndreas Boehler} 140*a1a3b679SAndreas Boehler 141*a1a3b679SAndreas Boehlerecho "Creating 'schedulingobjects'\n"; 142*a1a3b679SAndreas Boehler 143*a1a3b679SAndreas Boehlerswitch($driver) { 144*a1a3b679SAndreas Boehler 145*a1a3b679SAndreas Boehler case 'mysql' : 146*a1a3b679SAndreas Boehler $pdo->exec('CREATE TABLE IF NOT EXISTS schedulingobjects 147*a1a3b679SAndreas Boehler( 148*a1a3b679SAndreas Boehler id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, 149*a1a3b679SAndreas Boehler principaluri VARCHAR(255), 150*a1a3b679SAndreas Boehler calendardata MEDIUMBLOB, 151*a1a3b679SAndreas Boehler uri VARCHAR(200), 152*a1a3b679SAndreas Boehler lastmodified INT(11) UNSIGNED, 153*a1a3b679SAndreas Boehler etag VARCHAR(32), 154*a1a3b679SAndreas Boehler size INT(11) UNSIGNED NOT NULL 155*a1a3b679SAndreas Boehler) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 156*a1a3b679SAndreas Boehler '); 157*a1a3b679SAndreas Boehler break; 158*a1a3b679SAndreas Boehler 159*a1a3b679SAndreas Boehler 160*a1a3b679SAndreas Boehler case 'sqlite' : 161*a1a3b679SAndreas Boehler $pdo->exec('CREATE TABLE IF NOT EXISTS schedulingobjects ( 162*a1a3b679SAndreas Boehler id integer primary key asc, 163*a1a3b679SAndreas Boehler principaluri text, 164*a1a3b679SAndreas Boehler calendardata blob, 165*a1a3b679SAndreas Boehler uri text, 166*a1a3b679SAndreas Boehler lastmodified integer, 167*a1a3b679SAndreas Boehler etag text, 168*a1a3b679SAndreas Boehler size integer 169*a1a3b679SAndreas Boehler) 170*a1a3b679SAndreas Boehler'); 171*a1a3b679SAndreas Boehler break; 172*a1a3b679SAndreas Boehler $pdo->exec(' 173*a1a3b679SAndreas Boehler CREATE INDEX principaluri_uri ON calendarsubscriptions (principaluri, uri); 174*a1a3b679SAndreas Boehler '); 175*a1a3b679SAndreas Boehler break; 176*a1a3b679SAndreas Boehler} 177*a1a3b679SAndreas Boehler 178*a1a3b679SAndreas Boehlerecho "Done.\n"; 179*a1a3b679SAndreas Boehler 180*a1a3b679SAndreas Boehlerecho "Upgrade to 2.1 schema completed.\n"; 181