Add object storage driver.
authorJan Schneider <jan@horde.org>
Thu, 6 May 2010 15:50:50 +0000 (17:50 +0200)
committerJan Schneider <jan@horde.org>
Thu, 6 May 2010 15:51:09 +0000 (17:51 +0200)
framework/Alarm/lib/Horde/Alarm/Object.php [new file with mode: 0644]
framework/Alarm/package.xml
framework/Alarm/test/Horde/Alarm/ObjectTest.php [new file with mode: 0644]

diff --git a/framework/Alarm/lib/Horde/Alarm/Object.php b/framework/Alarm/lib/Horde/Alarm/Object.php
new file mode 100644 (file)
index 0000000..a7d5af3
--- /dev/null
@@ -0,0 +1,278 @@
+<?php
+/**
+ * @package Horde_Alarm
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ */
+
+/**
+ * The Horde_Alarm_Object:: class is a Horde_Alarm storage implementation
+ * using an object instance.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Alarm
+ */
+class Horde_Alarm_Object extends Horde_Alarm
+{
+    protected $_alarms = array();
+
+    /**
+     * Returns a certain alarm.
+     *
+     * @param string $id    The alarm's unique id.
+     * @param string $user  The alarm's user.
+     *
+     * @return array  An alarm hash.
+     */
+    protected function &_findAlarm($id, $user)
+    {
+        foreach ($this->_alarms as &$alarm) {
+            if ($alarm['id'] == $id && $alarm['user'] === $user) {
+                return $alarm;
+            }
+        }
+        $result = null;
+        return $result;
+    }
+
+    /**
+     * Sorts a number of alarms in chronological order.
+     */
+    protected function _sortAlarms($a, $b)
+    {
+        $cmp = $a['start']->compareDateTime($b['start']);
+        if ($cmp) {
+            return $cmp;
+        }
+        if (empty($a['end'])) {
+            return -1;
+        }
+        if (empty($b['end'])) {
+            return 1;
+        }
+        return $a['end']->compareDateTime($b['end']);
+    }
+
+    /**
+     * Returns a list of alarms from the backend.
+     *
+     * @param Horde_Date $time  The time when the alarms should be active.
+     * @param string $user      Return alarms for this user, all users if
+     *                          null, or global alarms if empty.
+     *
+     * @return array  A list of alarm hashes.
+     * @throws Horde_Alarm_Exception
+     */
+    protected function _list($user, Horde_Date $time)
+    {
+        $alarms = array();
+        foreach ($this->_alarms as $alarm) {
+            if (empty($alarm['dismissed']) &&
+                ((empty($alarm['snooze']) && $alarm['start']->compareDateTime($time) <= 0) ||
+                 $alarm['snooze']->compareDateTime($time) <= 0) &&
+                (empty($alarm['end']) || $alarm['end']->compareDateTime($time) => 0) &&
+                (is_null($user) || empty($alarm['uid']) || $alarm['uid'] = $user)) {
+                $alarms[] = $alarm;
+            }
+        }
+        usort($alarms, array($this, '_sortAlarms'));
+        return $alarms;
+    }
+
+    /**
+     * Returns an alarm hash from the backend.
+     *
+     * @param string $id    The alarm's unique id.
+     * @param string $user  The alarm's user.
+     *
+     * @return array  An alarm hash.
+     * @throws Horde_Alarm_Exception
+     */
+    protected function _get($id, $user)
+    {
+        $alarm = $this->_findAlarm($id, $user);
+        if (!$alarm) {
+            throw new Horde_Alarm_Exception('Alarm not found');
+        }
+        return $alarm;
+    }
+
+    /**
+     * Adds an alarm hash to the backend.
+     *
+     * @param array $alarm  An alarm hash.
+     */
+    protected function _add(array $alarm)
+    {
+        $alarm = array_merge(
+            array('user' => '',
+                  'end' => null,
+                  'text' => null,
+                  'snooze' => null,
+                  'internal' => null),
+            $alarm);
+        $this->_alarms[] = $alarm;
+    }
+
+    /**
+     * Updates an alarm hash in the backend.
+     *
+     * @param array $alarm         An alarm hash.
+     * @param boolean $keepsnooze  Whether to keep the snooze value unchanged.
+     */
+    protected function _update(array $alarm, $keepsnooze = false)
+    {
+        $user = isset($alarm['user']) ? $alarm['user'] : null;
+        $al = &$this->_findAlarm($alarm['id'], $user);
+
+        foreach (array('start', 'end', 'methods', 'params', 'title', 'text') as $property) {
+            $al[$property] = $alarm[$property];
+        }
+        if (!$keepsnooze) {
+            $al['snooze'] = null;
+        }
+    }
+
+    /**
+     * Updates internal alarm properties, i.e. properties not determined by
+     * the application setting the alarm.
+     *
+     * @param string $id       The alarm's unique id.
+     * @param string $user     The alarm's user
+     * @param array $internal  A hash with the internal data.
+     *
+     * @throws Horde_Alarm_Exception
+     */
+    protected function _internal($id, $user, array $internal)
+    {
+        $alarm = &$this->_findAlarm($id, $user);
+        $alarm['internal'] = $internal;
+    }
+
+    /**
+     * Returns whether an alarm with the given id exists already.
+     *
+     * @param string $id    The alarm's unique id.
+     * @param string $user  The alarm's user
+     *
+     * @return boolean  True if the specified alarm exists.
+     * @throws Horde_Alarm_Exception
+     */
+    protected function _exists($id, $user)
+    {
+        return (bool)$this->_findAlarm($id, $user);
+    }
+
+    /**
+     * Delays (snoozes) an alarm for a certain period.
+     *
+     * @param string $id          The alarm's unique id.
+     * @param string $user        The alarm's user
+     * @param Horde_Date $snooze  The snooze time.
+     *
+     * @throws Horde_Alarm_Exception
+     */
+    protected function _snooze($id, $user, Horde_Date $snooze)
+    {
+        $alarm = &$this->_findAlarm($id, $user);
+        $alarm['snooze'] = $snooze;
+    }
+
+    /**
+     * Returns whether an alarm is snoozed.
+     *
+     * @param string $id        The alarm's unique id.
+     * @param string $user      The alarm's user
+     * @param Horde_Date $time  The time when the alarm may be snoozed.
+     *
+     * @return boolean  True if the alarm is snoozed.
+     * @throws Horde_Alarm_Exception
+     */
+    protected function _isSnoozed($id, $user, Horde_Date $time)
+    {
+        $alarm = $this->_findAlarm($id, $user);
+        return !empty($alarm['dismissed']) ||
+            (isset($alarm['snooze']) &&
+             $alarm['snooze']->compareDateTime($time) >= 0);
+    }
+
+    /**
+     * Dismisses an alarm.
+     *
+     * @param string $id          The alarm's unique id.
+     * @param string $user        The alarm's user
+     *
+     * @throws Horde_Alarm_Exception
+     */
+    protected function _dismiss($id, $user)
+    {
+        $alarm = &$this->_findAlarm($id, $user);
+        $alarm['dismissed'] = true;
+    }
+
+    /**
+     * Deletes an alarm from the backend.
+     *
+     * @param string $id    The alarm's unique id.
+     * @param string $user  The alarm's user. All users' alarms if null.
+     *
+     * @throws Horde_Alarm_Exception
+     */
+    protected function _delete($id, $user = null)
+    {
+        $newAlarms = array();
+        foreach ($this->_alarms as &$alarm) {
+            if ($alarm['id'] != $id ||
+                (!is_null($user) && $alarm['user'] != $user)) {
+                $newAlarms[] = $alarm;
+            }
+        }
+        $this->_alarms = $newAlarms;
+    }
+
+    /**
+     * Garbage collects old alarms in the backend.
+     *
+     * @throws Horde_Alarm_Exception
+     */
+    protected function _gc()
+    {
+    }
+
+    /**
+     * Attempts to initialize the backend.
+     *
+     * @throws Horde_Alarm_Exception
+     */
+    public function initialize()
+    {
+    }
+
+    /**
+     * Converts a value from the driver's charset.
+     *
+     * @param mixed $value  Value to convert.
+     *
+     * @return mixed  Converted value.
+     */
+    protected function _fromDriver($value)
+    {
+        return $value;
+    }
+
+    /**
+     * Converts a value to the driver's charset.
+     *
+     * @param mixed $value  Value to convert.
+     *
+     * @return mixed  Converted value.
+     */
+    protected function _toDriver($value)
+    {
+        return $value;
+    }
+
+}
index 55e503a..a2158ba 100644 (file)
@@ -33,6 +33,7 @@ http://pear.php.net/dtd/package-2.0.xsd">
     <dir name="Horde">
      <dir name="Alarm">
       <file name="Exception.php" role="php" />
+      <file name="Object.php" role="php" />
       <file name="Sql.php" role="php" />
      </dir> <!-- /lib/Horde/Alarm -->
      <file name="Alarm.php" role="php" />
@@ -80,6 +81,7 @@ http://pear.php.net/dtd/package-2.0.xsd">
  <phprelease>
   <filelist>
    <install name="lib/Horde/Alarm/Exception.php" as="Horde/Alarm/Exception.php" />
+   <install name="lib/Horde/Alarm/Object.php" as="Horde/Alarm/Object.php" />
    <install name="lib/Horde/Alarm/Sql.php" as="Horde/Alarm/Sql.php" />
    <install name="lib/Horde/Alarm.php" as="Horde/Alarm.php" />
   </filelist>
diff --git a/framework/Alarm/test/Horde/Alarm/ObjectTest.php b/framework/Alarm/test/Horde/Alarm/ObjectTest.php
new file mode 100644 (file)
index 0000000..2670a1f
--- /dev/null
@@ -0,0 +1,154 @@
+<?php
+/**
+ * @author     Jan Schneider <jan@horde.org>
+ * @license    http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @category   Horde
+ * @package    Horde_Alarm
+ * @subpackage UnitTests
+ */
+
+class Horde_Alarm_ObjectTest extends PHPUnit_Framework_TestCase
+{
+    protected static $alarm;
+    protected static $date;
+    protected static $end;
+
+    public function testFactory()
+    {
+        self::$alarm = Horde_Alarm::factory('Object');
+    }
+
+    /**
+     * @depends testFactory
+     */
+    public function testSet()
+    {
+        $now = time();
+        self::$date = new Horde_Date($now);
+        self::$end = new Horde_Date($now + 3600);
+        $hash = array('id' => 'personalalarm',
+                      'user' => 'john',
+                      'start' => self::$date,
+                      'end' => self::$end,
+                      'methods' => array(),
+                      'params' => array(),
+                      'title' => 'This is a personal alarm.');
+        self::$alarm->set($hash);
+    }
+
+    /**
+     * @depends testSet
+     */
+    public function testExists()
+    {
+        $this->assertTrue(self::$alarm->exists('personalalarm', 'john'));
+    }
+
+    /**
+     * @depends testExists
+     */
+    public function testGet()
+    {
+        $alarm = self::$alarm->get('personalalarm', 'john');
+        $this->assertType('array', $alarm);
+        $this->assertEquals('personalalarm', $alarm['id']);
+        $this->assertEquals('john', $alarm['user']);
+        $this->assertEquals(array(), $alarm['methods']);
+        $this->assertEquals(array(), $alarm['params']);
+        $this->assertEquals('This is a personal alarm.', $alarm['title']);
+        $this->assertNull($alarm['text']);
+        $this->assertNull($alarm['snooze']);
+        $this->assertNull($alarm['internal']);
+        $this->assertTrue($alarm['start'] instanceof Horde_Date);
+        $this->assertTrue($alarm['end'] instanceof Horde_Date);
+        $this->assertEquals(0, $alarm['start']->compareDateTime(self::$date));
+        return $alarm;
+    }
+
+    /**
+     * @depends testGet
+     */
+    public function testUpdate($alarm)
+    {
+        $alarm['title'] = 'Changed alarm text';
+        self::$alarm->set($alarm);
+    }
+
+    /**
+     * @depends testUpdate
+     */
+    public function testListAlarms()
+    {
+        self::$alarm->set(array('id' => 'publicalarm',
+                                'start' => self::$date,
+                                'end' => self::$end,
+                                'methods' => array(),
+                                'params' => array(),
+                                'title' => 'This is a public alarm.'));
+        self::$date->min--;
+        $list = self::$alarm->listAlarms('john');
+        $this->assertEquals(2, count($list));
+        $this->assertEquals('publicalarm', $list[0]['id']);
+        $this->assertEquals('personalalarm', $list[1]['id']);
+    }
+
+    /**
+     * @depends testListAlarms
+     */
+    public function testDelete()
+    {
+        self::$alarm->delete('publicalarm', '');
+        $list = self::$alarm->listAlarms('john');
+        $this->assertEquals(1, count($list));
+        $this->assertEquals('personalalarm', $list[0]['id']);
+    }
+
+    /**
+     * @depends testDelete
+     * @expectedException Horde_Alarm_Exception
+     */
+    public function testSnoozeException()
+    {
+        self::$alarm->snooze('personalalarm', 'jane', 30);
+    }
+
+    /**
+     * @depends testDelete
+     */
+    public function testSnooze()
+    {
+        self::$alarm->snooze('personalalarm', 'john', 30);
+        $this->assertTrue(self::$alarm->isSnoozed('personalalarm', 'john'));
+        $list = self::$alarm->listAlarms('john');
+        $this->assertEquals(0, count($list));
+        $list = self::$alarm->listAlarms('john', self::$end);
+        $this->assertEquals(1, count($list));
+        $this->assertEquals('personalalarm', $list[0]['id']);
+    }
+
+    /**
+     * @depends testSnooze
+     */
+    public function testAlarmWithoutEnd()
+    {
+        self::$alarm->set(array('id' => 'noend',
+                                'user' => 'john',
+                                'start' => self::$date,
+                                'methods' => array('notify'),
+                                'params' => array(),
+                                'title' => 'This is an alarm without end.'));
+        $list = self::$alarm->listAlarms('john', self::$end);
+        $this->assertEquals(2, count($list));
+        $this->assertEquals('noend', $list[0]['id']);
+        $this->assertEquals('personalalarm', $list[1]['id']);
+    }
+
+    /**
+     * @depends testAlarmWithoutEnd
+     */
+    public function testCleanUp()
+    {
+        self::$alarm->delete('noend', 'john');
+        self::$alarm->delete('personalalarm', 'john');
+    }
+}