Move ICal module to include folder, export config to separate config file
This commit is contained in:
parent
e1fe24e6af
commit
3fcbd8e16f
5 changed files with 121 additions and 103 deletions
15
ICal/LICENSE
15
ICal/LICENSE
|
|
@ -1,15 +0,0 @@
|
|||
The MIT License (MIT)
|
||||
Copyright (c) 2018
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -92,16 +92,18 @@ class ICal
|
|||
public $disableCharacterReplacement = false;
|
||||
|
||||
/**
|
||||
* With this being non-null the parser will ignore all events more than roughly this many days after now.
|
||||
* If this value is an integer, the parser will ignore all events more than roughly this many days before now.
|
||||
* If this value is a date, the parser will ignore all events occurring before this date.
|
||||
*
|
||||
* @var integer|null
|
||||
* @var \DateTimeInterface|integer|null
|
||||
*/
|
||||
public $filterDaysBefore;
|
||||
|
||||
/**
|
||||
* With this being non-null the parser will ignore all events more than roughly this many days before now.
|
||||
* If this value is an integer, the parser will ignore all events more than roughly this many days after now.
|
||||
* If this value is a date, the parser will ignore all events occurring after this date.
|
||||
*
|
||||
* @var integer|null
|
||||
* @var \DateTimeInterface|integer|null
|
||||
*/
|
||||
public $filterDaysAfter;
|
||||
|
||||
|
|
@ -523,8 +525,33 @@ class ICal
|
|||
// Ideally you would use `PHP_INT_MIN` from PHP 7
|
||||
$php_int_min = -2147483648;
|
||||
|
||||
$this->windowMinTimestamp = is_null($this->filterDaysBefore) ? $php_int_min : (new \DateTime('now'))->sub(new \DateInterval('P' . $this->filterDaysBefore . 'D'))->getTimestamp();
|
||||
$this->windowMaxTimestamp = is_null($this->filterDaysAfter) ? PHP_INT_MAX : (new \DateTime('now'))->add(new \DateInterval('P' . $this->filterDaysAfter . 'D'))->getTimestamp();
|
||||
$this->windowMinTimestamp = $php_int_min;
|
||||
|
||||
if (!is_null($this->filterDaysBefore)) {
|
||||
if (is_int($this->filterDaysBefore)) {
|
||||
$this->windowMinTimestamp = (new \DateTime('now'))
|
||||
->sub(new \DateInterval('P' . $this->filterDaysBefore . 'D'))
|
||||
->getTimestamp();
|
||||
}
|
||||
|
||||
if ($this->filterDaysBefore instanceof \DateTimeInterface) {
|
||||
$this->windowMinTimestamp = $this->filterDaysBefore->getTimestamp();
|
||||
}
|
||||
}
|
||||
|
||||
$this->windowMaxTimestamp = PHP_INT_MAX;
|
||||
|
||||
if (!is_null($this->filterDaysAfter)) {
|
||||
if (is_int($this->filterDaysAfter)) {
|
||||
$this->windowMaxTimestamp = (new \DateTime('now'))
|
||||
->add(new \DateInterval('P' . $this->filterDaysAfter . 'D'))
|
||||
->getTimestamp();
|
||||
}
|
||||
|
||||
if ($this->filterDaysAfter instanceof \DateTimeInterface) {
|
||||
$this->windowMaxTimestamp = $this->filterDaysAfter->getTimestamp();
|
||||
}
|
||||
}
|
||||
|
||||
$this->shouldFilterByWindow = !is_null($this->filterDaysBefore) || !is_null($this->filterDaysAfter);
|
||||
|
||||
|
|
@ -532,7 +559,7 @@ class ICal
|
|||
$files = is_array($files) ? $files : array($files);
|
||||
|
||||
foreach ($files as $file) {
|
||||
if (!is_array($file) && $this->isFileOrUrl($file)) {
|
||||
if (is_string($file) && $this->isFileOrUrl($file)) {
|
||||
$lines = $this->fileOrUrl($file);
|
||||
} else {
|
||||
$lines = is_array($file) ? $file : array($file);
|
||||
|
|
@ -1144,9 +1171,9 @@ class ICal
|
|||
*/
|
||||
$pattern = '/^(?:TZID=)?([^:]*|".*")'; // [1]: Time zone
|
||||
$pattern .= ':?'; // Time zone delimiter
|
||||
$pattern .= '([0-9]{8})'; // [2]: YYYYMMDD
|
||||
$pattern .= '(\d{8})'; // [2]: YYYYMMDD
|
||||
$pattern .= 'T?'; // Time delimiter
|
||||
$pattern .= '(?(?<=T)([0-9]{6}))'; // [3]: HHMMSS (filled if delimiter present)
|
||||
$pattern .= '(?(?<=T)(\d{6}))'; // [3]: HHMMSS (filled if delimiter present)
|
||||
$pattern .= '(Z?)/'; // [4]: UTC flag
|
||||
|
||||
preg_match($pattern, $icalDate, $date);
|
||||
|
|
@ -1353,7 +1380,7 @@ class ICal
|
|||
foreach (array_filter(explode(';', $anEvent['RRULE'])) as $s) {
|
||||
list($k, $v) = explode('=', $s);
|
||||
if (in_array($k, array('BYSETPOS', 'BYDAY', 'BYMONTHDAY', 'BYMONTH', 'BYYEARDAY', 'BYWEEKNO'))) {
|
||||
$rrules[$k] = explode(',', $v);
|
||||
$rrules[$k] = $v === '' ? array() : explode(',', $v);
|
||||
} else {
|
||||
$rrules[$k] = $v;
|
||||
}
|
||||
|
|
@ -1395,7 +1422,7 @@ class ICal
|
|||
$interval = (empty($rrules['INTERVAL'])) ? 1 : (int) $rrules['INTERVAL'];
|
||||
|
||||
// Throw an error if this isn't an integer.
|
||||
if (!is_int($this->defaultSpan)) {
|
||||
if (!is_int($this->defaultSpan)) { // @phpstan-ignore function.alreadyNarrowedType
|
||||
trigger_error('ICal::defaultSpan: User defined value is not an integer', E_USER_NOTICE);
|
||||
}
|
||||
|
||||
|
|
@ -1567,7 +1594,7 @@ class ICal
|
|||
$clonedDateTime = clone $frequencyRecurringDateTime;
|
||||
$candidateDateTimes[] = $clonedDateTime->setDate(
|
||||
(int) $frequencyRecurringDateTime->format('Y'),
|
||||
(int) $frequencyRecurringDateTime->format('m'),
|
||||
(int) $frequencyRecurringDateTime->format('n'),
|
||||
$day
|
||||
);
|
||||
}
|
||||
|
|
@ -1600,7 +1627,7 @@ class ICal
|
|||
foreach ($monthDays as $day) {
|
||||
$matchingDays[] = $bymonthRecurringDatetime->setDate(
|
||||
(int) $frequencyRecurringDateTime->format('Y'),
|
||||
(int) $bymonthRecurringDatetime->format('m'),
|
||||
(int) $bymonthRecurringDatetime->format('n'),
|
||||
$day
|
||||
)->format('z') + 1;
|
||||
}
|
||||
|
|
@ -1682,7 +1709,7 @@ class ICal
|
|||
}
|
||||
|
||||
// Move forwards $interval $frequency.
|
||||
$monthPreMove = $frequencyRecurringDateTime->format('m');
|
||||
$monthPreMove = (int) $frequencyRecurringDateTime->format('n');
|
||||
$frequencyRecurringDateTime->modify("{$interval} {$this->frequencyConversion[$frequency]}");
|
||||
|
||||
// As noted in Example #2 on https://www.php.net/manual/en/datetime.modify.php,
|
||||
|
|
@ -1690,7 +1717,7 @@ class ICal
|
|||
// expect. For instance: January 31st + 1 month == March 3rd (March 2nd on a leap
|
||||
// year.) The following code crudely rectifies this.
|
||||
if ($frequency === 'MONTHLY') {
|
||||
$monthDiff = $frequencyRecurringDateTime->format('m') - $monthPreMove;
|
||||
$monthDiff = (int) $frequencyRecurringDateTime->format('n') - $monthPreMove;
|
||||
|
||||
if (($monthDiff > 0 && $monthDiff > $interval) || ($monthDiff < 0 && $monthDiff > $interval - 12)) {
|
||||
$frequencyRecurringDateTime->modify('-1 month');
|
||||
|
|
@ -1700,7 +1727,7 @@ class ICal
|
|||
// $monthDays is set in the DAILY frequency if the BYMONTHDAY stanza is present in
|
||||
// the RRULE. The variable only needs to be updated when we change months, so we
|
||||
// unset it here, prompting a recreation next iteration.
|
||||
if (isset($monthDays) && $frequencyRecurringDateTime->format('m') !== $monthPreMove) {
|
||||
if (isset($monthDays) && (int) $frequencyRecurringDateTime->format('n') !== $monthPreMove) {
|
||||
unset($monthDays);
|
||||
}
|
||||
}
|
||||
|
|
@ -2050,7 +2077,7 @@ class ICal
|
|||
foreach ($monthDays as $day) {
|
||||
$matchingDays[] = $monthDateTime->setDate(
|
||||
(int) $initialDateTime->format('Y'),
|
||||
(int) $monthDateTime->format('m'),
|
||||
(int) $monthDateTime->format('n'),
|
||||
$day
|
||||
)->format('z') + 1;
|
||||
}
|
||||
|
|
@ -2390,9 +2417,11 @@ class ICal
|
|||
|
||||
foreach ($tza as $zone) {
|
||||
foreach ($zone as $item) {
|
||||
if ($item['timezone_id'] !== null) {
|
||||
$valid[$item['timezone_id']] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unset($valid['']);
|
||||
|
||||
|
|
@ -2460,7 +2489,7 @@ class ICal
|
|||
*/
|
||||
protected function removeUnprintableChars($data)
|
||||
{
|
||||
return preg_replace('/[\x00-\x1F\x7F\xA0]/u', '', $data);
|
||||
return preg_replace('/[\x00-\x1F\x7F]/u', '', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2474,7 +2503,8 @@ class ICal
|
|||
{
|
||||
if (function_exists('mb_chr')) {
|
||||
return mb_chr($code);
|
||||
} else {
|
||||
}
|
||||
|
||||
if (($code %= 0x200000) < 0x80) {
|
||||
$s = chr($code);
|
||||
} elseif ($code < 0x800) {
|
||||
|
|
@ -2487,7 +2517,6 @@ class ICal
|
|||
|
||||
return $s;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Places double-quotes around texts that have characters not permitted
|
||||
|
|
@ -2550,10 +2579,10 @@ class ICal
|
|||
{
|
||||
if (empty($event['EXDATE_array'])) {
|
||||
return array();
|
||||
} else {
|
||||
$exdates = $event['EXDATE_array'];
|
||||
}
|
||||
|
||||
$exdates = $event['EXDATE_array'];
|
||||
|
||||
$output = array();
|
||||
$currentTimeZone = new \DateTimeZone($this->getDefaultTimeZone());
|
||||
|
||||
|
|
@ -2589,7 +2618,6 @@ class ICal
|
|||
*
|
||||
* @param string $value
|
||||
* @return boolean
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function isValidDate($value)
|
||||
{
|
||||
|
|
@ -2630,7 +2658,7 @@ class ICal
|
|||
$options['http'] = array();
|
||||
$options['http']['header'] = array();
|
||||
|
||||
if ($this->httpBasicAuth === array() || !empty($this->httpUserAgent) || !empty($this->httpAcceptLanguage)) {
|
||||
if ($this->httpBasicAuth !== array() || !empty($this->httpUserAgent) || !empty($this->httpAcceptLanguage)) {
|
||||
if ($this->httpBasicAuth !== array()) {
|
||||
$username = $this->httpBasicAuth['username'];
|
||||
$password = $this->httpBasicAuth['password'];
|
||||
11
include/config.sample.php
Normal file
11
include/config.sample.php
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
#ini_set('display_errors', 1);
|
||||
#ini_set('display_startup_errors', 1);
|
||||
#error_reporting(E_ALL);
|
||||
|
||||
$ical_url = '...';
|
||||
$ical_name = 'My Calendar File';
|
||||
|
||||
$cachefile = 'calendar.ics';
|
||||
$cachetime = 120; // 2 min
|
||||
78
index.php
78
index.php
|
|
@ -1,72 +1,66 @@
|
|||
<?php
|
||||
|
||||
#ini_set('display_errors', 1);
|
||||
#ini_set('display_startup_errors', 1);
|
||||
#error_reporting(E_ALL);
|
||||
|
||||
|
||||
# config
|
||||
$ical = 'https://cloud.hacknang.de/remote.php/dav/public-calendars/nZTMSHpd29ZRpAr6/?export';
|
||||
$cachefile = 'cache/hacknang.ics';
|
||||
$cachetime = 120; // 2 min
|
||||
|
||||
# requirements
|
||||
require_once 'ICal/ICal.php';
|
||||
require_once 'ICal/Event.php';
|
||||
require_once 'include/config.php';
|
||||
require_once 'include/ICal/ICal.php';
|
||||
require_once 'include/ICal/Event.php';
|
||||
|
||||
# Fix relative path
|
||||
$cachefile = 'cache/'.$cachefile;
|
||||
|
||||
# Init Calendar
|
||||
$iCal = new \ICal\ICal();
|
||||
$ical = new \ICal\ICal();
|
||||
|
||||
# Caching and load calendar
|
||||
if(@filemtime($cachefile) + $cachetime < time()) {
|
||||
$ical_str = file_get_contents($ical);
|
||||
if (!file_exists($cachefile) || (filemtime($cachefile) + $cachetime < time())) {
|
||||
$context = stream_context_create(['http' => ['timeout' => 10]]);
|
||||
$ical_str = @file_get_contents($ical_url, false, $context);
|
||||
|
||||
if ($ical_str !== false && strpos($ical_str, 'BEGIN:VCALENDAR') !== false) {
|
||||
file_put_contents($cachefile, $ical_str);
|
||||
$iCal->initString($ical_str);
|
||||
$ical->initString($ical_str);
|
||||
} else {
|
||||
$iCal->initFile($cachefile);
|
||||
if (file_exists($cachefile)) $ical->initFile($cachefile);
|
||||
}
|
||||
} else {
|
||||
$ical->initFile($cachefile);
|
||||
}
|
||||
//$iCal->initURL($ical);
|
||||
|
||||
# Load calendar entries
|
||||
$months = max(filter_input(INPUT_GET, 'period', FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 12))), 1);
|
||||
$events = $iCal->sortEventsWithOrder($iCal->eventsFromInterval($months.' month'));
|
||||
|
||||
$filter = filter_input(INPUT_GET, 'filter', FILTER_SANITIZE_SPECIAL_CHARS);
|
||||
$period_val = filter_input(INPUT_GET, 'period', FILTER_VALIDATE_INT, ['options' => ['min_range' => 1, 'max_range' => 12]]) ?: 1;
|
||||
$filter = filter_input(INPUT_GET, 'filter', FILTER_SANITIZE_SPECIAL_CHARS); // FILTER_UNSAFE_RAW
|
||||
|
||||
$events = $ical->sortEventsWithOrder($ical->eventsFromInterval($period_val . ' month'));
|
||||
$result = [];
|
||||
|
||||
foreach ($events as $event) {
|
||||
$cat = $event->categories ?? '';
|
||||
|
||||
if ($filter && strpos($event->categories, $filter) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($event->categories) && strpos($event->categories, "hidden")) {
|
||||
continue;
|
||||
}
|
||||
if ($filter && stripos($cat, $filter) === false) continue;
|
||||
if (stripos($cat, "hidden") !== false) continue;
|
||||
|
||||
$start = new DateTime($event->dtstart);
|
||||
$end = new DateTime($event->dtend);
|
||||
$uid = $event->uid;
|
||||
|
||||
$interval = DateInterval::createFromDateString('1 day');
|
||||
$interval = new DateInterval('P1D');
|
||||
$period = new DatePeriod($start, $interval, $end);
|
||||
|
||||
foreach ($period as $dt) {
|
||||
$date = $dt->format("Y-m-d");
|
||||
|
||||
$result[$date][$uid]["dtstart"] = $iCal->iCalDateToDateTime($event->dtstart_array[3])->format(DateTime::ATOM);
|
||||
$result[$date][$uid]["dtend"] = $iCal->iCalDateToDateTime($event->dtend_array[3])->format(DateTime::ATOM);
|
||||
$result[$date][$uid]["datestr"] = (isset($event->dtstart_array[0]["VALUE"]) && $event->dtstart_array[0]["VALUE"] == 'DATE')?'':$start->format('H:i');
|
||||
$result[$date][$uid]["summary"] = mb_strimwidth($event->summary, 0, 255, "...");
|
||||
$result[$date][$uid]["location"] = mb_strimwidth($event->location, 0, 255, "...");
|
||||
$result[$date][$uid]["description"] = mb_strimwidth($event->description, 0, 255, "...");
|
||||
if(isset($event->categories)) $result[$date][$uid]["categories"] = $event->categories;
|
||||
$result[$date][$uid] = [
|
||||
"dtstart" => $start->format(DateTime::ATOM), //$ical->iCalDateToDateTime($event->dtstart_array[3])->format(DateTime::ATOM);
|
||||
"dtend" => $end->format(DateTime::ATOM), //$ical->iCalDateToDateTime($event->dtend_array[3])->format(DateTime::ATOM);
|
||||
"datestr" => (isset($event->dtstart_array[0]["VALUE"]) && $event->dtstart_array[0]["VALUE"] == 'DATE') ? '' : $start->format('H:i'),
|
||||
"summary" => mb_strimwidth($event->summary, 0, 255, "..."),
|
||||
"location" => mb_strimwidth($event->location ?? '', 0, 255, "..."),
|
||||
"description" => mb_strimwidth($event->description ?? '', 0, 255, "...")
|
||||
];
|
||||
if(!empty($cat)) $result[$date][$uid]["categories"] = $cat;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Allow every page to load this json
|
||||
header("Access-Control-Allow-Origin: *");
|
||||
header("Content-Type: application/json");
|
||||
|
||||
echo json_encode($result, JSON_UNESCAPED_SLASHES);
|
||||
header("Content-Type: application/json; charset=utf-8");
|
||||
echo json_encode($result, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||
Loading…
Add table
Add a link
Reference in a new issue