[Pkg-owncloud-commits] [php-sabre-vobject] 16/65: Making the recurrence iterator faster on large calendars.

David Prévot taffit at moszumanska.debian.org
Tue Feb 24 23:57:14 UTC 2015


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository php-sabre-vobject.

commit fa70cac9287361e91ea6e22ddbcd0e4ceff4553c
Author: Evert Pot <evert at rooftopsolutions.nl>
Date:   Fri Jan 23 00:48:05 2015 -0500

    Making the recurrence iterator faster on large calendars.
---
 bin/rrulebench.php                             |  32 ++++++
 composer.json                                  |   3 +-
 lib/Component/VCalendar.php                    | 139 ++++++++++++++++++++++++-
 lib/Recur/EventIterator.php                    |   7 +-
 tests/VObject/Recur/EventIterator/MainTest.php |   2 +-
 5 files changed, 174 insertions(+), 9 deletions(-)

diff --git a/bin/rrulebench.php b/bin/rrulebench.php
new file mode 100644
index 0000000..f151819
--- /dev/null
+++ b/bin/rrulebench.php
@@ -0,0 +1,32 @@
+<?php
+
+include __DIR__ . '/../vendor/autoload.php';
+
+if ($argc < 4) {
+    echo "sabre/vobject ", Sabre\VObject\Version::VERSION, " RRULE benchmark\n";
+    echo "\n";
+    echo "This script can be used to measure the speed of the 'recurrence expansion'\n";
+    echo "system.";
+    echo "\n";
+    echo "Usage: " . $argv[0] . " inputfile.ics startdate enddate\n";
+    die();
+}
+
+list(, $inputFile, $startDate, $endDate) = $argv;
+
+$bench = new Hoa\Bench\Bench();
+$bench->parse->start();
+
+echo "Parsing.\n";
+$vobj = Sabre\VObject\Reader::read(fopen($inputFile,'r'));
+
+$bench->parse->stop();
+
+echo "Expanding.\n";
+$bench->expand->start();
+
+$vobj->expand(new DateTime($startDate), new DateTime($endDate));
+
+$bench->expand->stop();
+
+echo $bench,"\n";
diff --git a/composer.json b/composer.json
index 309c08a..54946cd 100644
--- a/composer.json
+++ b/composer.json
@@ -10,7 +10,8 @@
     },
     "require-dev" : {
         "phpunit/phpunit" : "*",
-        "squizlabs/php_codesniffer": "*"
+        "squizlabs/php_codesniffer": "*",
+        "hoa/bench": "~2.14.12"
     },
     "authors" : [
         {
diff --git a/lib/Component/VCalendar.php b/lib/Component/VCalendar.php
index 9d17e20..a4e3e01 100644
--- a/lib/Component/VCalendar.php
+++ b/lib/Component/VCalendar.php
@@ -270,7 +270,6 @@ class VCalendar extends VObject\Document {
             }
 
 
-
             $uid = (string)$vevent->uid;
             if (!$uid) {
                 throw new \LogicException('Event did not have a UID!');
@@ -278,6 +277,7 @@ class VCalendar extends VObject\Document {
 
             try {
                 $it = new EventIterator($this, $vevent->uid, $timeZone);
+
             } catch (NoInstancesException $e) {
                 // This event is recurring, but it doesn't have a single
                 // instance. We are skipping this event from the output
@@ -486,5 +486,142 @@ class VCalendar extends VObject\Document {
 
     }
 
+    /**
+     * If this is marked true, it means the UID index needs to be regenerated.
+     *
+     * @var bool
+     */
+    protected $dirtyIndex = false;
+
+    /**
+     * Index with events, todos and journals that have a specific id.
+     *
+     * @var array
+     */
+    protected $uidIndex = [];
+
+    /**
+     * Mark the UID index as 'dirty', which means it needs to be regenerated
+     * on the next use.
+     *
+     * @return void
+     */
+    function dirty() {
+
+        $this->dirtyIndex = true;
+
+    }
+
+    /**
+     * Returns all components that match a UID.
+     */
+    function getByUID($uid) {
+
+        if ($this->dirtyIndex) {
+            $this->uidIndex = [];
+            foreach($this->children as $key=>$child) {
+                if (!$child instanceof Component) {
+                    continue;
+                }
+                $cuid = $child->select('UID');
+                if ($cuid) {
+                    $cuid = current($cuid)->getValue();
+                    if (isset($this->uidIndex[$cuid])) {
+                        $this->uidIndex[$cuid][] = $key;
+                    } else {
+                        $this->uidIndex[$cuid] = [$key];
+                    }
+                }
+            }
+            $this->dirtyIndex = false;
+        }
+        if (isset($this->uidIndex[$uid])) {
+            return array_map(
+                function($key) {
+                    return $this->children[$key];
+                },
+                $this->uidIndex[$uid]
+            );
+        } else {
+            return [];
+        }
+
+    }
+
+    /**
+     * Adds a new property or component, and returns the new item.
+     *
+     * This method has 3 possible signatures:
+     *
+     * add(Component $comp) // Adds a new component
+     * add(Property $prop)  // Adds a new property
+     * add($name, $value, array $parameters = array()) // Adds a new property
+     * add($name, array $children = array()) // Adds a new component
+     * by name.
+     *
+     * @return Node
+     */
+    function add($a1, $a2 = null, $a3 = null) {
+        $r = parent::add($a1, $a2, $a3);
+        $this->dirty();
+        return $r;
+    }
+
+
+    /**
+     * This method removes a component or property from this component.
+     *
+     * You can either specify the item by name (like DTSTART), in which case
+     * all properties/components with that name will be removed, or you can
+     * pass an instance of a property or component, in which case only that
+     * exact item will be removed.
+     *
+     * The removed item will be returned. In case there were more than 1 items
+     * removed, only the last one will be returned.
+     *
+     * @param mixed $item
+     * @return void
+     */
+    function remove($item) {
+
+        parent::remove($item);
+        $this->dirty();
+
+    }
+
+    /**
+     * Using the setter method you can add properties or subcomponents
+     *
+     * You can either pass a Component, Property
+     * object, or a string to automatically create a Property.
+     *
+     * If the item already exists, it will be removed. If you want to add
+     * a new item with the same name, always use the add() method.
+     *
+     * @param string $name
+     * @param mixed $value
+     * @return void
+     */
+    function __set($name, $value) {
+
+        parent::__set($name, $value);
+        $this->dirty();
+
+    }
+
+    /**
+     * Removes all properties and components within this component with the
+     * specified name.
+     *
+     * @param string $name
+     * @return void
+     */
+    function __unset($name) {
+
+        parent::__unset($name);
+        $this->dirty();
+
+    }
+
 }
 
diff --git a/lib/Recur/EventIterator.php b/lib/Recur/EventIterator.php
index c621293..bf3fe50 100644
--- a/lib/Recur/EventIterator.php
+++ b/lib/Recur/EventIterator.php
@@ -99,12 +99,7 @@ class EventIterator implements \Iterator {
             if (!isset($vcal->VEVENT)) {
                 throw new InvalidArgumentException('No events found in this calendar');
             }
-            $events = array();
-            foreach($vcal->VEVENT as $event) {
-                if ($event->uid->getValue() === $uid) {
-                    $events[] = $event;
-                }
-            }
+            $events = $vcal->getByUID($uid);
 
         }
 
diff --git a/tests/VObject/Recur/EventIterator/MainTest.php b/tests/VObject/Recur/EventIterator/MainTest.php
index 064210c..3ffe35b 100644
--- a/tests/VObject/Recur/EventIterator/MainTest.php
+++ b/tests/VObject/Recur/EventIterator/MainTest.php
@@ -1,6 +1,6 @@
 <?php
 
-namespace Sabre\VObject\EventIterator;
+namespace Sabre\VObject\Recur\EventIterator;
 
 use DateTime;
 use DateTimeZone;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/php-sabre-vobject.git



More information about the Pkg-owncloud-commits mailing list