diff --git a/actions/event_manager/export/ical.php b/actions/event_manager/export/ical.php new file mode 100644 index 00000000..6aea43dd --- /dev/null +++ b/actions/event_manager/export/ical.php @@ -0,0 +1,128 @@ +getTimestamp(); + } + + $end_date = (string) get_input('end_date'); + if (empty($end_date)) { + $end_date = DateTime::createFromFormat('U', time()) + ->add(DateInterval::createFromDateString('1 month')) + ->getTimestamp(); + } else { + $end_date = DateTime::createFromFormat($date_format, $end_date)->getTimestamp(); + } + + $region = (string) get_input('region'); + $event_type = (string) get_input('event_type'); + + $owner = (array) get_input('owner'); + $group = (array) get_input('group'); + + $options = [ + 'types' => ['object'], + 'subTypes' => [Event::SUBTYPE], + 'metadata_name_value_pairs' => [ + [ + 'name' => 'event_start', + 'operand' => '>=', + 'value' => $start_date, + ], + [ + 'name' => 'event_end', + 'operand' => '<=', + 'value' => $end_date, + ], + ] + ]; + + if (!empty($region)) { + $options['metadata_name_value_pairs'][] = [ + 'name' => 'region', + 'operand' => 'IN', + 'value' => $region, + ]; + } + + if (!empty($event_type)) { + $options['metadata_name_value_pairs'][] = [ + 'name' => 'event_type', + 'operand' => 'IN', + 'value' => $event_type, + ]; + } + + switch ($calendar_type) { + case 'group': + if (empty($group)) { + return elgg_error_response(elgg_echo('event_manager:ical_direct:export:errors:groupempty')); + } + + $options['container_guids'] = $group; + break; + case 'owner': + if (empty($owner)) { + return elgg_error_response(elgg_echo('event_manager:ical_direct:export:errors:ownerempty')); + } + + if (!elgg_is_admin_logged_in() && (int) $owner[0] !== elgg_get_logged_in_user_guid()) { + return elgg_error_response(elgg_echo('event_manager:ical_direct:export:errors:ownermismatch')); + } + + $options['owner_guids'] = [$owner]; + break; + } + + $events = elgg_get_entities($options); +} else { + $event = get_entity($event_id); + if (!$event instanceof \Event) { + return; + } + + $events = [$event]; +} + +use Kigkonsult\Icalcreator\IcalInterface; +use Kigkonsult\Icalcreator\Vcalendar; + +try { + $vcalendar = Vcalendar::factory( + [ + IcalInterface::UNIQUE_ID => 'https://github.com/ColdTrick/event_manager', + ] + ) + ->setMethod(IcalInterface::PUBLISH) + ->setXprop(IcalInterface::X_WR_CALNAME, 'Exported event') + ->setXprop(IcalInterface::X_WR_CALDESC, 'Exported events from event_manager') + ->setXprop(IcalInterface::X_WR_RELCALID, elgg_get_site_url()) + ->setXprop(IcalInterface::X_WR_TIMEZONE, date_default_timezone_get()); +} catch (Exception $e) { + return elgg_error_response(elgg_echo('event_manager:ical_direct:export:errors:errorinstantiatingcalendar', [$e])); +} + +foreach ($events as $event) { + try { + $vcalendar->setComponent($event->toVEvent()); + } catch (Exception $e) { + return elgg_error_response(elgg_echo('event_manager:ical_direct:export:errors:erroraddingevent', [$e])); + } +} + +try { + return elgg_download_response($vcalendar->createCalendar(), 'export.ics'); +} catch (Exception $e) { + return elgg_error_response(elgg_echo('event_manager:ical_direct:export:errors:errorcreatingcalendar', [$e])); +} diff --git a/actions/event_manager/import/ical.php b/actions/event_manager/import/ical.php new file mode 100644 index 00000000..8188a1ec --- /dev/null +++ b/actions/event_manager/import/ical.php @@ -0,0 +1,91 @@ +canWriteToContainer(elgg_get_logged_in_user_guid())) { + return elgg_error_response(elgg_echo('event_manager:ical_direct:import:errors:grouppermission')); + } + break; + case 'owner': + if (empty($owner)) { + return elgg_error_response(elgg_echo('event_manager:ical_direct:import:errors:ownerempty')); + } + + $owner_guid = $owner[0]; + if (!get_entity($owner_guid) instanceof \ElggUser) { + return elgg_error_response(elgg_echo('event_manager:ical_direct:import:errors:invalidgroup')); + } + + if (!elgg_is_admin_logged_in() && (int) $owner_guid !== elgg_get_logged_in_user_guid()) { + return elgg_error_response(elgg_echo('event_manager:ical_direct:import:errors:ownermismatch')); + } + break; +} + +if (!$file) { + return elgg_error_response(elgg_echo('event_manager:ical_direct:import:errors:missingfile')); +} + +try { + $vcalendar = Vcalendar::factory( + [ + IcalInterface::UNIQUE_ID => 'https://github.com/ColdTrick/event_manager', + ] + ); +} catch (Exception $e) { + return elgg_error_response(elgg_echo('event_manager:ical_direct:import:errors:errorinstantiatingcalendar', [$e])); +} + +try { + $vcalendar->parse($file->getContent()); +} catch (Exception $e) { + return elgg_error_response(elgg_echo('event_manager:ical_direct:import:errors:errorpparsingcalendar', [$e])); +} + +$event_counter = 0; + +/** @var Vevent $component */ +foreach ($vcalendar->getComponents('Vevent') as $component) { + $event = Event::fromVEvent($component); + + switch ($calendar_type) { + case 'group': + $event->setContainerGUID($group_guid); + break; + case 'owner': + $event->owner_guid = $owner_guid; + break; + } + + $event->save(); + $event_counter++; +} + +$message = elgg_echo('event_manager:ical_direct:import:success', [$event_counter]); + +return elgg_ok_response( + '', + $message +); diff --git a/classes/ColdTrick/EventManager/Menus/Entity.php b/classes/ColdTrick/EventManager/Menus/Entity.php index 28085dd2..fa0b768a 100644 --- a/classes/ColdTrick/EventManager/Menus/Entity.php +++ b/classes/ColdTrick/EventManager/Menus/Entity.php @@ -35,7 +35,7 @@ public static function registerMailAttendees(\Elgg\Event $event): ?MenuItems { 'text' => elgg_echo('event_manager:menu:mail'), 'href' => elgg_generate_entity_url($entity, 'mail'), ]); - + return $result; } @@ -148,4 +148,35 @@ public static function registerEventUnsubscribe(\Elgg\Event $event): ?MenuItems return $result; } + + /** + * Adds menu items to the event entity menu for exporting it to ical + * + * @param \Elgg\Event $event 'register', 'menu:entity' + * + * @return null|MenuItems + */ + public static function registerICalExport(\Elgg\Event $event): ?MenuItems { + $entity = $event->getEntityParam(); + if (!$entity instanceof \Event) { + return null; + } + + if (!elgg_get_plugin_setting('ical_direct', 'event_manager')) { + return null; + } + + // show an ical export link + $result = $event->getValue(); + + $result[] = \ElggMenuItem::factory([ + 'name' => 'ical-export', + 'icon' => 'calendar-plus', + 'text' => elgg_echo('event_manager:ical_direct:export'), + 'href' => elgg_generate_action_url('event_manager/export/ical', ['event_id' => $entity->guid]), + 'priority' => 300, + ]); + + return $result; + } } diff --git a/classes/ColdTrick/EventManager/Menus/Title.php b/classes/ColdTrick/EventManager/Menus/Title.php new file mode 100644 index 00000000..311dd868 --- /dev/null +++ b/classes/ColdTrick/EventManager/Menus/Title.php @@ -0,0 +1,51 @@ +getValue(); + + if ($event->getParam('identifier') !== 'event' || $event->getParam('filter_id') !== 'events') { + return $result; + } + + if (elgg_get_plugin_setting('ical_direct', 'event_manager')) { + $result[] = \ElggMenuItem::factory([ + 'name' => 'export-ical', + 'icon' => 'download', + 'text' => elgg_echo('event_manager:ical_direct:export'), + 'href' => elgg_http_add_url_query_elements('ajax/form/event_manager/export/ical', [ + 'list_route' => elgg_get_current_route_name(), + 'route_parameters' => elgg_get_current_route()->getMatchedParameters(), + ]), + 'link_class' => 'elgg-lightbox' + ]); + $result[] = \ElggMenuItem::factory([ + 'name' => 'import-ical', + 'icon' => 'upload', + 'text' => elgg_echo('event_manager:ical_direct:import'), + 'href' => elgg_http_add_url_query_elements('ajax/form/event_manager/import/ical', [ + 'list_route' => elgg_get_current_route_name(), + 'route_parameters' => elgg_get_current_route()->getMatchedParameters(), + ]), + 'link_class' => 'elgg-lightbox' + ]); + } + + return $result; + } +} diff --git a/classes/Event.php b/classes/Event.php index c9b665e5..f11d9453 100644 --- a/classes/Event.php +++ b/classes/Event.php @@ -1,9 +1,11 @@ getStartDate('Y-m-d\\TH:i:s'), $timezone); + $dtend = DateTimeImmutable::createFromFormat('Y-m-d\\TH:i:s', $this->getEndDate('Y-m-d\\TH:i:s'), $timezone); + /** @noinspection PhpUnhandledExceptionInspection */ + $vevent = Vevent::factory( + null, + $dtstart, + $dtend, + null, + $this->title + ) + ->setDescription($this->shortdescription) + ->setDtstamp(DateTimeImmutable::createFromFormat('c', $this->getTimeCreated())) + ->setComment($this->description) + ->setLocation($this->location); + + $organizers = $this->getOrganizers(); + if (count($organizers) > 0 && isset($organizers[0]->email)) { + $vevent->setOrganizer($organizers[0]->email); + } + + if ($this->countAttendees() > 0) { + /** @var ElggUser[] $attendees */ + $attendees = elgg_get_entities([ + 'type' => 'user', // trigger search fields generation + 'type_subtype_pairs' => [ + 'user' => ELGG_ENTITIES_ANY_VALUE, + 'object' => [ + EventRegistration::SUBTYPE, + ], + ], + 'relationship_guid' => $this->guid, + 'relationship' => 'event_attending', + ]); + foreach ($attendees as $attendee) { + $vevent->setAttendee($attendee->email); + } + } + + foreach ($this->getContacts() as $contact) { + if ($contact instanceof ElggUser && isset($contact->email)) { + $vevent->setContact($contact->email); + } + } + + if ($this->website) { + $vevent->setXprop('X-WEBSITE', $this->website); + } + + if ($this->region) { + $vevent->setXprop('X-PROP-REGION', $this->region); + } + + if ($this->venue) { + $vevent->setXprop('X-PROP-VENUE', $this->venue); + } + + if ($this->event_type) { + $vevent->setXprop('X-PROP-TYPE', $this->event_type); + } + + return $vevent; + } + + /** + * Generates a new event based on an iCal Vevent + * + * @param Vevent $vevent Source iCal Vevent to convert + * @return Event + */ + public static function fromVEvent(Vevent $vevent): Event { + $event = new Event(); + $event->event_start = $vevent->getDtstart()->getTimestamp() + $vevent->getDtstart()->getOffset(); + if ($vevent->getDtend() == null || $vevent->getDtend()->getTimestamp() < $vevent->getDtstart()->getTimestamp()) { + $event->event_end = $event->event_start; + } else { + $event->event_end = $vevent->getDtend()->getTimestamp() + $vevent->getDtend()->getOffset(); + } + + $event->title = $vevent->getSummary(); + $event->shortdescription = $vevent->getDescription(); + $event->description = $vevent->getComment(); + $event->location = $vevent->getLocation(); + + if ($vevent->isOrganizerSet()) { + $organizer = elgg_get_user_by_email($vevent->getOrganizer()); + if (is_null($organizer)) { + $event->organizer = $vevent->getOrganizer(); + } else { + $event->organizer_guids = [$organizer->guid]; + } + } + + if ($vevent->isContactSet()) { + foreach ($vevent->getAllContact() as $contact) { + $contact_object = elgg_get_user_by_email($contact); + if (!is_null($contact_object)) { + if (!is_array($event->contact_guids)) { + $event->contact_guids = []; + } + + $event->contact_guids[] = $contact_object->guid; + } + } + } + + if ($vevent->isXpropSet('X-WEBSITE')) { + $event->website = $vevent->getXprop('X-WEBSITE')[1]; + } + + if ($vevent->isXpropSet('X-PROP-REGION')) { + $region = $vevent->getXprop('X-PROP-REGION')[1]; + $region_settings = trim((string) elgg_get_plugin_setting('region_list', 'event_manager')); + $region_list = explode(',', $region_settings); + if (in_array($region, $region_list)) { + $event->region = $vevent->getXprop('X-PROP-REGION')[1]; + } + } + + if ($vevent->isXpropSet('X-PROP-VENUE')) { + $event->venue = $vevent->getXprop('X-PROP-VENUE')[1]; + } + + if ($vevent->isXpropSet('X-PROP-TYPE')) { + $event->event_type = $vevent->getXprop('X-PROP-TYPE')[1]; + } + + return $event; + } } diff --git a/composer.json b/composer.json index fcff4d58..ce7315dc 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,8 @@ }, "require": { "dompdf/dompdf" : "~3.1.0", - "npm-asset/fullcalendar": "~6.1.0" + "npm-asset/fullcalendar": "~6.1.0", + "kigkonsult/icalcreator": "^2.41" }, "repositories": [ { diff --git a/composer.lock b/composer.lock index 127dec03..993d9104 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ed4a108af4e355cd8ac3748f5131e037", + "content-hash": "4393d2a789e3e889ed1f276b84d0b32c", "packages": [ { "name": "dompdf/dompdf", - "version": "v3.1.0", + "version": "v3.1.4", "source": { "type": "git", "url": "https://github.com/dompdf/dompdf.git", - "reference": "a51bd7a063a65499446919286fb18b518177155a" + "reference": "db712c90c5b9868df3600e64e68da62e78a34623" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/a51bd7a063a65499446919286fb18b518177155a", - "reference": "a51bd7a063a65499446919286fb18b518177155a", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/db712c90c5b9868df3600e64e68da62e78a34623", + "reference": "db712c90c5b9868df3600e64e68da62e78a34623", "shasum": "" }, "require": { @@ -66,22 +66,22 @@ "homepage": "https://github.com/dompdf/dompdf", "support": { "issues": "https://github.com/dompdf/dompdf/issues", - "source": "https://github.com/dompdf/dompdf/tree/v3.1.0" + "source": "https://github.com/dompdf/dompdf/tree/v3.1.4" }, - "time": "2025-01-15T14:09:04+00:00" + "time": "2025-10-29T12:43:30+00:00" }, { "name": "dompdf/php-font-lib", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/dompdf/php-font-lib.git", - "reference": "6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d" + "reference": "a6e9a688a2a80016ac080b97be73d3e10c444c9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d", - "reference": "6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d", + "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/a6e9a688a2a80016ac080b97be73d3e10c444c9a", + "reference": "a6e9a688a2a80016ac080b97be73d3e10c444c9a", "shasum": "" }, "require": { @@ -89,7 +89,7 @@ "php": "^7.1 || ^8.0" }, "require-dev": { - "symfony/phpunit-bridge": "^3 || ^4 || ^5 || ^6" + "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11 || ^12" }, "type": "library", "autoload": { @@ -111,31 +111,31 @@ "homepage": "https://github.com/dompdf/php-font-lib", "support": { "issues": "https://github.com/dompdf/php-font-lib/issues", - "source": "https://github.com/dompdf/php-font-lib/tree/1.0.1" + "source": "https://github.com/dompdf/php-font-lib/tree/1.0.2" }, - "time": "2024-12-02T14:37:59+00:00" + "time": "2026-01-20T14:10:26+00:00" }, { "name": "dompdf/php-svg-lib", - "version": "1.0.0", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/dompdf/php-svg-lib.git", - "reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af" + "reference": "8259ffb930817e72b1ff1caef5d226501f3dfeb1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/eb045e518185298eb6ff8d80d0d0c6b17aecd9af", - "reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af", + "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/8259ffb930817e72b1ff1caef5d226501f3dfeb1", + "reference": "8259ffb930817e72b1ff1caef5d226501f3dfeb1", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "^7.1 || ^8.0", - "sabberworm/php-css-parser": "^8.4" + "sabberworm/php-css-parser": "^8.4 || ^9.0" }, "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5" + "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11" }, "type": "library", "autoload": { @@ -157,9 +157,116 @@ "homepage": "https://github.com/dompdf/php-svg-lib", "support": { "issues": "https://github.com/dompdf/php-svg-lib/issues", - "source": "https://github.com/dompdf/php-svg-lib/tree/1.0.0" + "source": "https://github.com/dompdf/php-svg-lib/tree/1.0.2" }, - "time": "2024-04-29T13:26:35+00:00" + "time": "2026-01-02T16:01:13+00:00" + }, + { + "name": "kigkonsult/icalcreator", + "version": "v2.41.92", + "source": { + "type": "git", + "url": "https://github.com/iCalcreator/iCalcreator.git", + "reference": "a4d35d7a58c08b816dc8a7778db19f461c1429bd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/iCalcreator/iCalcreator/zipball/a4d35d7a58c08b816dc8a7778db19f461c1429bd", + "reference": "a4d35d7a58c08b816dc8a7778db19f461c1429bd", + "shasum": "" + }, + "require": { + "ext-intl": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "ext-simplexml": "*", + "ext-zlib": "*", + "php": ">=8.0" + }, + "require-dev": { + "degraciamathieu/php-arguments-detector": ">=0.5.0", + "ext-xdebug": "*", + "phpcompatibility/php-compatibility": ">=9.3.5", + "phpmd/phpmd": ">=2.13.0", + "phpstan/phpstan": ">=0.9.3", + "phpunit/phpunit": ">=6.5.13", + "squizlabs/php_codesniffer": ">=3.5.5", + "vimeo/psalm": "*" + }, + "type": "library", + "autoload": { + "files": [ + "autoload.php" + ], + "psr-4": { + "Kigkonsult\\Icalcreator\\": [ + "src/" + ] + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Kjell-Inge Gustafsson", + "email": "ical@kigkonsult.se" + } + ], + "description": "iCalcreator is the PHP implementation of rfc2445/rfc5545 and rfc updates, management of calendar information", + "keywords": [ + "alarm", + "availability", + "calendar", + "daylight", + "event", + "ical", + "json", + "location", + "management", + "participant", + "resource", + "rfc2445", + "rfc5545", + "rfc5870", + "rfc6321", + "rfc6868", + "rfc7529", + "rfc7808", + "rfc7953", + "rfc7986", + "rfc9073", + "rfc9074", + "standard", + "todo", + "vCalendar", + "valarm", + "vevent", + "vfreebusy", + "vjournal", + "vtimezone", + "vtodo", + "xml" + ], + "support": { + "issues": "https://github.com/iCalcreator/iCalcreator/issues", + "source": "https://github.com/iCalcreator/iCalcreator/tree/v2.41.92" + }, + "funding": [ + { + "url": "https://paypal.me/kigkonsult", + "type": "other" + }, + { + "url": "https://www.buymeacoffee.com/kigkonsult", + "type": "other" + } + ], + "time": "2025-01-17T10:06:29+00:00" }, { "name": "masterminds/html5", @@ -230,18 +337,18 @@ }, { "name": "npm-asset/fullcalendar", - "version": "6.1.18", + "version": "6.1.20", "dist": { "type": "tar", - "url": "https://registry.npmjs.org/fullcalendar/-/fullcalendar-6.1.18.tgz" + "url": "https://registry.npmjs.org/fullcalendar/-/fullcalendar-6.1.20.tgz" }, "require": { - "npm-asset/fullcalendar--core": "~6.1.18", - "npm-asset/fullcalendar--daygrid": "~6.1.18", - "npm-asset/fullcalendar--interaction": "~6.1.18", - "npm-asset/fullcalendar--list": "~6.1.18", - "npm-asset/fullcalendar--multimonth": "~6.1.18", - "npm-asset/fullcalendar--timegrid": "~6.1.18" + "npm-asset/fullcalendar--core": "~6.1.20", + "npm-asset/fullcalendar--daygrid": "~6.1.20", + "npm-asset/fullcalendar--interaction": "~6.1.20", + "npm-asset/fullcalendar--list": "~6.1.20", + "npm-asset/fullcalendar--multimonth": "~6.1.20", + "npm-asset/fullcalendar--timegrid": "~6.1.20" }, "type": "npm-asset", "license": [ @@ -250,10 +357,10 @@ }, { "name": "npm-asset/fullcalendar--core", - "version": "6.1.19", + "version": "6.1.20", "dist": { "type": "tar", - "url": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.19.tgz" + "url": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.20.tgz" }, "require": { "npm-asset/preact": "~10.12.1" @@ -265,10 +372,10 @@ }, { "name": "npm-asset/fullcalendar--daygrid", - "version": "6.1.18", + "version": "6.1.20", "dist": { "type": "tar", - "url": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.18.tgz" + "url": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.20.tgz" }, "type": "npm-asset", "license": [ @@ -277,10 +384,10 @@ }, { "name": "npm-asset/fullcalendar--interaction", - "version": "6.1.18", + "version": "6.1.20", "dist": { "type": "tar", - "url": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-6.1.18.tgz" + "url": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-6.1.20.tgz" }, "type": "npm-asset", "license": [ @@ -289,10 +396,10 @@ }, { "name": "npm-asset/fullcalendar--list", - "version": "6.1.18", + "version": "6.1.20", "dist": { "type": "tar", - "url": "https://registry.npmjs.org/@fullcalendar/list/-/list-6.1.18.tgz" + "url": "https://registry.npmjs.org/@fullcalendar/list/-/list-6.1.20.tgz" }, "type": "npm-asset", "license": [ @@ -301,13 +408,13 @@ }, { "name": "npm-asset/fullcalendar--multimonth", - "version": "6.1.18", + "version": "6.1.20", "dist": { "type": "tar", - "url": "https://registry.npmjs.org/@fullcalendar/multimonth/-/multimonth-6.1.18.tgz" + "url": "https://registry.npmjs.org/@fullcalendar/multimonth/-/multimonth-6.1.20.tgz" }, "require": { - "npm-asset/fullcalendar--daygrid": "~6.1.18" + "npm-asset/fullcalendar--daygrid": "~6.1.20" }, "type": "npm-asset", "license": [ @@ -316,13 +423,13 @@ }, { "name": "npm-asset/fullcalendar--timegrid", - "version": "6.1.18", + "version": "6.1.20", "dist": { "type": "tar", - "url": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-6.1.18.tgz" + "url": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-6.1.20.tgz" }, "require": { - "npm-asset/fullcalendar--daygrid": "~6.1.18" + "npm-asset/fullcalendar--daygrid": "~6.1.20" }, "type": "npm-asset", "license": [ @@ -343,25 +450,33 @@ }, { "name": "sabberworm/php-css-parser", - "version": "v8.9.0", + "version": "v9.1.0", "source": { "type": "git", "url": "https://github.com/MyIntervals/PHP-CSS-Parser.git", - "reference": "d8e916507b88e389e26d4ab03c904a082aa66bb9" + "reference": "1b363fdbdc6dd0ca0f4bf98d3a4d7f388133f1fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/d8e916507b88e389e26d4ab03c904a082aa66bb9", - "reference": "d8e916507b88e389e26d4ab03c904a082aa66bb9", + "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/1b363fdbdc6dd0ca0f4bf98d3a4d7f388133f1fb", + "reference": "1b363fdbdc6dd0ca0f4bf98d3a4d7f388133f1fb", "shasum": "" }, "require": { "ext-iconv": "*", - "php": "^5.6.20 || ^7.0.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + "php": "^7.2.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", + "thecodingmachine/safe": "^1.3 || ^2.5 || ^3.3" }, "require-dev": { - "phpunit/phpunit": "5.7.27 || 6.5.14 || 7.5.20 || 8.5.41", - "rawr/cross-data-providers": "^2.0.0" + "php-parallel-lint/php-parallel-lint": "1.4.0", + "phpstan/extension-installer": "1.4.3", + "phpstan/phpstan": "1.12.28 || 2.1.25", + "phpstan/phpstan-phpunit": "1.4.2 || 2.0.7", + "phpstan/phpstan-strict-rules": "1.6.2 || 2.0.6", + "phpunit/phpunit": "8.5.46", + "rawr/phpunit-data-provider": "3.3.1", + "rector/rector": "1.2.10 || 2.1.7", + "rector/type-perfect": "1.0.0 || 2.1.0" }, "suggest": { "ext-mbstring": "for parsing UTF-8 CSS" @@ -369,7 +484,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "9.0.x-dev" + "dev-main": "9.2.x-dev" } }, "autoload": { @@ -403,9 +518,152 @@ ], "support": { "issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues", - "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.9.0" + "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v9.1.0" + }, + "time": "2025-09-14T07:37:21+00:00" + }, + { + "name": "thecodingmachine/safe", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/thecodingmachine/safe.git", + "reference": "705683a25bacf0d4860c7dea4d7947bfd09eea19" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/705683a25bacf0d4860c7dea4d7947bfd09eea19", + "reference": "705683a25bacf0d4860c7dea4d7947bfd09eea19", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpstan/phpstan": "^2", + "phpunit/phpunit": "^10", + "squizlabs/php_codesniffer": "^3.2" + }, + "type": "library", + "autoload": { + "files": [ + "lib/special_cases.php", + "generated/apache.php", + "generated/apcu.php", + "generated/array.php", + "generated/bzip2.php", + "generated/calendar.php", + "generated/classobj.php", + "generated/com.php", + "generated/cubrid.php", + "generated/curl.php", + "generated/datetime.php", + "generated/dir.php", + "generated/eio.php", + "generated/errorfunc.php", + "generated/exec.php", + "generated/fileinfo.php", + "generated/filesystem.php", + "generated/filter.php", + "generated/fpm.php", + "generated/ftp.php", + "generated/funchand.php", + "generated/gettext.php", + "generated/gmp.php", + "generated/gnupg.php", + "generated/hash.php", + "generated/ibase.php", + "generated/ibmDb2.php", + "generated/iconv.php", + "generated/image.php", + "generated/imap.php", + "generated/info.php", + "generated/inotify.php", + "generated/json.php", + "generated/ldap.php", + "generated/libxml.php", + "generated/lzf.php", + "generated/mailparse.php", + "generated/mbstring.php", + "generated/misc.php", + "generated/mysql.php", + "generated/mysqli.php", + "generated/network.php", + "generated/oci8.php", + "generated/opcache.php", + "generated/openssl.php", + "generated/outcontrol.php", + "generated/pcntl.php", + "generated/pcre.php", + "generated/pgsql.php", + "generated/posix.php", + "generated/ps.php", + "generated/pspell.php", + "generated/readline.php", + "generated/rnp.php", + "generated/rpminfo.php", + "generated/rrd.php", + "generated/sem.php", + "generated/session.php", + "generated/shmop.php", + "generated/sockets.php", + "generated/sodium.php", + "generated/solr.php", + "generated/spl.php", + "generated/sqlsrv.php", + "generated/ssdeep.php", + "generated/ssh2.php", + "generated/stream.php", + "generated/strings.php", + "generated/swoole.php", + "generated/uodbc.php", + "generated/uopz.php", + "generated/url.php", + "generated/var.php", + "generated/xdiff.php", + "generated/xml.php", + "generated/xmlrpc.php", + "generated/yaml.php", + "generated/yaz.php", + "generated/zip.php", + "generated/zlib.php" + ], + "classmap": [ + "lib/DateTime.php", + "lib/DateTimeImmutable.php", + "lib/Exceptions/", + "generated/Exceptions/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHP core functions that throw exceptions instead of returning FALSE on error", + "support": { + "issues": "https://github.com/thecodingmachine/safe/issues", + "source": "https://github.com/thecodingmachine/safe/tree/v3.4.0" }, - "time": "2025-07-11T13:20:48+00:00" + "funding": [ + { + "url": "https://github.com/OskarStark", + "type": "github" + }, + { + "url": "https://github.com/shish", + "type": "github" + }, + { + "url": "https://github.com/silasjoisten", + "type": "github" + }, + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2026-02-04T18:08:13+00:00" } ], "packages-dev": [], diff --git a/elgg-plugin.php b/elgg-plugin.php index 6cf9c675..9edc8e19 100644 --- a/elgg-plugin.php +++ b/elgg-plugin.php @@ -35,6 +35,7 @@ 'show_service_outlookcom' => 1, 'show_service_outlook' => 1, 'show_service_appleical' => 1, + 'ical_direct' => 1, ], 'entities' => [ [ @@ -118,6 +119,8 @@ 'event_manager/forms/program/day' => ['ajax' => true], 'event_manager/forms/program/slot' => ['ajax' => true], 'forms/event_manager/event/copy' => ['ajax' => true], + 'forms/event_manager/export/ical' => ['ajax' => true], + 'forms/event_manager/import/ical' => ['ajax' => true] ], 'routes' => [ 'add:object:event' => [ @@ -258,6 +261,9 @@ 'event_manager/day/edit' => [], 'event_manager/delete_program_item' => [], + + 'event_manager/export/ical' => [], + 'event_manager/import/ical' => [], ], 'widgets' => [ 'events' => [ @@ -338,6 +344,7 @@ '\ColdTrick\EventManager\Menus\Entity::registerAttendeeActions' => [], '\ColdTrick\EventManager\Menus\Entity::registerEventUnsubscribe' => ['priority' => 600], '\ColdTrick\EventManager\Menus\Entity::registerMailAttendees' => [], + '\ColdTrick\EventManager\Menus\Entity::registerICalExport' => [], ], 'menu:event_files' => [ '\ColdTrick\EventManager\Menus\EventFiles::registerFiles' => [], @@ -359,6 +366,9 @@ 'menu:site' => [ '\ColdTrick\EventManager\Menus\Site::registerEvents' => [], ], + 'menu:title' => [ + '\ColdTrick\EventManager\Menus\Title::registerICal' => [], + ] ], 'search:fields' => [ 'object:event' => [ diff --git a/languages/de.php b/languages/de.php index c42dbaf7..db43bef7 100644 --- a/languages/de.php +++ b/languages/de.php @@ -34,7 +34,7 @@ 'event_manager:personwaitinglist' => 'Personen auf der Warteliste', 'event_manager:peoplewaitinglist' => 'Personen auf der Warteliste', 'event_manager:registration:view:savetopdf' => 'als PDF speichern', - 'event_manager:edit:title' => ' erstelle / bearbeite Veranstaltung', + 'event_manager:edit:title' => 'Veranstaltung bearbeiten', 'event_manager:edit:upload:title' => 'Datei(en) zu deiner Veranstaltung hinzufügen', 'event_manager:edit:form:tabs:profile' => 'Profile', 'event_manager:edit:form:tabs:profile:toggle' => 'Hier können Sie weitere Veranstaltungs-Details konfigurieren', @@ -301,4 +301,56 @@ 'event_manager:addevent:mail:service:outlook' => 'Outlook', 'event_manager:addevent:mail:service:outlookcom' => 'Outlook.com', 'event_manager:addevent:mail:service:yahoo' => 'Yahoo', + + 'event_manager:settings:ical_direct' => 'Integriertes iCal', + 'event_manager:settings:ical_direct:enable' => 'Die internen iCal-Features aktivieren', + 'event_manager:settings:ical_direct:enable:help' => 'Die integrierten iCal-Features für Export und Import aktivieren', + 'event_manager:ical_direct:export' => 'iCal exportieren', + 'event_manager:ical_direct:export:calendar_type' => 'Kalender', + 'event_manager:ical_direct:export:calendar_type:help' => 'Wöhle den zu exportierenden Kalender aus', + 'event_manager:ical_direct:calendar_type:all' => 'Alle', + 'event_manager:ical_direct:calendar_type:group' => 'Gruppe', + 'event_manager:ical_direct:calendar_type:owner' => 'Benutzer*in', + 'event_manager:ical_direct:export:owner' => 'Benutzer*in', + 'event_manager:ical_direct:export:owner:help' => 'Wähle die Benutzer*in aus, deren Kalender exportiert werden soll', + 'event_manager:ical_direct:export:group' => 'Gruppe', + 'event_manager:ical_direct:export:group:help' => 'Wähle die Gruppe aus, deren Kalender exportiert werden soll', + 'event_manager:ical_direct:export:timespan' => 'Zeitbereich für den Export', + 'event_manager:ical_direct:export:start' => 'Startdatum', + 'event_manager:ical_direct:export:end' => 'Enddatum', + 'event_manager:ical_direct:export:region' => 'Region', + 'event_manager:ical_direct:export:region:help' => 'Wähle eine oder mehr Regionen aus, um nach diesen zu filtern', + 'event_manager:ical_direct:export:type' => 'Typ', + 'event_manager:ical_direct:export:type:help' => 'Wähle einen oder mehrere Eventtypen aus, um nach diesen zu filtern', + 'event_manager:ical_direct:export:submit' => 'Exportieren', + 'event_manager:ical_direct:export:errors:groupempty' => 'Keine Gruppe angegeben', + 'event_manager:ical_direct:export:errors:ownerempty' => 'Kein Besitzer angegeben', + 'event_manager:ical_direct:export:errors:ownermismatch' => 'Du musst ein Administrator sein, um die Kalender anderer Benutzer zu exportieren', + 'event_manager:ical_direct:export:errors:errorinstantiatingcalendar' => 'Fehler beim Instanzieren des Kalenders: %s', + 'event_manager:ical_direct:export:errors:erroraddingevent' => 'Fehler beim Hinzufügen eines Events zum Kalender: %s', + 'event_manager:ical_direct:export:errors:errorcreatingcalendar' => 'Fehler beim Erzeugen des Kalenders: %s', + + 'event_manager:ical_direct:import' => 'iCal importieren', + 'event_manager:ical_direct:import:calendar_type' => 'Kalender', + 'event_manager:ical_direct:import:calendar_type:help' => 'Wähle den Zielkalender für den Import', + 'event_manager:ical_direct:import:owner' => 'Benutzer*in', + 'event_manager:ical_direct:import:owner:help' => 'Wähle die Benutzer*in in deren Kalender die Datei importiert wird', + 'event_manager:ical_direct:import:group' => 'Gruppe', + 'event_manager:ical_direct:import:group:help' => 'Wähle die Gruppe in deren Kalender die Datei importiert wird', + 'event_manager:ical_direct:import:file' => 'Import-Datei', + 'event_manager:ical_direct:import:file:help' => 'ICS-Datei für den Import', + 'event_manager:ical_direct:import:submit' => 'Importieren', + 'event_manager:ical_direct:import:success' => '%d Einträge erfolgreich importiert', + 'event_manager:ical_direct:import:errors:groupempty' => 'Keine Gruppe angegeben', + 'event_manager:ical_direct:import:errors:invalidgroup' => 'Ungültige Gruppe angegeben', + 'event_manager:ical_direct:import:errors:ownerempty' => 'Kein Besitzer angegeben', + 'event_manager:ical_direct:import:errors:invalidowner' => 'Ungültigen Besitzer angegeben', + 'event_manager:ical_direct:import:errors:ownermismatch' => 'Du musst ein Administrator sein, um einen Kalender für einen anderen Benutzer zu importieren.', + 'event_manager:ical_direct:import:errors:grouppermission' => 'Du musst ein Administrator sein oder eine Schreibberechtigung für die Gruppe haben', + 'event_manager:ical_direct:import:errors:errorinstantiatingcalendar' => 'Fehler beim Instanzieren des Kalenders: %s', + 'event_manager:ical_direct:import:errors:errorconvertingevent' => 'Fehler bei der Konvertierung eines Events: %s', + 'event_manager:ical_direct:import:errors:errorpparsingcalendar' => 'Fehler beim Parsen der iCal-Datei: %s', + 'event_manager:ical_direct:import:errors:missingfile' => 'Fehlende iCal-Datei', + 'event_manager:ical_direct_import:errors:unknownregion' => 'Region %s unbekannt. Bitte füge sie zur Liste der Regionen hinzu.', + ); diff --git a/languages/en.php b/languages/en.php index 79dc411b..a5a1d3cd 100644 --- a/languages/en.php +++ b/languages/en.php @@ -452,5 +452,55 @@ 'event_manager:upgrade:2023030700:title' => "Move event header images to new image location", 'event_manager:upgrade:2023030700:description' => "In Elgg 5 there is built in header image support. This migration moves old icons uploaded with events to this new location.", - + 'event_manager:settings:ical_direct' => 'Embedded iCal', + 'event_manager:settings:ical_direct:enable' => 'Enable embedded iCal features', + 'event_manager:settings:ical_direct:enable:help' => 'Enable the embeded iCal-features for export and import', + 'event_manager:ical_direct:export' => 'Export to iCal', + 'event_manager:ical_direct:export:calendar_type' => 'Calendar', + 'event_manager:ical_direct:export:calendar_type:help' => 'Select the calendar to export', + 'event_manager:ical_direct:calendar_type:all' => 'All', + 'event_manager:ical_direct:calendar_type:group' => 'Group', + 'event_manager:ical_direct:calendar_type:owner' => 'User', + 'event_manager:ical_direct:export:owner' => 'User', + 'event_manager:ical_direct:export:owner:help' => 'Select the user whose calendar will be exported', + 'event_manager:ical_direct:export:group' => 'Group', + 'event_manager:ical_direct:export:group:help' => 'Select the group which calendar will be exported', + 'event_manager:ical_direct:export:timespan' => 'Export timespan', + 'event_manager:ical_direct:export:start' => 'Start date', + 'event_manager:ical_direct:export:end' => 'End date', + 'event_manager:ical_direct:export:region' => 'Region', + 'event_manager:ical_direct:export:region:help' => 'Select one or more regions to filter for', + 'event_manager:ical_direct:export:type' => 'Type', + 'event_manager:ical_direct:export:type:help' => 'Select one or more event types to filter for', + 'event_manager:ical_direct:export:submit' => 'Export', + 'event_manager:ical_direct:export:errors:groupempty' => 'No group specified', + 'event_manager:ical_direct:export:errors:ownerempty' => 'No owner specified', + 'event_manager:ical_direct:export:errors:ownermismatch' => 'You need to be an administrator to export other user\'s calendars', + 'event_manager:ical_direct:export:errors:errorinstantiatingcalendar' => 'Error instantiating calendar: %s', + 'event_manager:ical_direct:export:errors:erroraddingevent' => 'Error adding event to calendar: %s', + 'event_manager:ical_direct:export:errors:errorcreatingcalendar' => 'Error creating calendar: %s', + + 'event_manager:ical_direct:import' => 'Import iCal', + 'event_manager:ical_direct:import:calendar_type' => 'Calendar', + 'event_manager:ical_direct:import:calendar_type:help' => 'Select the calendar to import into', + 'event_manager:ical_direct:import:owner' => 'User', + 'event_manager:ical_direct:import:owner:help' => 'Select the user whose calendar will be used for the import', + 'event_manager:ical_direct:import:group' => 'Group', + 'event_manager:ical_direct:import:group:help' => 'Select the group which calendar will be user for the import', + 'event_manager:ical_direct:import:file' => 'Import file', + 'event_manager:ical_direct:import:file:help' => 'ICS file to import', + 'event_manager:ical_direct:import:submit' => 'Import', + 'event_manager:ical_direct:import:success' => 'Successfully imported %d entries.', + 'event_manager:ical_direct:import:errors:groupempty' => 'No group specified', + 'event_manager:ical_direct:import:errors:invalidgroup' => 'Invalid group specified', + 'event_manager:ical_direct:import:errors:ownerempty' => 'No owner specified', + 'event_manager:ical_direct:import:errors:invalidowner' => 'Invalid owner specified', + 'event_manager:ical_direct:import:errors:ownermismatch' => 'You need to be an administrator to import other user\'s calendars', + 'event_manager:ical_direct:import:errors:grouppermission' => 'You need to be an administrator or be able to write to the target group', + 'event_manager:ical_direct:import:errors:errorinstantiatingcalendar' => 'Error instantiating calendar: %s', + 'event_manager:ical_direct:import:errors:errorconvertingevent' => 'Error converting to event: %s', + 'event_manager:ical_direct:import:errors:errorpparsingcalendar' => 'Error parsing calendar file: %s', + 'event_manager:ical_direct:import:errors:missingfile' => 'Missing iCal file', + 'event_manager:ical_direct_import:errors:unknownregion' => 'Region %s unknown. Please add it to the list of regions.', + ); diff --git a/views/default/forms/event_manager/export/ical.php b/views/default/forms/event_manager/export/ical.php new file mode 100644 index 00000000..d83bdea6 --- /dev/null +++ b/views/default/forms/event_manager/export/ical.php @@ -0,0 +1,145 @@ + [ + 'text' => elgg_echo('event_manager:ical_direct:calendar_type:all'), + 'selected' => $calendar_type_selected == 'all', + 'value' => 'all', + ], + 'group' => [ + 'text' => elgg_echo('event_manager:ical_direct:calendar_type:group'), + 'selected' => $calendar_type_selected == 'group', + 'value' => 'group', + ], + 'owner' => [ + 'text' => elgg_echo('event_manager:ical_direct:calendar_type:owner'), + 'selected' => $calendar_type_selected == 'owner', + 'value' => 'owner', + ], +]; + +echo elgg_view_field([ + '#type' => 'select', + '#label' => elgg_echo('event_manager:ical_direct:export:calendar_type'), + '#help' => elgg_echo('event_manager:ical_direct:export:calendar_type:help'), + 'required' => true, + 'name' => 'calendar_type', + 'options_values' => $calendar_type_options, +]); + +$owner = ''; + +if (array_key_exists('username', $route_parameters)) { + $owner = elgg_get_user_by_username($route_parameters['username'])->getGUID(); +} + +echo elgg_view_field([ + '#type' => 'userpicker', + '#label' => elgg_echo('event_manager:ical_direct:export:owner'), + '#help' => elgg_echo('event_manager:ical_direct:export:owner:help'), + 'required' => true, + 'name' => 'owner', + 'limit' => 1, + 'values' => [$owner], + '#class' => $calendar_type_selected != 'owner' ? ['hidden'] : [], +]); + + +$group = ''; + +if (array_key_exists('guid', $route_parameters)) { + $group = $route_parameters['guid']; +} + +echo elgg_view_field([ + '#type' => 'grouppicker', + '#label' => elgg_echo('event_manager:ical_direct:export:group'), + '#help' => elgg_echo('event_manager:ical_direct:export:group:help'), + 'required' => true, + 'name' => 'group', + 'limit' => 1, + 'values' => [$group], + '#class' => $calendar_type_selected != 'group' ? ['hidden'] : [], +]); + +// Filter timespan + +echo elgg_view_field([ + '#type' => 'fieldset', + 'legend' => elgg_echo('event_manager:ical_direct:export:timespan'), + 'fields' => [ + [ + '#type' => 'date', + '#label' => elgg_echo('event_manager:ical_direct:export:start'), + 'required' => true, + 'name' => 'start_date', + 'value' => time(), + ], + [ + '#type' => 'date', + '#label' => elgg_echo('event_manager:ical_direct:export:end'), + 'required' => true, + 'name' => 'end_date', + 'value' => DateTime::createFromFormat('U', time())->add(DateInterval::createFromDateString('1 month'))->getTimestamp() + ] + ] +]); + +// Filter region + +$region_settings = trim((string) elgg_get_plugin_setting('region_list', 'event_manager')); +$region_list = explode(',', $region_settings); +$region_options = array_reduce($region_list, function ($options, $value){ + $options[$value] = [ + 'text' => $value + ]; + return $options; +}, []); +echo elgg_view_field([ + '#type' => 'select', + '#label' => elgg_echo('event_manager:ical_direct:export:region'), + '#help' => elgg_echo('event_manager:ical_direct:export:region:help'), + 'required' => false, + 'multiple' => true, + 'name' => 'region', + 'options_values' => $region_options, +]); + +// Filter type + +$type_settings = trim((string) elgg_get_plugin_setting('type_list', 'event_manager')); +$type_list = explode(',', $type_settings); +$type_options = array_reduce($type_list, function ($options, $value){ + $options[$value] = [ + 'text' => $value + ]; + return $options; +}, []); +echo elgg_view_field([ + '#type' => 'select', + '#label' => elgg_echo('event_manager:ical_direct:export:type'), + '#help' => elgg_echo('event_manager:ical_direct:export:type:help'), + 'required' => false, + 'multiple' => true, + 'name' => 'event_type', + 'options_values' => $type_options, +]); + +elgg_set_form_footer( + elgg_view_field([ + '#type' => 'submit', + 'text' => elgg_echo('event_manager:ical_direct:export:submit'), + ]) +); diff --git a/views/default/forms/event_manager/icalFormTool.mjs b/views/default/forms/event_manager/icalFormTool.mjs new file mode 100644 index 00000000..044a3935 --- /dev/null +++ b/views/default/forms/event_manager/icalFormTool.mjs @@ -0,0 +1,28 @@ +import 'jquery'; + +function toggle($type) { + const $calendar_object = $('select[name="calendar_type"]') + const $form = $calendar_object.closest('form'); + if (!$form.length) { + return; + } + + if ($calendar_object[0].value === $type) { + $(`[name="${$type}"]`, $form).each(function() { + $(this).prop('required', true); + $(this).closest('.elgg-field').removeClass('hidden'); + }); + + } else { + $(`[name="${$type}"]`, $form).each(function() { + $(this).prop('required', false); + $(this).closest('.elgg-field').addClass('hidden'); + }); + } +} + +$(document).on('change', 'select[name="calendar_type"]', function() { + toggle('owner'); + toggle('group'); +}); + diff --git a/views/default/forms/event_manager/import/ical.php b/views/default/forms/event_manager/import/ical.php new file mode 100644 index 00000000..2118efa8 --- /dev/null +++ b/views/default/forms/event_manager/import/ical.php @@ -0,0 +1,89 @@ + [ + 'text' => elgg_echo('event_manager:ical_direct:calendar_type:all'), + 'selected' => $calendar_type_selected == 'all', + 'value' => 'all', + ], + 'group' => [ + 'text' => elgg_echo('event_manager:ical_direct:calendar_type:group'), + 'selected' => $calendar_type_selected == 'group', + 'value' => 'group', + ], + 'owner' => [ + 'text' => elgg_echo('event_manager:ical_direct:calendar_type:owner'), + 'selected' => $calendar_type_selected == 'owner', + 'value' => 'owner', + ], +]; + +echo elgg_view_field([ + '#type' => 'select', + '#label' => elgg_echo('event_manager:ical_direct:import:calendar_type'), + '#help' => elgg_echo('event_manager:ical_direct:import:calendar_type:help'), + 'required' => true, + 'name' => 'calendar_type', + 'options_values' => $calendar_type_options, +]); + +$owner = ''; + +if (array_key_exists('username', $route_parameters)) { + $owner = elgg_get_user_by_username($route_parameters['username'])->getGUID(); +} + +echo elgg_view_field([ + '#type' => 'userpicker', + '#label' => elgg_echo('event_manager:ical_direct:import:owner'), + '#help' => elgg_echo('event_manager:ical_direct:import:owner:help'), + 'required' => true, + 'name' => 'owner', + 'limit' => 1, + 'values' => [$owner], + '#class' => $calendar_type_selected != 'owner' ? ['hidden'] : [], +]); + + +$group = ''; + +if (array_key_exists('guid', $route_parameters)) { + $group = $route_parameters['guid']; +} + +echo elgg_view_field([ + '#type' => 'grouppicker', + '#label' => elgg_echo('event_manager:ical_direct:import:group'), + '#help' => elgg_echo('event_manager:ical_direct:import:group:help'), + 'required' => true, + 'name' => 'group', + 'limit' => 1, + 'values' => [$group], + '#class' => $calendar_type_selected != 'group' ? ['hidden'] : [], +]); + +echo elgg_view_field([ + '#type' => 'file', + '#label' => elgg_echo('event_manager:ical_direct:import:file'), + '#help' => elgg_echo('event_manager:ical_direct:import:file:help'), + 'name' => 'import' +]); + +elgg_set_form_footer( + elgg_view_field([ + '#type' => 'submit', + 'text' => elgg_echo('event_manager:ical_direct:import:submit'), + ]) +); diff --git a/views/default/plugins/event_manager/settings.php b/views/default/plugins/event_manager/settings.php index 59be23cf..5dfd448b 100644 --- a/views/default/plugins/event_manager/settings.php +++ b/views/default/plugins/event_manager/settings.php @@ -75,6 +75,17 @@ echo elgg_view_module('info', elgg_echo('event_manager:settings:maps'), $maps); +// iCal direct features +$ical_direct = elgg_view_field([ + '#type' => 'switch', + '#label' => elgg_echo('event_manager:settings:ical_direct:enable'), + '#help' => elgg_echo('event_manager:settings:ical_direct:enable:help'), + 'name' => 'params[ical_direct]', + 'value' => $plugin->ical_direct, +]); + +echo elgg_view_module('info', elgg_echo('event_manager:settings:ical_direct'), $ical_direct); + // AddEvent options $add_event = elgg_view_field([ '#type' => 'select',