@@ -20,12 +20,16 @@ | |||
*/ | |||
namespace OCA\Dav\AppInfo; | |||
use OCA\DAV\CalDAV\CalDavBackend; | |||
use OCA\DAV\CardDAV\CardDavBackend; | |||
use OCA\DAV\CardDAV\ContactsManager; | |||
use OCA\DAV\CardDAV\SyncJob; | |||
use OCA\DAV\CardDAV\SyncService; | |||
use OCA\DAV\HookManager; | |||
use OCA\Dav\Migration\AddressBookAdapter; | |||
use OCA\Dav\Migration\CalendarAdapter; | |||
use OCA\Dav\Migration\MigrateAddressbooks; | |||
use OCA\Dav\Migration\MigrateCalendars; | |||
use \OCP\AppFramework\App; | |||
use OCP\AppFramework\IAppContainer; | |||
use OCP\Contacts\IManager; | |||
@@ -73,7 +77,17 @@ class Application extends App { | |||
$c->getServer()->getUserManager(), | |||
$c->getServer()->getGroupManager() | |||
); | |||
return new \OCA\DAV\CardDAV\CardDavBackend($db, $principal, $logger); | |||
return new CardDavBackend($db, $principal, $logger); | |||
}); | |||
$container->registerService('CalDavBackend', function($c) { | |||
/** @var IAppContainer $c */ | |||
$db = $c->getServer()->getDatabaseConnection(); | |||
$principal = new \OCA\DAV\Connector\Sabre\Principal( | |||
$c->getServer()->getUserManager(), | |||
$c->getServer()->getGroupManager() | |||
); | |||
return new CalDavBackend($db, $principal); | |||
}); | |||
$container->registerService('MigrateAddressbooks', function($c) { | |||
@@ -84,6 +98,15 @@ class Application extends App { | |||
$c->query('CardDavBackend') | |||
); | |||
}); | |||
$container->registerService('MigrateCalendars', function($c) { | |||
/** @var IAppContainer $c */ | |||
$db = $c->getServer()->getDatabaseConnection(); | |||
return new MigrateCalendars( | |||
new CalendarAdapter($db), | |||
$c->query('CalDavBackend') | |||
); | |||
}); | |||
} | |||
/** | |||
@@ -112,8 +135,8 @@ class Application extends App { | |||
} | |||
public function migrateAddressbooks() { | |||
try { | |||
/** @var MigrateAddressbooks $migration */ | |||
$migration = $this->getContainer()->query('MigrateAddressbooks'); | |||
$migration->setup(); | |||
$userManager = $this->getContainer()->getServer()->getUserManager(); | |||
@@ -127,4 +150,19 @@ class Application extends App { | |||
} | |||
} | |||
public function migrateCalendars() { | |||
try { | |||
/** @var MigrateCalendars $migration */ | |||
$migration = $this->getContainer()->query('MigrateCalendars'); | |||
$migration->setup(); | |||
$userManager = $this->getContainer()->getServer()->getUserManager(); | |||
$userManager->callForAllUsers(function($user) use($migration) { | |||
/** @var IUser $user */ | |||
$migration->migrateForUser($user->getUID()); | |||
}); | |||
} catch (\Exception $ex) { | |||
$this->getContainer()->getServer()->getLogger()->logException($ex); | |||
} | |||
} | |||
} |
@@ -24,3 +24,4 @@ use OCA\Dav\AppInfo\Application; | |||
$app = new Application(); | |||
$app->setupCron(); | |||
$app->migrateAddressbooks(); | |||
$app->migrateCalendars(); |
@@ -23,6 +23,7 @@ use OCA\Dav\AppInfo\Application; | |||
use OCA\DAV\Command\CreateAddressBook; | |||
use OCA\DAV\Command\CreateCalendar; | |||
use OCA\Dav\Command\MigrateAddressbooks; | |||
use OCA\Dav\Command\MigrateCalendars; | |||
use OCA\DAV\Command\SyncSystemAddressBook; | |||
$config = \OC::$server->getConfig(); | |||
@@ -44,4 +45,6 @@ if ($config->getSystemValue('debug', false)){ | |||
$app = new \OCA\Dav\AppInfo\Application(); | |||
$migration = $app->getContainer()->query('MigrateAddressbooks'); | |||
$application->add(new MigrateAddressbooks($userManager, $migration)); | |||
$migration = $app->getContainer()->query('MigrateCalendars'); | |||
$application->add(new MigrateCalendars($userManager, $migration)); | |||
} |
@@ -68,6 +68,7 @@ class MigrateAddressbooks extends Command { | |||
} | |||
$output->writeln("Start migration for $user"); | |||
$this->service->migrateForUser($user); | |||
return; | |||
} | |||
$output->writeln("Start migration of all known users ..."); | |||
$p = new ProgressBar($output); |
@@ -0,0 +1,66 @@ | |||
<?php | |||
namespace OCA\Dav\Command; | |||
use OCP\IUser; | |||
use OCP\IUserManager; | |||
use Symfony\Component\Console\Command\Command; | |||
use Symfony\Component\Console\Helper\ProgressBar; | |||
use Symfony\Component\Console\Input\InputArgument; | |||
use Symfony\Component\Console\Input\InputInterface; | |||
use Symfony\Component\Console\Output\OutputInterface; | |||
class MigrateCalendars extends Command { | |||
/** @var IUserManager */ | |||
protected $userManager; | |||
/** @var \OCA\Dav\Migration\MigrateCalendars */ | |||
private $service; | |||
/** | |||
* @param IUserManager $userManager | |||
* @param \OCA\Dav\Migration\MigrateCalendars $service | |||
*/ | |||
function __construct(IUserManager $userManager, | |||
\OCA\Dav\Migration\MigrateCalendars $service | |||
) { | |||
parent::__construct(); | |||
$this->userManager = $userManager; | |||
$this->service = $service; | |||
} | |||
protected function configure() { | |||
$this | |||
->setName('dav:migrate-calendars') | |||
->setDescription('Migrate calendars from the calendar app to core') | |||
->addArgument('user', | |||
InputArgument::OPTIONAL, | |||
'User for whom all calendars will be migrated'); | |||
} | |||
protected function execute(InputInterface $input, OutputInterface $output) { | |||
$this->service->setup(); | |||
if ($input->hasArgument('user')) { | |||
$user = $input->getArgument('user'); | |||
if (!$this->userManager->userExists($user)) { | |||
throw new \InvalidArgumentException("User <$user> in unknown."); | |||
} | |||
$output->writeln("Start migration for $user"); | |||
$this->service->migrateForUser($user); | |||
return; | |||
} | |||
$output->writeln("Start migration of all known users ..."); | |||
$p = new ProgressBar($output); | |||
$p->start(); | |||
$this->userManager->callForAllUsers(function($user) use ($p) { | |||
$p->advance(); | |||
/** @var IUser $user */ | |||
$this->service->migrateForUser($user->getUID()); | |||
}); | |||
$p->finish(); | |||
$output->writeln(''); | |||
} | |||
} |
@@ -22,9 +22,11 @@ | |||
namespace OCA\DAV\CalDAV; | |||
use OCA\DAV\DAV\Sharing\IShareable; | |||
use OCP\DB\QueryBuilder\IQueryBuilder; | |||
use OCA\DAV\Connector\Sabre\Principal; | |||
use OCA\DAV\DAV\Sharing\Backend; | |||
use OCP\IDBConnection; | |||
use Sabre\CalDAV\Backend\AbstractBackend; | |||
use Sabre\CalDAV\Backend\SchedulingSupport; | |||
use Sabre\CalDAV\Backend\SubscriptionSupport; | |||
@@ -59,7 +61,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription | |||
const MAX_DATE = '2038-01-01'; | |||
/** | |||
* List of CalDAV properties, and how they map to database fieldnames | |||
* List of CalDAV properties, and how they map to database field names | |||
* Add your own properties by simply adding on to this array. | |||
* | |||
* Note that only string-based properties are supported here. | |||
@@ -75,7 +77,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription | |||
]; | |||
/** | |||
* List of subscription properties, and how they map to database fieldnames. | |||
* List of subscription properties, and how they map to database field names. | |||
* | |||
* @var array | |||
*/ | |||
@@ -89,7 +91,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription | |||
'{http://calendarserver.org/ns/}subscribed-strip-attachments' => 'stripattachments', | |||
]; | |||
/** @var \OCP\IDBConnection */ | |||
/** @var IDBConnection */ | |||
private $db; | |||
/** @var Backend */ | |||
@@ -101,9 +103,10 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription | |||
/** | |||
* CalDavBackend constructor. | |||
* | |||
* @param \OCP\IDBConnection $db | |||
* @param IDBConnection $db | |||
* @param Principal $principalBackend | |||
*/ | |||
public function __construct(\OCP\IDBConnection $db, Principal $principalBackend) { | |||
public function __construct(IDBConnection $db, Principal $principalBackend) { | |||
$this->db = $db; | |||
$this->principalBackend = $principalBackend; | |||
$this->sharingBackend = new Backend($this->db, $principalBackend, 'calendar'); | |||
@@ -232,6 +235,95 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription | |||
return array_values($calendars); | |||
} | |||
public function getCalendarByUri($principal, $uri) { | |||
$fields = array_values($this->propertyMap); | |||
$fields[] = 'id'; | |||
$fields[] = 'uri'; | |||
$fields[] = 'synctoken'; | |||
$fields[] = 'components'; | |||
$fields[] = 'principaluri'; | |||
$fields[] = 'transparent'; | |||
// Making fields a comma-delimited list | |||
$query = $this->db->getQueryBuilder(); | |||
$query->select($fields)->from('calendars') | |||
->where($query->expr()->eq('uri', $query->createNamedParameter($uri))) | |||
->andWhere($query->expr()->eq('principaluri', $query->createNamedParameter($principal))) | |||
->setMaxResults(1); | |||
$stmt = $query->execute(); | |||
$row = $stmt->fetch(\PDO::FETCH_ASSOC); | |||
$stmt->closeCursor(); | |||
if ($row === false) { | |||
return null; | |||
} | |||
$components = []; | |||
if ($row['components']) { | |||
$components = explode(',',$row['components']); | |||
} | |||
$calendar = [ | |||
'id' => $row['id'], | |||
'uri' => $row['uri'], | |||
'principaluri' => $row['principaluri'], | |||
'{' . Plugin::NS_CALENDARSERVER . '}getctag' => 'http://sabre.io/ns/sync/' . ($row['synctoken']?$row['synctoken']:'0'), | |||
'{http://sabredav.org/ns}sync-token' => $row['synctoken']?$row['synctoken']:'0', | |||
'{' . Plugin::NS_CALDAV . '}supported-calendar-component-set' => new SupportedCalendarComponentSet($components), | |||
'{' . Plugin::NS_CALDAV . '}schedule-calendar-transp' => new ScheduleCalendarTransp($row['transparent']?'transparent':'opaque'), | |||
]; | |||
foreach($this->propertyMap as $xmlName=>$dbName) { | |||
$calendar[$xmlName] = $row[$dbName]; | |||
} | |||
return $calendar; | |||
} | |||
public function getCalendarById($calendarId) { | |||
$fields = array_values($this->propertyMap); | |||
$fields[] = 'id'; | |||
$fields[] = 'uri'; | |||
$fields[] = 'synctoken'; | |||
$fields[] = 'components'; | |||
$fields[] = 'principaluri'; | |||
$fields[] = 'transparent'; | |||
// Making fields a comma-delimited list | |||
$query = $this->db->getQueryBuilder(); | |||
$query->select($fields)->from('calendars') | |||
->where($query->expr()->eq('id', $query->createNamedParameter($calendarId))) | |||
->setMaxResults(1); | |||
$stmt = $query->execute(); | |||
$row = $stmt->fetch(\PDO::FETCH_ASSOC); | |||
$stmt->closeCursor(); | |||
if ($row === false) { | |||
return null; | |||
} | |||
$components = []; | |||
if ($row['components']) { | |||
$components = explode(',',$row['components']); | |||
} | |||
$calendar = [ | |||
'id' => $row['id'], | |||
'uri' => $row['uri'], | |||
'principaluri' => $row['principaluri'], | |||
'{' . Plugin::NS_CALENDARSERVER . '}getctag' => 'http://sabre.io/ns/sync/' . ($row['synctoken']?$row['synctoken']:'0'), | |||
'{http://sabredav.org/ns}sync-token' => $row['synctoken']?$row['synctoken']:'0', | |||
'{' . Plugin::NS_CALDAV . '}supported-calendar-component-set' => new SupportedCalendarComponentSet($components), | |||
'{' . Plugin::NS_CALDAV . '}schedule-calendar-transp' => new ScheduleCalendarTransp($row['transparent']?'transparent':'opaque'), | |||
]; | |||
foreach($this->propertyMap as $xmlName=>$dbName) { | |||
$calendar[$xmlName] = $row[$dbName]; | |||
} | |||
return $calendar; | |||
} | |||
/** | |||
* Creates a new calendar for a principal. | |||
* | |||
@@ -241,7 +333,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription | |||
* @param string $principalUri | |||
* @param string $calendarUri | |||
* @param array $properties | |||
* @return void | |||
* @return int | |||
*/ | |||
function createCalendar($principalUri, $calendarUri, array $properties) { | |||
$values = [ | |||
@@ -278,6 +370,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription | |||
$query->setValue($column, $query->createNamedParameter($value)); | |||
} | |||
$query->execute(); | |||
return $query->getLastInsertId(); | |||
} | |||
/** | |||
@@ -1249,16 +1342,29 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription | |||
return $cardData; | |||
} | |||
/** | |||
* @param IShareable $shareable | |||
* @param array $add | |||
* @param array $remove | |||
*/ | |||
public function updateShares($shareable, $add, $remove) { | |||
$this->sharingBackend->updateShares($shareable, $add, $remove); | |||
} | |||
/** | |||
* @param int $resourceId | |||
* @return array | |||
*/ | |||
public function getShares($resourceId) { | |||
return $this->sharingBackend->getShares($resourceId); | |||
} | |||
public function applyShareAcl($addressBookId, $acl) { | |||
return $this->sharingBackend->applyShareAcl($addressBookId, $acl); | |||
/** | |||
* @param int $resourceId | |||
* @param array $acl | |||
* @return array | |||
*/ | |||
public function applyShareAcl($resourceId, $acl) { | |||
return $this->sharingBackend->applyShareAcl($resourceId, $acl); | |||
} | |||
} |
@@ -0,0 +1,83 @@ | |||
<?php | |||
namespace OCA\Dav\Migration; | |||
use OCP\IDBConnection; | |||
class CalendarAdapter { | |||
/** @var \OCP\IDBConnection */ | |||
protected $dbConnection; | |||
/** @var string */ | |||
private $sourceCalendarTable; | |||
/** @var string */ | |||
private $sourceCalObjTable; | |||
/** | |||
* @param IDBConnection $dbConnection | |||
* @param string $sourceCalendarTable | |||
* @param string $sourceCalObjTable | |||
*/ | |||
function __construct(IDBConnection $dbConnection, | |||
$sourceCalendarTable = 'clndr_calendars', | |||
$sourceCalObjTable = 'clndr_objects') { | |||
$this->dbConnection = $dbConnection; | |||
$this->sourceCalendarTable = $sourceCalendarTable; | |||
$this->sourceCalObjTable = $sourceCalObjTable; | |||
} | |||
/** | |||
* @param string $user | |||
* @param \Closure $callBack | |||
*/ | |||
public function foreachCalendar($user, \Closure $callBack) { | |||
// get all calendars of that user | |||
$query = $this->dbConnection->getQueryBuilder(); | |||
$stmt = $query->select('*')->from($this->sourceCalendarTable) | |||
->where($query->expr()->eq('userid', $query->createNamedParameter($user))) | |||
->execute(); | |||
while($row = $stmt->fetch()) { | |||
$callBack($row); | |||
} | |||
} | |||
public function setup() { | |||
if (!$this->dbConnection->tableExists($this->sourceCalendarTable)) { | |||
throw new \DomainException('Calendar tables are missing. Nothing to do.'); | |||
} | |||
} | |||
/** | |||
* @param int $calendarId | |||
* @param \Closure $callBack | |||
*/ | |||
public function foreachCalendarObject($calendarId, \Closure $callBack) { | |||
$query = $this->dbConnection->getQueryBuilder(); | |||
$stmt = $query->select('*')->from($this->sourceCalObjTable) | |||
->where($query->expr()->eq('calendarid', $query->createNamedParameter($calendarId))) | |||
->execute(); | |||
while($row = $stmt->fetch()) { | |||
$callBack($row); | |||
} | |||
} | |||
/** | |||
* @param int $addressBookId | |||
* @return array | |||
*/ | |||
public function getShares($addressBookId) { | |||
$query = $this->dbConnection->getQueryBuilder(); | |||
$shares = $query->select('*')->from('share') | |||
->where($query->expr()->eq('item_source', $query->createNamedParameter($addressBookId))) | |||
->andWhere($query->expr()->eq('item_type', $query->expr()->literal('calendar'))) | |||
->andWhere($query->expr()->in('share_type', [ $query->expr()->literal(0), $query->expr()->literal(1)])) | |||
->execute() | |||
->fetchAll(); | |||
return $shares; | |||
} | |||
} |
@@ -0,0 +1,94 @@ | |||
<?php | |||
namespace OCA\Dav\Migration; | |||
use OCA\DAV\CalDAV\CalDavBackend; | |||
use OCA\DAV\CalDAV\Calendar; | |||
use Symfony\Component\Console\Command\Command; | |||
use Symfony\Component\Console\Input\InputArgument; | |||
use Symfony\Component\Console\Input\InputInterface; | |||
use Symfony\Component\Console\Output\OutputInterface; | |||
class MigrateCalendars { | |||
/** @var CalendarAdapter */ | |||
protected $adapter; | |||
/** @var CalDavBackend */ | |||
private $backend; | |||
/** | |||
* @param CalendarAdapter $adapter | |||
* @param CalDavBackend $backend | |||
*/ | |||
function __construct(CalendarAdapter $adapter, | |||
CalDavBackend $backend | |||
) { | |||
$this->adapter = $adapter; | |||
$this->backend = $backend; | |||
} | |||
/** | |||
* @param string $user | |||
*/ | |||
public function migrateForUser($user) { | |||
$this->adapter->foreachCalendar($user, function($calendar) use ($user) { | |||
$principal = "principals/users/$user"; | |||
$calendarByUri = $this->backend->getCalendarByUri($principal, $calendar['uri']); | |||
if (!is_null($calendarByUri)) { | |||
return; | |||
} | |||
$newId = $this->backend->createCalendar($principal, $calendar['uri'], [ | |||
'{DAV:}displayname' => $calendar['displayname'], | |||
'{urn:ietf:params:xml:ns:caldav}calendar-description' => $calendar['displayname'], | |||
'{urn:ietf:params:xml:ns:caldav}calendar-timezone' => $calendar['timezone'], | |||
'{http://apple.com/ns/ical/}calendar-order' => $calendar['calendarorder'], | |||
'{http://apple.com/ns/ical/}calendar-color' => $calendar['calendarcolor'], | |||
]); | |||
$this->migrateCalendar($calendar['id'], $newId); | |||
$this->migrateShares($calendar['id'], $newId); | |||
}); | |||
} | |||
public function setup() { | |||
$this->adapter->setup(); | |||
} | |||
/** | |||
* @param int $calendarId | |||
* @param int $newCalendarId | |||
*/ | |||
private function migrateCalendar($calendarId, $newCalendarId) { | |||
$this->adapter->foreachCalendarObject($calendarId, function($calObject) use ($newCalendarId) { | |||
$this->backend->createCalendarObject($newCalendarId, $calObject['uri'], $calObject['calendardata']); | |||
}); | |||
} | |||
/** | |||
* @param int $calendarId | |||
* @param int $newCalendarId | |||
*/ | |||
private function migrateShares($calendarId, $newCalendarId) { | |||
$shares =$this->adapter->getShares($calendarId); | |||
if (empty($shares)) { | |||
return; | |||
} | |||
$add = array_map(function($s) { | |||
$prefix = 'principal:principals/users/'; | |||
if ($s['share_type'] === 1) { | |||
$prefix = 'principal:principals/groups/'; | |||
} | |||
return [ | |||
'href' => $prefix . $s['share_with'] | |||
]; | |||
}, $shares); | |||
$newCalendar = $this->backend->getCalendarById($newCalendarId); | |||
$calendar = new Calendar($this->backend, $newCalendar); | |||
$this->backend->updateShares($calendar, $add, []); | |||
} | |||
} |
@@ -0,0 +1,191 @@ | |||
<?xml version="1.0" encoding="ISO-8859-1" ?> | |||
<database> | |||
<name>*dbname*</name> | |||
<create>true</create> | |||
<overwrite>false</overwrite> | |||
<charset>utf8</charset> | |||
<table> | |||
<name>*dbprefix*clndr_objects</name> | |||
<declaration> | |||
<field> | |||
<name>id</name> | |||
<type>integer</type> | |||
<default>0</default> | |||
<notnull>true</notnull> | |||
<autoincrement>1</autoincrement> | |||
<unsigned>true</unsigned> | |||
<length>4</length> | |||
</field> | |||
<field> | |||
<name>calendarid</name> | |||
<type>integer</type> | |||
<default></default> | |||
<notnull>true</notnull> | |||
<unsigned>true</unsigned> | |||
<length>4</length> | |||
</field> | |||
<field> | |||
<name>objecttype</name> | |||
<type>text</type> | |||
<default></default> | |||
<notnull>true</notnull> | |||
<length>40</length> | |||
</field> | |||
<field> | |||
<name>startdate</name> | |||
<type>timestamp</type> | |||
<default>1970-01-01 00:00:00</default> | |||
<notnull>false</notnull> | |||
</field> | |||
<field> | |||
<name>enddate</name> | |||
<type>timestamp</type> | |||
<default>1970-01-01 00:00:00</default> | |||
<notnull>false</notnull> | |||
</field> | |||
<field> | |||
<name>repeating</name> | |||
<type>integer</type> | |||
<default></default> | |||
<notnull>false</notnull> | |||
<length>4</length> | |||
</field> | |||
<field> | |||
<name>summary</name> | |||
<type>text</type> | |||
<default></default> | |||
<notnull>false</notnull> | |||
<length>255</length> | |||
</field> | |||
<field> | |||
<name>calendardata</name> | |||
<type>clob</type> | |||
<notnull>false</notnull> | |||
</field> | |||
<field> | |||
<name>uri</name> | |||
<type>text</type> | |||
<default></default> | |||
<notnull>false</notnull> | |||
<length>255</length> | |||
</field> | |||
<field> | |||
<name>lastmodified</name> | |||
<type>integer</type> | |||
<default></default> | |||
<notnull>false</notnull> | |||
<length>4</length> | |||
</field> | |||
</declaration> | |||
</table> | |||
<table> | |||
<name>*dbprefix*clndr_calendars</name> | |||
<declaration> | |||
<field> | |||
<name>id</name> | |||
<type>integer</type> | |||
<default>0</default> | |||
<notnull>true</notnull> | |||
<autoincrement>1</autoincrement> | |||
<unsigned>true</unsigned> | |||
<length>4</length> | |||
</field> | |||
<field> | |||
<name>userid</name> | |||
<type>text</type> | |||
<default></default> | |||
<notnull>false</notnull> | |||
<length>255</length> | |||
</field> | |||
<field> | |||
<name>displayname</name> | |||
<type>text</type> | |||
<default></default> | |||
<notnull>false</notnull> | |||
<length>100</length> | |||
</field> | |||
<field> | |||
<name>uri</name> | |||
<type>text</type> | |||
<default></default> | |||
<notnull>false</notnull> | |||
<length>255</length> | |||
</field> | |||
<field> | |||
<name>active</name> | |||
<type>integer</type> | |||
<default>1</default> | |||
<notnull>true</notnull> | |||
<length>4</length> | |||
</field> | |||
<field> | |||
<name>ctag</name> | |||
<type>integer</type> | |||
<default>0</default> | |||
<notnull>true</notnull> | |||
<unsigned>true</unsigned> | |||
<length>4</length> | |||
</field> | |||
<field> | |||
<name>calendarorder</name> | |||
<type>integer</type> | |||
<default>0</default> | |||
<notnull>true</notnull> | |||
<unsigned>true</unsigned> | |||
<length>4</length> | |||
</field> | |||
<field> | |||
<name>calendarcolor</name> | |||
<type>text</type> | |||
<default></default> | |||
<notnull>false</notnull> | |||
<length>10</length> | |||
</field> | |||
<field> | |||
<name>timezone</name> | |||
<type>clob</type> | |||
<notnull>false</notnull> | |||
</field> | |||
<field> | |||
<name>components</name> | |||
<type>text</type> | |||
<default></default> | |||
<notnull>false</notnull> | |||
<length>100</length> | |||
</field> | |||
</declaration> | |||
</table> | |||
</database> |
@@ -0,0 +1,131 @@ | |||
<?php | |||
/** | |||
* @author Thomas Müller <thomas.mueller@tmit.eu> | |||
* | |||
* @copyright Copyright (c) 2016, ownCloud, Inc. | |||
* @license AGPL-3.0 | |||
* | |||
* This code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License, version 3, | |||
* as published by the Free Software Foundation. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Affero General Public License, version 3, | |||
* along with this program. If not, see <http://www.gnu.org/licenses/> | |||
* | |||
*/ | |||
namespace OCA\DAV\Tests\Unit\Migration; | |||
use DomainException; | |||
use OCA\Dav\Migration\AddressBookAdapter; | |||
use OCA\Dav\Migration\CalendarAdapter; | |||
use OCP\IDBConnection; | |||
use Test\TestCase; | |||
/** | |||
* Class CalendarAdapterTest | |||
* | |||
* @group DB | |||
* | |||
* @package OCA\DAV\Tests\Unit\Migration | |||
*/ | |||
class CalendarAdapterTest extends TestCase { | |||
/** @var IDBConnection */ | |||
private $db; | |||
/** @var CalendarAdapter */ | |||
private $adapter; | |||
/** @var array */ | |||
private $cals = []; | |||
/** @var array */ | |||
private $calObjs = []; | |||
public function setUp() { | |||
parent::setUp(); | |||
$this->db = \OC::$server->getDatabaseConnection(); | |||
$manager = new \OC\DB\MDB2SchemaManager($this->db); | |||
$manager->createDbFromStructure(__DIR__ . '/calendar_schema.xml'); | |||
$this->adapter = new CalendarAdapter($this->db); | |||
} | |||
public function tearDown() { | |||
$this->db->dropTable('clndr_calendars'); | |||
$this->db->dropTable('clndr_objects'); | |||
parent::tearDown(); | |||
} | |||
/** | |||
* @expectedException DomainException | |||
*/ | |||
public function testOldTablesDoNotExist() { | |||
$adapter = new AddressBookAdapter(\OC::$server->getDatabaseConnection(), 'crazy_table_that_does_no_exist'); | |||
$adapter->setup(); | |||
} | |||
public function test() { | |||
// insert test data | |||
$builder = $this->db->getQueryBuilder(); | |||
$builder->insert('clndr_calendars') | |||
->values([ | |||
'userid' => $builder->createNamedParameter('test-user-666'), | |||
'displayname' => $builder->createNamedParameter('Display Name'), | |||
'uri' => $builder->createNamedParameter('events'), | |||
'ctag' => $builder->createNamedParameter('112233'), | |||
'active' => $builder->createNamedParameter('1') | |||
]) | |||
->execute(); | |||
$builder = $this->db->getQueryBuilder(); | |||
$builder->insert('clndr_objects') | |||
->values([ | |||
'calendarid' => $builder->createNamedParameter(6666), | |||
'objecttype' => $builder->createNamedParameter('VEVENT'), | |||
'startdate' => $builder->createNamedParameter(new \DateTime(), 'datetime'), | |||
'enddate' => $builder->createNamedParameter(new \DateTime(), 'datetime'), | |||
'repeating' => $builder->createNamedParameter(0), | |||
'summary' => $builder->createNamedParameter('Something crazy will happen'), | |||
'uri' => $builder->createNamedParameter('event.ics'), | |||
'lastmodified' => $builder->createNamedParameter('112233'), | |||
]) | |||
->execute(); | |||
$builder = $this->db->getQueryBuilder(); | |||
$builder->insert('share') | |||
->values([ | |||
'share_type' => $builder->createNamedParameter(1), | |||
'share_with' => $builder->createNamedParameter('user01'), | |||
'uid_owner' => $builder->createNamedParameter('user02'), | |||
'item_type' => $builder->createNamedParameter('calendar'), | |||
'item_source' => $builder->createNamedParameter(6666), | |||
'item_target' => $builder->createNamedParameter('Contacts (user02)'), | |||
]) | |||
->execute(); | |||
// test the adapter | |||
$this->adapter->foreachCalendar('test-user-666', function($row) { | |||
$this->cals[] = $row; | |||
}); | |||
$this->assertArrayHasKey('id', $this->cals[0]); | |||
$this->assertEquals('test-user-666', $this->cals[0]['userid']); | |||
$this->assertEquals('Display Name', $this->cals[0]['displayname']); | |||
$this->assertEquals('events', $this->cals[0]['uri']); | |||
$this->assertEquals('112233', $this->cals[0]['ctag']); | |||
$this->adapter->foreachCalendarObject(6666, function($row) { | |||
$this->calObjs[]= $row; | |||
}); | |||
$this->assertArrayHasKey('id', $this->calObjs[0]); | |||
$this->assertEquals(6666, $this->calObjs[0]['calendarid']); | |||
// test getShares | |||
$shares = $this->adapter->getShares(6666); | |||
$this->assertEquals(1, count($shares)); | |||
} | |||
} |
@@ -0,0 +1,76 @@ | |||
<?php | |||
/** | |||
* @author Thomas Müller <thomas.mueller@tmit.eu> | |||
* | |||
* @copyright Copyright (c) 2016, ownCloud, Inc. | |||
* @license AGPL-3.0 | |||
* | |||
* This code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License, version 3, | |||
* as published by the Free Software Foundation. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Affero General Public License, version 3, | |||
* along with this program. If not, see <http://www.gnu.org/licenses/> | |||
* | |||
*/ | |||
namespace OCA\DAV\Tests\Unit\Migration; | |||
use OCA\DAV\CalDAV\CalDavBackend; | |||
use OCA\Dav\Migration\CalendarAdapter; | |||
use Test\TestCase; | |||
class MigrateCalendarTest extends TestCase { | |||
public function testMigration() { | |||
/** @var CalendarAdapter | \PHPUnit_Framework_MockObject_MockObject $adapter */ | |||
$adapter = $this->mockAdapter(); | |||
/** @var CalDavBackend | \PHPUnit_Framework_MockObject_MockObject $cardDav */ | |||
$cardDav = $this->getMockBuilder('\OCA\Dav\CalDAV\CalDAVBackend')->disableOriginalConstructor()->getMock(); | |||
$cardDav->method('createCalendar')->willReturn(666); | |||
$cardDav->expects($this->once())->method('createCalendar')->with('principals/users/test01', 'test_contacts'); | |||
$cardDav->expects($this->once())->method('createCalendarObject')->with(666, '63f0dd6c-39d5-44be-9d34-34e7a7441fc2.ics', 'BEGIN:VCARD'); | |||
$m = new \OCA\Dav\Migration\MigrateCalendars($adapter, $cardDav); | |||
$m->migrateForUser('test01'); | |||
} | |||
/** | |||
* @return \PHPUnit_Framework_MockObject_MockObject | |||
*/ | |||
private function mockAdapter($shares = []) { | |||
$adapter = $this->getMockBuilder('\OCA\Dav\Migration\CalendarAdapter') | |||
->disableOriginalConstructor() | |||
->getMock(); | |||
$adapter->method('foreachCalendar')->willReturnCallback(function ($user, \Closure $callBack) { | |||
$callBack([ | |||
// calendarorder | calendarcolor | timezone | components | |||
'id' => 0, | |||
'userid' => $user, | |||
'displayname' => 'Test Contacts', | |||
'uri' => 'test_contacts', | |||
'ctag' => 1234567890, | |||
'active' => 1, | |||
'calendarorder' => '0', | |||
'calendarcolor' => '#b3dc6c', | |||
'timezone' => null, | |||
'components' => 'VEVENT,VTODO,VJOURNAL' | |||
]); | |||
}); | |||
$adapter->method('foreachCalendarObject')->willReturnCallback(function ($addressBookId, \Closure $callBack) { | |||
$callBack([ | |||
'userid' => $addressBookId, | |||
'uri' => '63f0dd6c-39d5-44be-9d34-34e7a7441fc2.ics', | |||
'calendardata' => 'BEGIN:VCARD' | |||
]); | |||
}); | |||
$adapter->method('getShares')->willReturn($shares); | |||
return $adapter; | |||
} | |||
} |