2 commits - plugins/libkolab plugins/tasklist
Thomas Brüderli
bruederli at kolabsys.com
Wed Jul 11 09:17:16 CEST 2012
plugins/libkolab/bin/Date_Recurrence_weekday.diff | 325 ++++++++++++++++
plugins/libkolab/bin/Date_last_weekday.diff | 37 +
plugins/libkolab/bin/get_horde_date.sh | 46 +-
plugins/libkolab/lib/Horde_Date.php | 210 ++++++++++
plugins/libkolab/lib/Horde_Date_Recurrence.php | 378 +++++++------------
plugins/tasklist/localization/de_CH.inc | 2
plugins/tasklist/localization/en_US.inc | 2
plugins/tasklist/skins/larry/tasklist.css | 12
plugins/tasklist/skins/larry/templates/mainview.html | 14
9 files changed, 756 insertions(+), 270 deletions(-)
New commits:
commit b9c8346a4d57c58194479f8911f7004b4e7c417d
Author: Thomas Bruederli <thomas at roundcube.net>
Date: Wed Jul 11 09:17:16 2012 +0200
Patch Horde Date classes when importing them for the use in libkolab
diff --git a/plugins/libkolab/bin/Date_Recurrence_weekday.diff b/plugins/libkolab/bin/Date_Recurrence_weekday.diff
new file mode 100644
index 0000000..e8b767d
--- /dev/null
+++ b/plugins/libkolab/bin/Date_Recurrence_weekday.diff
@@ -0,0 +1,325 @@
+--- Date/Recurrence.php.orig 2012-07-10 19:54:48.000000000 +0200
++++ Date/Recurrence.php 2012-07-10 19:55:38.000000000 +0200
+@@ -95,6 +95,20 @@
+ public $recurData = null;
+
+ /**
++ * BYDAY recurrence number
++ *
++ * @var integer
++ */
++ public $recurNthDay = null;
++
++ /**
++ * BYMONTH recurrence data
++ *
++ * @var array
++ */
++ public $recurMonths = array();
++
++ /**
+ * All the exceptions from recurrence for this event.
+ *
+ * @var array
+@@ -157,6 +171,44 @@
+ }
+
+ /**
++ *
++ * @param integer $nthDay The nth weekday of month to repeat events on
++ */
++ public function setRecurNthWeekday($nth)
++ {
++ $this->recurNthDay = (int)$nth;
++ }
++
++ /**
++ *
++ * @return integer The nth weekday of month to repeat events.
++ */
++ public function getRecurNthWeekday()
++ {
++ return isset($this->recurNthDay) ? $this->recurNthDay : ceil($this->start->mday / 7);
++ }
++
++ /**
++ * Specifies the months for yearly (weekday) recurrence
++ *
++ * @param array $months List of months (integers) this event recurs on.
++ */
++ function setRecurByMonth($months)
++ {
++ $this->recurMonths = (array)$months;
++ }
++
++ /**
++ * Returns a list of months this yearly event recurs on
++ *
++ * @return array List of months (integers) this event recurs on.
++ */
++ function getRecurByMonth()
++ {
++ return $this->recurMonths;
++ }
++
++ /**
+ * Returns the days this event recurs on.
+ *
+ * @return integer A mask consisting of Horde_Date::MASK_* constants
+@@ -546,8 +598,13 @@
+ $estart = clone $this->start;
+
+ // What day of the week, and week of the month, do we recur on?
+- $nth = ceil($this->start->mday / 7);
+- $weekday = $estart->dayOfWeek();
++ if (isset($this->recurNthDay)) {
++ $nth = $this->recurNthDay;
++ $weekday = log($this->recurData, 2);
++ } else {
++ $nth = ceil($this->start->mday / 7);
++ $weekday = $estart->dayOfWeek();
++ }
+
+ // Adjust $estart to be the first candidate.
+ $offset = ($after->month - $estart->month) + ($after->year - $estart->year) * 12;
+@@ -660,8 +717,13 @@
+ $estart = clone $this->start;
+
+ // What day of the week, and week of the month, do we recur on?
+- $nth = ceil($this->start->mday / 7);
+- $weekday = $estart->dayOfWeek();
++ if (isset($this->recurNthDay)) {
++ $nth = $this->recurNthDay;
++ $weekday = log($this->recurData, 2);
++ } else {
++ $nth = ceil($this->start->mday / 7);
++ $weekday = $estart->dayOfWeek();
++ }
+
+ // Adjust $estart to be the first candidate.
+ $offset = floor(($after->year - $estart->year + $this->recurInterval - 1) / $this->recurInterval) * $this->recurInterval;
+@@ -894,15 +956,6 @@
+ case 'W':
+ $this->setRecurType(self::RECUR_WEEKLY);
+ if (!empty($remainder)) {
+- $maskdays = array(
+- 'SU' => Horde_Date::MASK_SUNDAY,
+- 'MO' => Horde_Date::MASK_MONDAY,
+- 'TU' => Horde_Date::MASK_TUESDAY,
+- 'WE' => Horde_Date::MASK_WEDNESDAY,
+- 'TH' => Horde_Date::MASK_THURSDAY,
+- 'FR' => Horde_Date::MASK_FRIDAY,
+- 'SA' => Horde_Date::MASK_SATURDAY,
+- );
+ $mask = 0;
+ while (preg_match('/^ ?[A-Z]{2} ?/', $remainder, $matches)) {
+ $day = trim($matches[0]);
+@@ -953,7 +1006,10 @@
+ list($year, $month, $mday) = sscanf($remainder, '%04d%02d%02d');
+ $this->setRecurEnd(new Horde_Date(array('year' => $year,
+ 'month' => $month,
+- 'mday' => $mday)));
++ 'mday' => $mday,
++ 'hour' => 23,
++ 'min' => 59,
++ 'sec' => 59)));
+ }
+ }
+ }
+@@ -1049,6 +1105,16 @@
+ // Always default the recurInterval to 1.
+ $this->setRecurInterval(isset($rdata['INTERVAL']) ? $rdata['INTERVAL'] : 1);
+
++ $maskdays = array(
++ 'SU' => Horde_Date::MASK_SUNDAY,
++ 'MO' => Horde_Date::MASK_MONDAY,
++ 'TU' => Horde_Date::MASK_TUESDAY,
++ 'WE' => Horde_Date::MASK_WEDNESDAY,
++ 'TH' => Horde_Date::MASK_THURSDAY,
++ 'FR' => Horde_Date::MASK_FRIDAY,
++ 'SA' => Horde_Date::MASK_SATURDAY,
++ );
++
+ switch (Horde_String::upper($rdata['FREQ'])) {
+ case 'DAILY':
+ $this->setRecurType(self::RECUR_DAILY);
+@@ -1057,15 +1123,6 @@
+ case 'WEEKLY':
+ $this->setRecurType(self::RECUR_WEEKLY);
+ if (isset($rdata['BYDAY'])) {
+- $maskdays = array(
+- 'SU' => Horde_Date::MASK_SUNDAY,
+- 'MO' => Horde_Date::MASK_MONDAY,
+- 'TU' => Horde_Date::MASK_TUESDAY,
+- 'WE' => Horde_Date::MASK_WEDNESDAY,
+- 'TH' => Horde_Date::MASK_THURSDAY,
+- 'FR' => Horde_Date::MASK_FRIDAY,
+- 'SA' => Horde_Date::MASK_SATURDAY,
+- );
+ $days = explode(',', $rdata['BYDAY']);
+ $mask = 0;
+ foreach ($days as $day) {
+@@ -1090,6 +1147,10 @@
+ case 'MONTHLY':
+ if (isset($rdata['BYDAY'])) {
+ $this->setRecurType(self::RECUR_MONTHLY_WEEKDAY);
++ if (preg_match('/(-?[1-4])([A-Z]+)/', $rdata['BYDAY'], $m)) {
++ $this->setRecurOnDay($maskdays[$m[2]]);
++ $this->setRecurNthWeekday($m[1]);
++ }
+ } else {
+ $this->setRecurType(self::RECUR_MONTHLY_DATE);
+ }
+@@ -1100,6 +1161,14 @@
+ $this->setRecurType(self::RECUR_YEARLY_DAY);
+ } elseif (isset($rdata['BYDAY'])) {
+ $this->setRecurType(self::RECUR_YEARLY_WEEKDAY);
++ if (preg_match('/(-?[1-4])([A-Z]+)/', $rdata['BYDAY'], $m)) {
++ $this->setRecurOnDay($maskdays[$m[2]]);
++ $this->setRecurNthWeekday($m[1]);
++ }
++ if ($rdata['BYMONTH']) {
++ $months = explode(',', $rdata['BYMONTH']);
++ $this->setRecurByMonth($months);
++ }
+ } else {
+ $this->setRecurType(self::RECUR_YEARLY_DATE);
+ }
+@@ -1163,13 +1232,19 @@
+ break;
+
+ case self::RECUR_MONTHLY_WEEKDAY:
+- $nth_weekday = (int)($this->start->mday / 7);
+- if (($this->start->mday % 7) > 0) {
+- $nth_weekday++;
++ if (isset($this->recurNthDay)) {
++ $nth_weekday = $this->recurNthDay;
++ $day_of_week = log($this->recurData, 2);
++ } else {
++ $day_of_week = $this->start->dayOfWeek();
++ $nth_weekday = (int)($this->start->mday / 7);
++ if (($this->start->mday % 7) > 0) {
++ $nth_weekday++;
++ }
+ }
+ $vcaldays = array('SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA');
+ $rrule = 'FREQ=MONTHLY;INTERVAL=' . $this->recurInterval
+- . ';BYDAY=' . $nth_weekday . $vcaldays[$this->start->dayOfWeek()];
++ . ';BYDAY=' . $nth_weekday . $vcaldays[$day_of_week];
+ break;
+
+ case self::RECUR_YEARLY_DATE:
+@@ -1182,15 +1257,22 @@
+ break;
+
+ case self::RECUR_YEARLY_WEEKDAY:
+- $nth_weekday = (int)($this->start->mday / 7);
+- if (($this->start->mday % 7) > 0) {
+- $nth_weekday++;
+- }
++ if (isset($this->recurNthDay)) {
++ $nth_weekday = $this->recurNthDay;
++ $day_of_week = log($this->recurData, 2);
++ } else {
++ $day_of_week = $this->start->dayOfWeek();
++ $nth_weekday = (int)($this->start->mday / 7);
++ if (($this->start->mday % 7) > 0) {
++ $nth_weekday++;
++ }
++ }
++ $months = !empty($this->recurMonths) ? join(',', $this->recurMonths) : $this->start->month;
+ $vcaldays = array('SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA');
+ $rrule = 'FREQ=YEARLY;INTERVAL=' . $this->recurInterval
+ . ';BYDAY='
+ . $nth_weekday
+- . $vcaldays[$this->start->dayOfWeek()]
++ . $vcaldays[$day_of_week]
+ . ';BYMONTH=' . $this->start->month;
+ break;
+ }
+@@ -1223,6 +1305,21 @@
+
+ $this->setRecurInterval((int)$hash['interval']);
+
++ $month2number = array(
++ 'january' => 1,
++ 'february' => 2,
++ 'march' => 3,
++ 'april' => 4,
++ 'may' => 5,
++ 'june' => 6,
++ 'july' => 7,
++ 'august' => 8,
++ 'september' => 9,
++ 'october' => 10,
++ 'november' => 11,
++ 'december' => 12,
++ );
++
+ $parse_day = false;
+ $set_daymask = false;
+ $update_month = false;
+@@ -1255,11 +1352,9 @@
+
+ case 'weekday':
+ $this->setRecurType(self::RECUR_MONTHLY_WEEKDAY);
+- $nth_weekday = (int)$hash['daynumber'];
+- $hash['daynumber'] = 1;
++ $this->setRecurNthWeekday($hash['daynumber']);
+ $parse_day = true;
+- $update_daynumber = true;
+- $update_weekday = true;
++ $set_daymask = true;
+ break;
+ }
+ break;
+@@ -1297,12 +1392,13 @@
+ }
+
+ $this->setRecurType(self::RECUR_YEARLY_WEEKDAY);
+- $nth_weekday = (int)$hash['daynumber'];
+- $hash['daynumber'] = 1;
++ $this->setRecurNthWeekday($hash['daynumber']);
+ $parse_day = true;
+- $update_month = true;
+- $update_daynumber = true;
+- $update_weekday = true;
++ $set_daymask = true;
++
++ if ($hash['month'] && isset($month2number[$hash['month']])) {
++ $this->setRecurByMonth($month2number[$hash['month']]);
++ }
+ break;
+ }
+ }
+@@ -1368,21 +1464,6 @@
+
+ if ($update_month || $update_daynumber || $update_weekday) {
+ if ($update_month) {
+- $month2number = array(
+- 'january' => 1,
+- 'february' => 2,
+- 'march' => 3,
+- 'april' => 4,
+- 'may' => 5,
+- 'june' => 6,
+- 'july' => 7,
+- 'august' => 8,
+- 'september' => 9,
+- 'october' => 10,
+- 'november' => 11,
+- 'december' => 12,
+- );
+-
+ if (isset($month2number[$hash['month']])) {
+ $this->start->month = $month2number[$hash['month']];
+ }
+@@ -1398,7 +1479,7 @@
+ }
+
+ if ($update_weekday) {
+- $this->start->setNthWeekday($last_found_day, $nth_weekday);
++ $this->setNthWeekday($nth_weekday);
+ }
+ }
+
diff --git a/plugins/libkolab/bin/Date_last_weekday.diff b/plugins/libkolab/bin/Date_last_weekday.diff
new file mode 100644
index 0000000..d260360
--- /dev/null
+++ b/plugins/libkolab/bin/Date_last_weekday.diff
@@ -0,0 +1,37 @@
+--- Date.php.orig 2012-07-10 19:14:26.000000000 +0200
++++ Date.php 2012-07-10 19:16:22.000000000 +0200
+@@ -627,16 +627,25 @@
+ return;
+ }
+
+- $this->_mday = 1;
+- $first = $this->dayOfWeek();
+- if ($weekday < $first) {
+- $this->_mday = 8 + $weekday - $first;
+- } else {
+- $this->_mday = $weekday - $first + 1;
++ if ($nth < 0) { // last $weekday of month
++ $this->_mday = $lastday = Horde_Date_Utils::daysInMonth($this->_month, $this->_year);
++ $last = $this->dayOfWeek();
++ $this->_mday += ($weekday - $last);
++ if ($this->_mday > $lastday)
++ $this->_mday -= 7;
++ }
++ else {
++ $this->_mday = 1;
++ $first = $this->dayOfWeek();
++ if ($weekday < $first) {
++ $this->_mday = 8 + $weekday - $first;
++ } else {
++ $this->_mday = $weekday - $first + 1;
++ }
++ $diff = 7 * $nth - 7;
++ $this->_mday += $diff;
++ $this->_correct(self::MASK_DAY, $diff < 0);
+ }
+- $diff = 7 * $nth - 7;
+- $this->_mday += $diff;
+- $this->_correct(self::MASK_DAY, $diff < 0);
+ }
+
+ /**
diff --git a/plugins/libkolab/bin/get_horde_date.sh b/plugins/libkolab/bin/get_horde_date.sh
index c75b7fd..b8e663d 100755
--- a/plugins/libkolab/bin/get_horde_date.sh
+++ b/plugins/libkolab/bin/get_horde_date.sh
@@ -1,24 +1,46 @@
#!/bin/sh
-# Copy Horde_Date_Recurrence classes and dependencies to stdout.
+# Copy Horde_Date_Recurrence classes and dependencies to the given target directory.
# This will create a standalone copy of the classes requried for date recurrence computation.
SRCDIR=$1
+DESTDIR=$2
+BINDIR=`dirname $0`
-if [ ! -d "$SRCDIR" ]; then
- echo "Usage: get_horde_date.sh SRCDIR"
- echo "Please enter a valid source directory of the Horde libs"
+if [ ! -d "$SRCDIR" -o ! -d "$DESTDIR" ]; then
+ echo "Usage: get_horde_date.sh SRCDIR DESTDIR"
+ echo "Please enter valid source and destination directories for the Horde libs"
exit 1
fi
+
+# concat Date.php and Date/Utils.php
+HORDE_DATE="$DESTDIR/Horde_Date.php"
+
echo "<?php
/**
* This is a concatenated copy of the following files:
- * Horde/Date/Utils.php, Horde/Date/Recurrence.php
+ * Horde/Date.php, Horde/Date/Utils.php
* Pull the latest version of these files from the PEAR channel of the Horde
* project at http://pear.horde.org by installing the Horde_Date package.
*/
+" > $HORDE_DATE
+
+patch $SRCDIR/Date.php $BINDIR/Date_last_weekday.diff --output=$HORDE_DATE.patched
+sed 's/<?php//; s/?>//' $HORDE_DATE.patched >> $HORDE_DATE
+sed 's/<?php//; s/?>//' $SRCDIR/Date/Utils.php >> $HORDE_DATE
+
+# copy and patch Date/Recurrence.php
+HORDE_DATE_RECURRENCE="$DESTDIR/Horde_Date_Recurrence.php"
+
+echo "<?php
+
+/**
+ * This is a modified copy of Horde/Date/Recurrence.php
+ * Pull the latest version of this file from the PEAR channel of the Horde
+ * project at http://pear.horde.org by installing the Horde_Date package.
+ */
if (!class_exists('Horde_Date'))
require_once(dirname(__FILE__) . '/Horde_Date.php');
@@ -29,10 +51,14 @@ class Horde_Date_Translation
function t(\$arg) { return \$arg; }
function ngettext(\$sing, \$plur, \$num) { return (\$num > 1 ? \$plur : \$sing); }
}
-"
+" > $HORDE_DATE_RECURRENCE
+
+patch $SRCDIR/Date/Recurrence.php $BINDIR/Date_Recurrence_weekday.diff --output=$HORDE_DATE_RECURRENCE.patched
+sed 's/<?php//; s/?>//' $HORDE_DATE_RECURRENCE.patched >> $HORDE_DATE_RECURRENCE
+
+# remove dependency to Horde_String
+sed -i '' "s/Horde_String::/strto/" $HORDE_DATE_RECURRENCE
+
+rm $DESTDIR/Horde_Date*.patched
-sed 's/<?php//; s/?>//' $SRCDIR/Date/Utils.php
-echo "\n"
-sed 's/<?php//; s/?>//' $SRCDIR/Date/Recurrence.php | sed -E "s/Horde_String::/strto/"
-echo "\n"
diff --git a/plugins/libkolab/lib/Horde_Date.php b/plugins/libkolab/lib/Horde_Date.php
index 4ddd9d5..9197f84 100644
--- a/plugins/libkolab/lib/Horde_Date.php
+++ b/plugins/libkolab/lib/Horde_Date.php
@@ -1,4 +1,13 @@
<?php
+
+/**
+ * This is a concatenated copy of the following files:
+ * Horde/Date/Utils.php, Horde/Date/Recurrence.php
+ * Pull the latest version of these files from the PEAR channel of the Horde
+ * project at http://pear.horde.org by installing the Horde_Date package.
+ */
+
+
/**
* Horde Date wrapper/logic class, including some calculation
* functions.
@@ -627,16 +636,25 @@ class Horde_Date
return;
}
- $this->_mday = 1;
- $first = $this->dayOfWeek();
- if ($weekday < $first) {
- $this->_mday = 8 + $weekday - $first;
- } else {
- $this->_mday = $weekday - $first + 1;
+ if ($nth < 0) { // last $weekday of month
+ $this->_mday = $lastday = Horde_Date_Utils::daysInMonth($this->_month, $this->_year);
+ $last = $this->dayOfWeek();
+ $this->_mday += ($weekday - $last);
+ if ($this->_mday > $lastday)
+ $this->_mday -= 7;
+ }
+ else {
+ $this->_mday = 1;
+ $first = $this->dayOfWeek();
+ if ($weekday < $first) {
+ $this->_mday = 8 + $weekday - $first;
+ } else {
+ $this->_mday = $weekday - $first + 1;
+ }
+ $diff = 7 * $nth - 7;
+ $this->_mday += $diff;
+ $this->_correct(self::MASK_DAY, $diff < 0);
}
- $diff = 7 * $nth - 7;
- $this->_mday += $diff;
- $this->_correct(self::MASK_DAY, $diff < 0);
}
/**
@@ -1110,3 +1128,177 @@ class Horde_Date
}
}
+
+/**
+ * @category Horde
+ * @package Date
+ */
+
+/**
+ * Horde Date wrapper/logic class, including some calculation
+ * functions.
+ *
+ * @category Horde
+ * @package Date
+ */
+class Horde_Date_Utils
+{
+ /**
+ * Returns whether a year is a leap year.
+ *
+ * @param integer $year The year.
+ *
+ * @return boolean True if the year is a leap year.
+ */
+ public static function isLeapYear($year)
+ {
+ if (strlen($year) != 4 || preg_match('/\D/', $year)) {
+ return false;
+ }
+
+ return (($year % 4 == 0 && $year % 100 != 0) || $year % 400 == 0);
+ }
+
+ /**
+ * Returns the date of the year that corresponds to the first day of the
+ * given week.
+ *
+ * @param integer $week The week of the year to find the first day of.
+ * @param integer $year The year to calculate for.
+ *
+ * @return Horde_Date The date of the first day of the given week.
+ */
+ public static function firstDayOfWeek($week, $year)
+ {
+ return new Horde_Date(sprintf('%04dW%02d', $year, $week));
+ }
+
+ /**
+ * Returns the number of days in the specified month.
+ *
+ * @param integer $month The month
+ * @param integer $year The year.
+ *
+ * @return integer The number of days in the month.
+ */
+ public static function daysInMonth($month, $year)
+ {
+ static $cache = array();
+ if (!isset($cache[$year][$month])) {
+ $date = new DateTime(sprintf('%04d-%02d-01', $year, $month));
+ $cache[$year][$month] = $date->format('t');
+ }
+ return $cache[$year][$month];
+ }
+
+ /**
+ * Returns a relative, natural language representation of a timestamp
+ *
+ * @todo Wider range of values ... maybe future time as well?
+ * @todo Support minimum resolution parameter.
+ *
+ * @param mixed $time The time. Any format accepted by Horde_Date.
+ * @param string $date_format Format to display date if timestamp is
+ * more then 1 day old.
+ * @param string $time_format Format to display time if timestamp is 1
+ * day old.
+ *
+ * @return string The relative time (i.e. 2 minutes ago)
+ */
+ public static function relativeDateTime($time, $date_format = '%x',
+ $time_format = '%X')
+ {
+ $date = new Horde_Date($time);
+
+ $delta = time() - $date->timestamp();
+ if ($delta < 60) {
+ return sprintf(Horde_Date_Translation::ngettext("%d second ago", "%d seconds ago", $delta), $delta);
+ }
+
+ $delta = round($delta / 60);
+ if ($delta < 60) {
+ return sprintf(Horde_Date_Translation::ngettext("%d minute ago", "%d minutes ago", $delta), $delta);
+ }
+
+ $delta = round($delta / 60);
+ if ($delta < 24) {
+ return sprintf(Horde_Date_Translation::ngettext("%d hour ago", "%d hours ago", $delta), $delta);
+ }
+
+ if ($delta > 24 && $delta < 48) {
+ $date = new Horde_Date($time);
+ return sprintf(Horde_Date_Translation::t("yesterday at %s"), $date->strftime($time_format));
+ }
+
+ $delta = round($delta / 24);
+ if ($delta < 7) {
+ return sprintf(Horde_Date_Translation::t("%d days ago"), $delta);
+ }
+
+ if (round($delta / 7) < 5) {
+ $delta = round($delta / 7);
+ return sprintf(Horde_Date_Translation::ngettext("%d week ago", "%d weeks ago", $delta), $delta);
+ }
+
+ // Default to the user specified date format.
+ return $date->strftime($date_format);
+ }
+
+ /**
+ * Tries to convert strftime() formatters to date() formatters.
+ *
+ * Unsupported formatters will be removed.
+ *
+ * @param string $format A strftime() formatting string.
+ *
+ * @return string A date() formatting string.
+ */
+ public static function strftime2date($format)
+ {
+ $replace = array(
+ '/%a/' => 'D',
+ '/%A/' => 'l',
+ '/%d/' => 'd',
+ '/%e/' => 'j',
+ '/%j/' => 'z',
+ '/%u/' => 'N',
+ '/%w/' => 'w',
+ '/%U/' => '',
+ '/%V/' => 'W',
+ '/%W/' => '',
+ '/%b/' => 'M',
+ '/%B/' => 'F',
+ '/%h/' => 'M',
+ '/%m/' => 'm',
+ '/%C/' => '',
+ '/%g/' => '',
+ '/%G/' => 'o',
+ '/%y/' => 'y',
+ '/%Y/' => 'Y',
+ '/%H/' => 'H',
+ '/%I/' => 'h',
+ '/%i/' => 'g',
+ '/%M/' => 'i',
+ '/%p/' => 'A',
+ '/%P/' => 'a',
+ '/%r/' => 'h:i:s A',
+ '/%R/' => 'H:i',
+ '/%S/' => 's',
+ '/%T/' => 'H:i:s',
+ '/%X/e' => 'Horde_Date_Utils::strftime2date(Horde_Nls::getLangInfo(T_FMT))',
+ '/%z/' => 'O',
+ '/%Z/' => '',
+ '/%c/' => '',
+ '/%D/' => 'm/d/y',
+ '/%F/' => 'Y-m-d',
+ '/%s/' => 'U',
+ '/%x/e' => 'Horde_Date_Utils::strftime2date(Horde_Nls::getLangInfo(D_FMT))',
+ '/%n/' => "\n",
+ '/%t/' => "\t",
+ '/%%/' => '%'
+ );
+
+ return preg_replace(array_keys($replace), array_values($replace), $format);
+ }
+
+}
diff --git a/plugins/libkolab/lib/Horde_Date_Recurrence.php b/plugins/libkolab/lib/Horde_Date_Recurrence.php
index 2171a47..bbdf13d 100644
--- a/plugins/libkolab/lib/Horde_Date_Recurrence.php
+++ b/plugins/libkolab/lib/Horde_Date_Recurrence.php
@@ -1,9 +1,8 @@
<?php
/**
- * This is a concatenated copy of the following files:
- * Horde/Date.php, Horde/Date/Utils.php, Horde/Date/Recurrence.php
- * Pull the latest version of these files from the PEAR channel of the Horde
+ * This is a modified copy of Horde/Date/Recurrence.php
+ * Pull the latest version of this file from the PEAR channel of the Horde
* project at http://pear.horde.org by installing the Horde_Date package.
*/
@@ -19,182 +18,6 @@ class Horde_Date_Translation
/**
- * @category Horde
- * @package Date
- */
-
-/**
- * Horde Date wrapper/logic class, including some calculation
- * functions.
- *
- * @category Horde
- * @package Date
- */
-class Horde_Date_Utils
-{
- /**
- * Returns whether a year is a leap year.
- *
- * @param integer $year The year.
- *
- * @return boolean True if the year is a leap year.
- */
- public static function isLeapYear($year)
- {
- if (strlen($year) != 4 || preg_match('/\D/', $year)) {
- return false;
- }
-
- return (($year % 4 == 0 && $year % 100 != 0) || $year % 400 == 0);
- }
-
- /**
- * Returns the date of the year that corresponds to the first day of the
- * given week.
- *
- * @param integer $week The week of the year to find the first day of.
- * @param integer $year The year to calculate for.
- *
- * @return Horde_Date The date of the first day of the given week.
- */
- public static function firstDayOfWeek($week, $year)
- {
- return new Horde_Date(sprintf('%04dW%02d', $year, $week));
- }
-
- /**
- * Returns the number of days in the specified month.
- *
- * @param integer $month The month
- * @param integer $year The year.
- *
- * @return integer The number of days in the month.
- */
- public static function daysInMonth($month, $year)
- {
- static $cache = array();
- if (!isset($cache[$year][$month])) {
- $date = new DateTime(sprintf('%04d-%02d-01', $year, $month));
- $cache[$year][$month] = $date->format('t');
- }
- return $cache[$year][$month];
- }
-
- /**
- * Returns a relative, natural language representation of a timestamp
- *
- * @todo Wider range of values ... maybe future time as well?
- * @todo Support minimum resolution parameter.
- *
- * @param mixed $time The time. Any format accepted by Horde_Date.
- * @param string $date_format Format to display date if timestamp is
- * more then 1 day old.
- * @param string $time_format Format to display time if timestamp is 1
- * day old.
- *
- * @return string The relative time (i.e. 2 minutes ago)
- */
- public static function relativeDateTime($time, $date_format = '%x',
- $time_format = '%X')
- {
- $date = new Horde_Date($time);
-
- $delta = time() - $date->timestamp();
- if ($delta < 60) {
- return sprintf(Horde_Date_Translation::ngettext("%d second ago", "%d seconds ago", $delta), $delta);
- }
-
- $delta = round($delta / 60);
- if ($delta < 60) {
- return sprintf(Horde_Date_Translation::ngettext("%d minute ago", "%d minutes ago", $delta), $delta);
- }
-
- $delta = round($delta / 60);
- if ($delta < 24) {
- return sprintf(Horde_Date_Translation::ngettext("%d hour ago", "%d hours ago", $delta), $delta);
- }
-
- if ($delta > 24 && $delta < 48) {
- $date = new Horde_Date($time);
- return sprintf(Horde_Date_Translation::t("yesterday at %s"), $date->strftime($time_format));
- }
-
- $delta = round($delta / 24);
- if ($delta < 7) {
- return sprintf(Horde_Date_Translation::t("%d days ago"), $delta);
- }
-
- if (round($delta / 7) < 5) {
- $delta = round($delta / 7);
- return sprintf(Horde_Date_Translation::ngettext("%d week ago", "%d weeks ago", $delta), $delta);
- }
-
- // Default to the user specified date format.
- return $date->strftime($date_format);
- }
-
- /**
- * Tries to convert strftime() formatters to date() formatters.
- *
- * Unsupported formatters will be removed.
- *
- * @param string $format A strftime() formatting string.
- *
- * @return string A date() formatting string.
- */
- public static function strftime2date($format)
- {
- $replace = array(
- '/%a/' => 'D',
- '/%A/' => 'l',
- '/%d/' => 'd',
- '/%e/' => 'j',
- '/%j/' => 'z',
- '/%u/' => 'N',
- '/%w/' => 'w',
- '/%U/' => '',
- '/%V/' => 'W',
- '/%W/' => '',
- '/%b/' => 'M',
- '/%B/' => 'F',
- '/%h/' => 'M',
- '/%m/' => 'm',
- '/%C/' => '',
- '/%g/' => '',
- '/%G/' => 'o',
- '/%y/' => 'y',
- '/%Y/' => 'Y',
- '/%H/' => 'H',
- '/%I/' => 'h',
- '/%i/' => 'g',
- '/%M/' => 'i',
- '/%p/' => 'A',
- '/%P/' => 'a',
- '/%r/' => 'h:i:s A',
- '/%R/' => 'H:i',
- '/%S/' => 's',
- '/%T/' => 'H:i:s',
- '/%X/e' => 'Horde_Date_Utils::strftime2date(Horde_Nls::getLangInfo(T_FMT))',
- '/%z/' => 'O',
- '/%Z/' => '',
- '/%c/' => '',
- '/%D/' => 'm/d/y',
- '/%F/' => 'Y-m-d',
- '/%s/' => 'U',
- '/%x/e' => 'Horde_Date_Utils::strftime2date(Horde_Nls::getLangInfo(D_FMT))',
- '/%n/' => "\n",
- '/%t/' => "\t",
- '/%%/' => '%'
- );
-
- return preg_replace(array_keys($replace), array_values($replace), $format);
- }
-
-}
-
-
-
-/**
* This file contains the Horde_Date_Recurrence class and according constants.
*
* Copyright 2007-2012 Horde LLC (http://www.horde.org/)
@@ -290,6 +113,20 @@ class Horde_Date_Recurrence
public $recurData = null;
/**
+ * BYDAY recurrence number
+ *
+ * @var integer
+ */
+ public $recurNthDay = null;
+
+ /**
+ * BYMONTH recurrence data
+ *
+ * @var array
+ */
+ public $recurMonths = array();
+
+ /**
* All the exceptions from recurrence for this event.
*
* @var array
@@ -352,6 +189,44 @@ class Horde_Date_Recurrence
}
/**
+ *
+ * @param integer $nthDay The nth weekday of month to repeat events on
+ */
+ public function setRecurNthWeekday($nth)
+ {
+ $this->recurNthDay = (int)$nth;
+ }
+
+ /**
+ *
+ * @return integer The nth weekday of month to repeat events.
+ */
+ public function getRecurNthWeekday()
+ {
+ return isset($this->recurNthDay) ? $this->recurNthDay : ceil($this->start->mday / 7);
+ }
+
+ /**
+ * Specifies the months for yearly (weekday) recurrence
+ *
+ * @param array $months List of months (integers) this event recurs on.
+ */
+ function setRecurByMonth($months)
+ {
+ $this->recurMonths = (array)$months;
+ }
+
+ /**
+ * Returns a list of months this yearly event recurs on
+ *
+ * @return array List of months (integers) this event recurs on.
+ */
+ function getRecurByMonth()
+ {
+ return $this->recurMonths;
+ }
+
+ /**
* Returns the days this event recurs on.
*
* @return integer A mask consisting of Horde_Date::MASK_* constants
@@ -741,8 +616,13 @@ class Horde_Date_Recurrence
$estart = clone $this->start;
// What day of the week, and week of the month, do we recur on?
- $nth = ceil($this->start->mday / 7);
- $weekday = $estart->dayOfWeek();
+ if (isset($this->recurNthDay)) {
+ $nth = $this->recurNthDay;
+ $weekday = log($this->recurData, 2);
+ } else {
+ $nth = ceil($this->start->mday / 7);
+ $weekday = $estart->dayOfWeek();
+ }
// Adjust $estart to be the first candidate.
$offset = ($after->month - $estart->month) + ($after->year - $estart->year) * 12;
@@ -855,8 +735,13 @@ class Horde_Date_Recurrence
$estart = clone $this->start;
// What day of the week, and week of the month, do we recur on?
- $nth = ceil($this->start->mday / 7);
- $weekday = $estart->dayOfWeek();
+ if (isset($this->recurNthDay)) {
+ $nth = $this->recurNthDay;
+ $weekday = log($this->recurData, 2);
+ } else {
+ $nth = ceil($this->start->mday / 7);
+ $weekday = $estart->dayOfWeek();
+ }
// Adjust $estart to be the first candidate.
$offset = floor(($after->year - $estart->year + $this->recurInterval - 1) / $this->recurInterval) * $this->recurInterval;
@@ -1089,15 +974,6 @@ class Horde_Date_Recurrence
case 'W':
$this->setRecurType(self::RECUR_WEEKLY);
if (!empty($remainder)) {
- $maskdays = array(
- 'SU' => Horde_Date::MASK_SUNDAY,
- 'MO' => Horde_Date::MASK_MONDAY,
- 'TU' => Horde_Date::MASK_TUESDAY,
- 'WE' => Horde_Date::MASK_WEDNESDAY,
- 'TH' => Horde_Date::MASK_THURSDAY,
- 'FR' => Horde_Date::MASK_FRIDAY,
- 'SA' => Horde_Date::MASK_SATURDAY,
- );
$mask = 0;
while (preg_match('/^ ?[A-Z]{2} ?/', $remainder, $matches)) {
$day = trim($matches[0]);
@@ -1148,7 +1024,10 @@ class Horde_Date_Recurrence
list($year, $month, $mday) = sscanf($remainder, '%04d%02d%02d');
$this->setRecurEnd(new Horde_Date(array('year' => $year,
'month' => $month,
- 'mday' => $mday)));
+ 'mday' => $mday,
+ 'hour' => 23,
+ 'min' => 59,
+ 'sec' => 59)));
}
}
}
@@ -1244,6 +1123,16 @@ class Horde_Date_Recurrence
// Always default the recurInterval to 1.
$this->setRecurInterval(isset($rdata['INTERVAL']) ? $rdata['INTERVAL'] : 1);
+ $maskdays = array(
+ 'SU' => Horde_Date::MASK_SUNDAY,
+ 'MO' => Horde_Date::MASK_MONDAY,
+ 'TU' => Horde_Date::MASK_TUESDAY,
+ 'WE' => Horde_Date::MASK_WEDNESDAY,
+ 'TH' => Horde_Date::MASK_THURSDAY,
+ 'FR' => Horde_Date::MASK_FRIDAY,
+ 'SA' => Horde_Date::MASK_SATURDAY,
+ );
+
switch (strtoupper($rdata['FREQ'])) {
case 'DAILY':
$this->setRecurType(self::RECUR_DAILY);
@@ -1252,15 +1141,6 @@ class Horde_Date_Recurrence
case 'WEEKLY':
$this->setRecurType(self::RECUR_WEEKLY);
if (isset($rdata['BYDAY'])) {
- $maskdays = array(
- 'SU' => Horde_Date::MASK_SUNDAY,
- 'MO' => Horde_Date::MASK_MONDAY,
- 'TU' => Horde_Date::MASK_TUESDAY,
- 'WE' => Horde_Date::MASK_WEDNESDAY,
- 'TH' => Horde_Date::MASK_THURSDAY,
- 'FR' => Horde_Date::MASK_FRIDAY,
- 'SA' => Horde_Date::MASK_SATURDAY,
- );
$days = explode(',', $rdata['BYDAY']);
$mask = 0;
foreach ($days as $day) {
@@ -1285,6 +1165,10 @@ class Horde_Date_Recurrence
case 'MONTHLY':
if (isset($rdata['BYDAY'])) {
$this->setRecurType(self::RECUR_MONTHLY_WEEKDAY);
+ if (preg_match('/(-?[1-4])([A-Z]+)/', $rdata['BYDAY'], $m)) {
+ $this->setRecurOnDay($maskdays[$m[2]]);
+ $this->setRecurNthWeekday($m[1]);
+ }
} else {
$this->setRecurType(self::RECUR_MONTHLY_DATE);
}
@@ -1295,6 +1179,14 @@ class Horde_Date_Recurrence
$this->setRecurType(self::RECUR_YEARLY_DAY);
} elseif (isset($rdata['BYDAY'])) {
$this->setRecurType(self::RECUR_YEARLY_WEEKDAY);
+ if (preg_match('/(-?[1-4])([A-Z]+)/', $rdata['BYDAY'], $m)) {
+ $this->setRecurOnDay($maskdays[$m[2]]);
+ $this->setRecurNthWeekday($m[1]);
+ }
+ if ($rdata['BYMONTH']) {
+ $months = explode(',', $rdata['BYMONTH']);
+ $this->setRecurByMonth($months);
+ }
} else {
$this->setRecurType(self::RECUR_YEARLY_DATE);
}
@@ -1358,13 +1250,19 @@ class Horde_Date_Recurrence
break;
case self::RECUR_MONTHLY_WEEKDAY:
- $nth_weekday = (int)($this->start->mday / 7);
- if (($this->start->mday % 7) > 0) {
- $nth_weekday++;
+ if (isset($this->recurNthDay)) {
+ $nth_weekday = $this->recurNthDay;
+ $day_of_week = log($this->recurData, 2);
+ } else {
+ $day_of_week = $this->start->dayOfWeek();
+ $nth_weekday = (int)($this->start->mday / 7);
+ if (($this->start->mday % 7) > 0) {
+ $nth_weekday++;
+ }
}
$vcaldays = array('SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA');
$rrule = 'FREQ=MONTHLY;INTERVAL=' . $this->recurInterval
- . ';BYDAY=' . $nth_weekday . $vcaldays[$this->start->dayOfWeek()];
+ . ';BYDAY=' . $nth_weekday . $vcaldays[$day_of_week];
break;
case self::RECUR_YEARLY_DATE:
@@ -1377,15 +1275,22 @@ class Horde_Date_Recurrence
break;
case self::RECUR_YEARLY_WEEKDAY:
- $nth_weekday = (int)($this->start->mday / 7);
- if (($this->start->mday % 7) > 0) {
- $nth_weekday++;
- }
+ if (isset($this->recurNthDay)) {
+ $nth_weekday = $this->recurNthDay;
+ $day_of_week = log($this->recurData, 2);
+ } else {
+ $day_of_week = $this->start->dayOfWeek();
+ $nth_weekday = (int)($this->start->mday / 7);
+ if (($this->start->mday % 7) > 0) {
+ $nth_weekday++;
+ }
+ }
+ $months = !empty($this->recurMonths) ? join(',', $this->recurMonths) : $this->start->month;
$vcaldays = array('SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA');
$rrule = 'FREQ=YEARLY;INTERVAL=' . $this->recurInterval
. ';BYDAY='
. $nth_weekday
- . $vcaldays[$this->start->dayOfWeek()]
+ . $vcaldays[$day_of_week]
. ';BYMONTH=' . $this->start->month;
break;
}
@@ -1418,6 +1323,21 @@ class Horde_Date_Recurrence
$this->setRecurInterval((int)$hash['interval']);
+ $month2number = array(
+ 'january' => 1,
+ 'february' => 2,
+ 'march' => 3,
+ 'april' => 4,
+ 'may' => 5,
+ 'june' => 6,
+ 'july' => 7,
+ 'august' => 8,
+ 'september' => 9,
+ 'october' => 10,
+ 'november' => 11,
+ 'december' => 12,
+ );
+
$parse_day = false;
$set_daymask = false;
$update_month = false;
@@ -1450,11 +1370,9 @@ class Horde_Date_Recurrence
case 'weekday':
$this->setRecurType(self::RECUR_MONTHLY_WEEKDAY);
- $nth_weekday = (int)$hash['daynumber'];
- $hash['daynumber'] = 1;
+ $this->setRecurNthWeekday($hash['daynumber']);
$parse_day = true;
- $update_daynumber = true;
- $update_weekday = true;
+ $set_daymask = true;
break;
}
break;
@@ -1492,12 +1410,13 @@ class Horde_Date_Recurrence
}
$this->setRecurType(self::RECUR_YEARLY_WEEKDAY);
- $nth_weekday = (int)$hash['daynumber'];
- $hash['daynumber'] = 1;
+ $this->setRecurNthWeekday($hash['daynumber']);
$parse_day = true;
- $update_month = true;
- $update_daynumber = true;
- $update_weekday = true;
+ $set_daymask = true;
+
+ if ($hash['month'] && isset($month2number[$hash['month']])) {
+ $this->setRecurByMonth($month2number[$hash['month']]);
+ }
break;
}
}
@@ -1563,21 +1482,6 @@ class Horde_Date_Recurrence
if ($update_month || $update_daynumber || $update_weekday) {
if ($update_month) {
- $month2number = array(
- 'january' => 1,
- 'february' => 2,
- 'march' => 3,
- 'april' => 4,
- 'may' => 5,
- 'june' => 6,
- 'july' => 7,
- 'august' => 8,
- 'september' => 9,
- 'october' => 10,
- 'november' => 11,
- 'december' => 12,
- );
-
if (isset($month2number[$hash['month']])) {
$this->start->month = $month2number[$hash['month']];
}
@@ -1593,7 +1497,7 @@ class Horde_Date_Recurrence
}
if ($update_weekday) {
- $this->start->setNthWeekday($last_found_day, $nth_weekday);
+ $this->setNthWeekday($nth_weekday);
}
}
@@ -1764,5 +1668,3 @@ class Horde_Date_Recurrence
}
}
-
-
commit c5f9fd15b43e5f3816e30160ce2eb0b2dbeeb3e4
Author: Thomas Bruederli <thomas at roundcube.net>
Date: Wed Jul 11 09:16:01 2012 +0200
Change tasklist main screen layout according to recent changes in Larry skin
diff --git a/plugins/tasklist/localization/de_CH.inc b/plugins/tasklist/localization/de_CH.inc
index b62f6d0..5d57e93 100644
--- a/plugins/tasklist/localization/de_CH.inc
+++ b/plugins/tasklist/localization/de_CH.inc
@@ -6,7 +6,7 @@ $labels['lists'] = 'Ressourcen';
$labels['list'] = 'Ressource';
$labels['tags'] = 'Tags';
-$labels['createnewtask'] = 'Neue Aufgabe eingeben';
+$labels['createnewtask'] = 'Neue Aufgabe eingeben (z.B. Samstag, Rasenmähen)';
$labels['mark'] = 'Markieren';
$labels['unmark'] = 'Markierung aufheben';
$labels['edit'] = 'Bearbeiten';
diff --git a/plugins/tasklist/localization/en_US.inc b/plugins/tasklist/localization/en_US.inc
index b146039..b73dda9 100644
--- a/plugins/tasklist/localization/en_US.inc
+++ b/plugins/tasklist/localization/en_US.inc
@@ -6,7 +6,7 @@ $labels['lists'] = 'Resources';
$labels['list'] = 'Resource';
$labels['tags'] = 'Tags';
-$labels['createnewtask'] = 'Create new Task';
+$labels['createnewtask'] = 'Create new Task (e.g. Saturday, Mow the lawn)';
$labels['mark'] = 'Mark';
$labels['unmark'] = 'Unmark';
$labels['edit'] = 'Edit';
diff --git a/plugins/tasklist/skins/larry/tasklist.css b/plugins/tasklist/skins/larry/tasklist.css
index e6136f5..063632d 100644
--- a/plugins/tasklist/skins/larry/tasklist.css
+++ b/plugins/tasklist/skins/larry/tasklist.css
@@ -208,11 +208,14 @@ body.tasklistview #searchmenulink {
#taskstoolbar {
position: absolute;
top: -6px;
- right: 0;
- width: 40%;
+ left: 0;
+ width: 100%;
height: 40px;
white-space: nowrap;
- text-align: right;
+}
+
+#quicksearchbar {
+ top: -7px;
}
#quickaddbox {
@@ -227,7 +230,8 @@ body.tasklistview #searchmenulink {
#quickaddinput {
width: 85%;
margin: 0;
- padding: 5px 8px;
+ padding: 3px 8px;
+ height: 18px;
background: #f1f1f1;
background: rgba(255, 255, 255, 0.7);
border-color: #a3a3a3;
diff --git a/plugins/tasklist/skins/larry/templates/mainview.html b/plugins/tasklist/skins/larry/templates/mainview.html
index 0ec9cab..927ee4b 100644
--- a/plugins/tasklist/skins/larry/templates/mainview.html
+++ b/plugins/tasklist/skins/larry/templates/mainview.html
@@ -10,12 +10,10 @@
<div id="mainscreen">
<div id="sidebar">
- <div id="quicksearchbar">
- <roundcube:object name="plugin.searchform" id="quicksearchbox" />
- <a id="searchmenulink" class="iconbutton searchoptions" > </a>
- <roundcube:button command="reset-search" id="searchreset" class="iconbutton reset" title="resetsearch" content=" " />
+ <div id="taskstoolbar" class="toolbar">
+ <roundcube:container name="toolbar" id="taskstoolbar" />
</div>
-
+
<div id="selectorbox" class="uibox listbox">
<div class="scroller">
<h2 class="boxtitle"><roundcube:label name="tasklist.tags" /></h2>
@@ -39,8 +37,10 @@
<roundcube:object name="plugin.quickaddform" />
</div>
- <div id="taskstoolbar" class="toolbar">
- <roundcube:container name="toolbar" id="taskstoolbar" />
+ <div id="quicksearchbar">
+ <roundcube:object name="plugin.searchform" id="quicksearchbox" />
+ <a id="searchmenulink" class="iconbutton searchoptions" > </a>
+ <roundcube:button command="reset-search" id="searchreset" class="iconbutton reset" title="resetsearch" content=" " />
</div>
<div id="tasksview" class="uibox">
More information about the commits
mailing list