forked from horde/kronolith
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement an optional backend to store incoming caldav events
- Loading branch information
Showing
9 changed files
with
306 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
<?php | ||
/** | ||
* Horde_Injector based factory for Icalendar storage. | ||
*/ | ||
class Kronolith_Factory_IcalendarStorage | ||
{ | ||
/** | ||
* Instances. | ||
* | ||
* @var array | ||
*/ | ||
private $_instances = array(); | ||
|
||
/** | ||
* Return the caldav driver instance. | ||
* | ||
* @param string $driver The storage backend to use. | ||
* @param array $params Driver params. | ||
* | ||
* @return Kronolith_Caldav_Storage | ||
* @throws Kronolith_Exception | ||
*/ | ||
public function create(Horde_Injector $injector): Kronolith_Icalendar_Storage | ||
{ | ||
$driver = Horde_String::ucfirst($GLOBALS['conf']['icalendar']['driver']); | ||
|
||
if (!empty($this->_instances[$driver])) { | ||
return $this->_instances[$driver]; | ||
} | ||
|
||
switch ($driver) { | ||
case 'Sql': | ||
$params = Horde::getDriverConfig('icalendar', 'Sql'); | ||
if (isset($params['driverconfig']) && | ||
$params['driverconfig'] != 'horde') { | ||
$customParams = $params; | ||
unset($customParams['driverconfig'], $customParams['table']); | ||
$db = $injector->getInstance('Horde_Core_Factory_Db')->create('kronolith', $customParams); | ||
} else { | ||
$db = $injector->getInstance('Horde_Db_Adapter'); | ||
} | ||
$instance = new Kronolith_Icalendar_Storage_Sql($db); | ||
break; | ||
|
||
case 'null': | ||
default: | ||
$instance = new Kronolith_Icalendar_Storage_Null($db); | ||
break; | ||
} | ||
$this->_instances[$driver] = $instance; | ||
|
||
return $instance; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?php | ||
interface Kronolith_Icalendar_Storage | ||
{ | ||
public function put(string $calendarId, string $eventUid, string $data): void; | ||
public function get(string $calendarId, string $eventUid): string; | ||
public function remove(string $calendarId, string $eventUid): void; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<?php | ||
/** | ||
* @author Ralf Lang <lang@b1-systems.de> | ||
*/ | ||
use \Horde_Rdo_Base as EntityBase; | ||
use \Kronolith_Icalendar_Sql as EntityMapper; | ||
/** | ||
* Entity class needed for Horde Rdo | ||
* | ||
* @internal This class is internal to the SQL Backend | ||
* for caldav vevent storage and should not be relied | ||
* upon outside the SQL specific context | ||
* | ||
* | ||
*/ | ||
class Kronolith_Icalendar_Storage_Entity extends EntityBase | ||
{ | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?php | ||
/** | ||
* Noop storage driver for CalDAV data | ||
* | ||
* Simplifies calling code which can just depend on storage interface | ||
*/ | ||
class Kronolith_Icalendar_Storage_Null implements Kronolith_Icalendar_Storage | ||
{ | ||
public function put(string $calendarId, string $eventUid, string $data): void | ||
{ | ||
return; | ||
} | ||
|
||
public function remove(string $calendarId, string $eventUid): void | ||
{ | ||
return; | ||
} | ||
|
||
|
||
public function get(string $calendarId, string $eventUid): string | ||
{ | ||
return ''; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
<?php | ||
/** | ||
* Simple storage for icalendar objects | ||
*/ | ||
declare (strict_types=1); | ||
//use \InvalidArgumentException; | ||
use \Kronolith_Icalendar_Storage_Entity as Entity; | ||
/** | ||
* Simple storage for caldav related data | ||
*/ | ||
class Kronolith_Icalendar_Storage_Sql extends \Horde_Rdo_Mapper implements Kronolith_Icalendar_Storage | ||
{ | ||
|
||
protected $_classname = Entity::class; | ||
protected $_table = 'kronolith_icalendar_storage'; | ||
|
||
/** | ||
* Remove existing item. | ||
* | ||
* If we wanted to name it delete, | ||
* we would need to make the rdo mapper a dependency | ||
* rather than inheriting from it. | ||
* @param string $calendarId The calendar ID to operate on | ||
* @param string $eventUid The Event to operate on | ||
* | ||
* @throw InvalidArgumentException | ||
* @return void | ||
*/ | ||
public function remove(string $calendarId, string $eventUid): void | ||
{ | ||
$this->_noNullString($calendarId, $eventUid); | ||
$entity = $this->_getEntity($calendarId, $eventUid); | ||
if ($entity) { | ||
$this->delete($entity); | ||
} | ||
} | ||
|
||
/** | ||
* Create or update item. | ||
* | ||
* @param string $calendarId The calendar ID to operate on | ||
* @param string $eventUid The Event to operate on | ||
* @param string $data The actual icalendar data | ||
* | ||
* @throw InvalidArgumentException | ||
* @return void | ||
*/ | ||
public function put(string $calendarId, string $eventUid, string $data): void | ||
{ | ||
$entity = $this->_getEntity($calendarId, $eventUid); | ||
if (empty($entity)) { | ||
$entity = new Entity([ | ||
'calendar_id' => $calendarId, | ||
'event_uid' => $eventUid, | ||
'event_data' => $data | ||
]); | ||
$entity->setMapper($this); | ||
} else { | ||
$entity->event_data = $data; | ||
} | ||
$entity->save(); | ||
} | ||
|
||
/** | ||
* Retrieve stored item. | ||
* | ||
* @param string $calendarId The calendar ID to operate on | ||
* @param string $eventUid The Event to operate on | ||
* | ||
* @throw InvalidArgumentException | ||
* @return string | ||
*/ | ||
public function get(string $calendarId, string $eventUid): string | ||
{ | ||
$entity = $this->_getEntity($calendarId, $eventUid); | ||
if ($entity) { | ||
return $entity->event_data; | ||
} | ||
return ''; | ||
} | ||
|
||
|
||
protected function _getEntity(string $calendarId, string $eventUid): ?Entity | ||
{ | ||
$this->_noNullString($calendarId, $eventUid); | ||
return $this->findOne([ | ||
'calendar_id' => $calendarId, | ||
'event_uid' => $eventUid | ||
]); | ||
} | ||
|
||
/** | ||
* Filter out invalid/malicious calls, throw Exception | ||
* | ||
* Rdo does undesirable actions on empty string arguments, | ||
* also they are not valid for our use case. | ||
* | ||
* @param string $calendarId The calendar ID to operate on | ||
* @param string $eventUid The Event to operate on | ||
* | ||
* @throw InvalidArgumentException | ||
* @return void | ||
*/ | ||
protected function _noNullString(string $calendarId, string $eventUid) | ||
{ | ||
if ($calendarId == '') { | ||
throw new InvalidArgumentException('Calendar ID must not be empty'); | ||
} | ||
if ($eventUid == '') { | ||
throw new InvalidArgumentException('Event UID must not be empty'); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<?php | ||
/** | ||
* Copyright 2020-2021 Horde LLC (http://www.horde.org/) | ||
* | ||
* See the enclosed file LICENSE for license information (GPL). If you | ||
* did not receive this file, see http://www.horde.org/licenses/gpl. | ||
* | ||
* @author Ralf Lang <lang@b1-systems.de> | ||
* @category Horde | ||
* @license http://www.horde.org/licenses/gpl GPL | ||
* @package Kronolith | ||
*/ | ||
|
||
/** | ||
* Add a table for storing caldav event details | ||
* | ||
* @author Ralf Lang <lang@b1-systems.de> | ||
* @category Horde | ||
* @license http://www.horde.org/licenses/gpl GPL | ||
* @package Kronolith | ||
*/ | ||
class KronolithIcalendarStorage extends Horde_Db_Migration_Base | ||
{ | ||
/** | ||
* Upgrade. | ||
*/ | ||
public function up() | ||
{ | ||
/** | ||
* NOTE: We use horde/rdo for SQL icalendar storage. | ||
* The ical_id is never read but the attribute helps us circumvent | ||
* rdo's notion that an item with an existing primary key must already | ||
* exist in backend. That would issue an UPDATE where an INSERT is more | ||
* appropriate. | ||
*/ | ||
$t = $this->createTable('kronolith_icalendar_storage', ['autoincrementKey' => 'ical_id']); | ||
$t->column('calendar_id', 'string', ['limit' => 255, 'null' => false]); | ||
$t->column('event_uid', 'string', ['limit' => 255, 'null' => false]); | ||
$t->column('event_data', 'text', ['null' => false]); | ||
$t->end(); | ||
$this->addIndex('kronolith_icalendar_storage', ['calendar_id', 'event_uid'], ['unique' => true]); | ||
} | ||
|
||
/** | ||
* Downgrade | ||
*/ | ||
public function down() | ||
{ | ||
$this->dropTable('kronolith_icalendar_storage'); | ||
} | ||
} |