From 2c90ab69d648912407f580bd7203eec3651271da Mon Sep 17 00:00:00 2001 From: Philipp Date: Tue, 1 Nov 2022 00:01:37 +0100 Subject: [PATCH] Move event export to src/Module/Events/Export --- mod/cal.php | 44 ------------- src/Model/Event.php | 7 +- src/Module/Events/Export.php | 109 +++++++++++++++++++++++++++++++ static/routes.config.php | 3 +- view/templates/widget/events.tpl | 4 +- 5 files changed, 116 insertions(+), 51 deletions(-) create mode 100644 src/Module/Events/Export.php diff --git a/mod/cal.php b/mod/cal.php index 4c22232d27..d5b0487a4a 100644 --- a/mod/cal.php +++ b/mod/cal.php @@ -34,7 +34,6 @@ use Friendica\Model\Event; use Friendica\Model\Item; use Friendica\Model\User; use Friendica\Module\BaseProfile; -use Friendica\Module\Response; use Friendica\Network\HTTPException; use Friendica\Util\DateTimeFormat; use Friendica\Util\Temporal; @@ -101,15 +100,8 @@ function cal_content(App $a) $m = 0; $ignored = (!empty($_REQUEST['ignored']) ? intval($_REQUEST['ignored']) : 0); - $format = 'ical'; - if (DI::args()->getArgc() == 4 && DI::args()->getArgv()[2] == 'export') { - $mode = 'export'; - $format = DI::args()->getArgv()[3]; - } - // Setup permissions structures $owner_uid = intval($owner['uid']); - $nick = $owner['nickname']; $contact_id = DI::userSession()->getRemoteContactID($owner['uid']); @@ -258,40 +250,4 @@ function cal_content(App $a) return $o; } - - if ($mode == 'export') { - if (!$owner_uid) { - DI::sysmsg()->addNotice(DI::l10n()->t('User not found')); - return; - } - - // Get the export data by uid - $evexport = Event::exportListByUserId($owner_uid, $format); - - if (!$evexport["success"]) { - if ($evexport["content"]) { - DI::sysmsg()->addNotice(DI::l10n()->t('This calendar format is not supported')); - } else { - DI::sysmsg()->addNotice(DI::l10n()->t('No exportable data found')); - } - - // If it the own calendar return to the events page - // otherwise to the profile calendar page - if (DI::userSession()->getLocalUserId() === $owner_uid) { - $return_path = "events"; - } else { - $return_path = "cal/" . $nick; - } - - DI::baseUrl()->redirect($return_path); - } - - // If nothing went wrong we can echo the export content - if ($evexport["success"]) { - header('content-disposition: attachment; filename="' . DI::l10n()->t('calendar') . '-' . $nick . '.' . $evexport["extension"] . '"'); - System::httpExit($evexport["content"], Response::TYPE_BLANK, 'text/calendar'); - } - - return; - } } diff --git a/src/Model/Event.php b/src/Model/Event.php index a738428eaa..9a75152724 100644 --- a/src/Model/Event.php +++ b/src/Model/Event.php @@ -670,7 +670,6 @@ class Event switch ($format) { // Format the exported data as a CSV file. case "csv": - header("Content-type: text/csv"); $o .= '"Subject", "Start Date", "Start Time", "Description", "End Date", "End Time", "Location"' . PHP_EOL; foreach ($events as $event) { @@ -691,7 +690,6 @@ class Event // Format the exported data as a ics file. case "ical": - header("Content-type: text/ics"); $o = 'BEGIN:VCALENDAR' . PHP_EOL . 'VERSION:2.0' . PHP_EOL . 'PRODID:-//friendica calendar export//0.1//EN' . PHP_EOL; @@ -705,6 +703,8 @@ class Event // also long lines SHOULD be split at 75 characters length foreach ($events as $event) { $o .= 'BEGIN:VEVENT' . PHP_EOL; + $o .= 'UID:' . $event['id'] . PHP_EOL; + $o .= 'DTSTAMP:' . DateTimeFormat::utc($event['created'], 'Ymd\THis\Z') . PHP_EOL; if ($event['start']) { $o .= 'DTSTART:' . DateTimeFormat::utc($event['start'], 'Ymd\THis\Z') . PHP_EOL; @@ -736,7 +736,6 @@ class Event } $o .= 'END:VEVENT' . PHP_EOL; - $o .= PHP_EOL; } $o .= 'END:VCALENDAR' . PHP_EOL; @@ -768,7 +767,7 @@ class Event return $return; } - $fields = ['start', 'finish', 'summary', 'desc', 'location', 'nofinish']; + $fields = ['id', 'created', 'start', 'finish', 'summary', 'desc', 'location', 'nofinish']; $conditions = ['uid' => $uid, 'cid' => 0]; diff --git a/src/Module/Events/Export.php b/src/Module/Events/Export.php new file mode 100644 index 0000000000..fef3ed8bed --- /dev/null +++ b/src/Module/Events/Export.php @@ -0,0 +1,109 @@ +. + * + */ + +namespace Friendica\Module\Events; + +use Friendica\App; +use Friendica\BaseModule; +use Friendica\Core\L10n; +use Friendica\Core\Session\Capability\IHandleUserSessions; +use Friendica\Model\Event; +use Friendica\Model\User; +use Friendica\Module\Response; +use Friendica\Navigation\SystemMessages; +use Friendica\Network\HTTPException; +use Friendica\Util\Profiler; +use Psr\Log\LoggerInterface; + +/** + * Controller to export calendar + */ +class Export extends BaseModule +{ + const EXPORT_ICAL = 'ical'; + const EXPORT_CSV = 'csv'; + + const DEFAULT_EXPORT = self::EXPORT_ICAL; + + /** @var IHandleUserSessions */ + protected $session; + /** @var SystemMessages */ + protected $sysMessages; + + public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, IHandleUserSessions $session, SystemMessages $sysMessages, array $server, array $parameters = []) + { + parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); + + $this->session = $session; + $this->sysMessages = $sysMessages; + } + + protected function rawContent(array $request = []) + { + $owner = User::getByNickname($this->parameters['nickname'], ['uid']); + if (empty($owner)) { + throw new HTTPException\NotFoundException($this->t('User not found.')); + } + $ownerUid = $owner['uid']; + $format = $this->parameters['format'] ?: static::DEFAULT_EXPORT; + + // Get the export data by uid + $evexport = Event::exportListByUserId($ownerUid, $format); + + if (!$evexport["success"]) { + if ($evexport["content"]) { + $this->sysMessages->addNotice($this->t('This calendar format is not supported')); + } else { + $this->sysMessages->addNotice($this->t('No exportable data found')); + } + + // If it is the own calendar return to the events page + // otherwise to the profile calendar page + if ($this->session->getLocalUserId() === $ownerUid) { + $returnPath = 'events'; + } else { + $returnPath = 'events/' . $this->parameters['nickname']; + } + + $this->baseUrl->redirect($returnPath); + } + + // If nothing went wrong we can echo the export content + if ($evexport["success"]) { + $this->response->setHeader(sprintf('content-disposition: attachment; filename="%s-%s.%s"', + $this->t('calendar'), + $this->parameters['nickname'], + $evexport["extension"] + )); + + switch ($format) { + case static::EXPORT_ICAL: + $this->response->setType(Response::TYPE_BLANK, 'text/ics'); + break; + case static::EXPORT_CSV: + $this->response->setType(Response::TYPE_BLANK, 'text/csv'); + break; + } + + $this->response->addContent($evexport['content']); + } + } +} diff --git a/static/routes.config.php b/static/routes.config.php index 6f05faee2d..e344de75cc 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -398,7 +398,8 @@ return [ '/dirfind' => [Module\Search\Directory::class, [R::GET]], '/directory' => [Module\Directory::class, [R::GET]], - '/events/json' => [Module\Events\Json::class, [R::GET]], + '/events/{nickname}/export[/{format}]' => [Module\Events\Export::class, [R::GET]], + '/events/json' => [Module\Events\Json::class, [R::GET]], '/featured/{nickname}' => [Module\ActivityPub\Featured::class, [R::GET]], diff --git a/view/templates/widget/events.tpl b/view/templates/widget/events.tpl index 81dde70463..c83542778e 100644 --- a/view/templates/widget/events.tpl +++ b/view/templates/widget/events.tpl @@ -3,7 +3,7 @@

{{$etitle}}