3 * @copyright Copyright (C) 2010-2023, the Friendica project
5 * @license GNU AGPL version 3 or any later version
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 namespace Friendica\Module\Calendar\Event;
25 use Friendica\BaseModule;
26 use Friendica\Content\Widget\CalendarExport;
27 use Friendica\Core\ACL;
28 use Friendica\Core\L10n;
29 use Friendica\Core\Renderer;
30 use Friendica\Core\Session\Capability\IHandleUserSessions;
31 use Friendica\Model\Event as EventModel;
32 use Friendica\Model\User;
33 use Friendica\Module\Response;
34 use Friendica\Module\Security\Login;
35 use Friendica\Navigation\SystemMessages;
36 use Friendica\Network\HTTPException\BadRequestException;
37 use Friendica\Util\ACLFormatter;
38 use Friendica\Util\DateTimeFormat;
39 use Friendica\Util\Profiler;
40 use Friendica\Util\Temporal;
41 use Psr\Log\LoggerInterface;
44 * The editor-view of an event
46 class Form extends BaseModule
48 const MODE_NEW = 'new';
49 const MODE_EDIT = 'edit';
50 const MODE_COPY = 'copy';
52 const ALLOWED_MODES = [
58 /** @var IHandleUserSessions */
60 /** @var SystemMessages */
61 protected $sysMessages;
62 /** @var ACLFormatter */
63 protected $aclFormatter;
67 public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, IHandleUserSessions $session, SystemMessages $sysMessages, ACLFormatter $aclFormatter, App\Page $page, array $server, array $parameters = [])
69 parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
71 $this->session = $session;
72 $this->sysMessages = $sysMessages;
73 $this->aclFormatter = $aclFormatter;
77 protected function content(array $request = []): string
79 if (empty($this->parameters['mode']) || !in_array($this->parameters['mode'], self::ALLOWED_MODES)) {
80 throw new BadRequestException($this->t('Invalid Request'));
83 if (!$this->session->getLocalUserId()) {
84 $this->sysMessages->addNotice($this->t('Permission denied.'));
88 $mode = $this->parameters['mode'];
90 if (($mode === self::MODE_EDIT || $mode === self::MODE_COPY)) {
91 if (empty($this->parameters['id'])) {
92 throw new BadRequestException('Invalid Request');
94 $orig_event = EventModel::getByIdAndUid($this->session->getLocalUserId(), $this->parameters['id']);
95 if (empty($orig_event)) {
96 throw new BadRequestException('Invalid Request');
100 if ($mode === self::MODE_NEW) {
101 $this->session->set('return_path', $this->args->getCommand());
104 // get the translation strings for the calendar
105 $i18n = EventModel::getStrings();
107 $this->page->registerStylesheet('view/asset/fullcalendar/dist/fullcalendar.min.css');
108 $this->page->registerStylesheet('view/asset/fullcalendar/dist/fullcalendar.print.min.css', 'print');
109 $this->page->registerFooterScript('view/asset/moment/min/moment-with-locales.min.js');
110 $this->page->registerFooterScript('view/asset/fullcalendar/dist/fullcalendar.min.js');
112 $htpl = Renderer::getMarkupTemplate('calendar/calendar_head.tpl');
114 $this->page['htmlhead'] .= Renderer::replaceMacros($htpl, [
115 '$calendar_api' => $this->baseUrl . '/calendar/api/get',
116 '$event_api' => $this->baseUrl . '/calendar/event/show',
122 $share_disabled = '';
124 if (empty($orig_event)) {
125 $orig_event = User::getById($this->session->getLocalUserId(),
126 ['allow_cid', 'allow_gid', 'deny_cid', 'deny_gid']);
127 } elseif ($orig_event['allow_cid'] !== '<' . $this->session->getLocalUserId() . '>'
128 || $orig_event['allow_gid']
129 || $orig_event['deny_cid']
130 || $orig_event['deny_gid']) {
131 $share_checked = ' checked="checked" ';
134 // In case of an error the browser is redirected back here, with these parameters filled in with the previous values
135 if (!empty($request['nofinish'])) {
136 $orig_event['nofinish'] = $request['nofinish'];
138 if (!empty($request['summary'])) {
139 $orig_event['summary'] = $request['summary'];
141 if (!empty($request['desc'])) {
142 $orig_event['desc'] = $request['desc'];
144 if (!empty($request['location'])) {
145 $orig_event['location'] = $request['location'];
147 if (!empty($request['start'])) {
148 $orig_event['start'] = $request['start'];
150 if (!empty($request['finish'])) {
151 $orig_event['finish'] = $request['finish'];
154 $n_checked = (!empty($orig_event['nofinish']) ? ' checked="checked" ' : '');
156 $t_orig = $orig_event['summary'] ?? '';
157 $d_orig = $orig_event['desc'] ?? '';
158 $l_orig = $orig_event['location'] ?? '';
159 $eid = $orig_event['id'] ?? 0;
160 $cid = $orig_event['cid'] ?? 0;
161 $uri = $orig_event['uri'] ?? '';
163 if ($cid || $mode === 'edit') {
164 $share_disabled = 'disabled="disabled"';
167 $sdt = $orig_event['start'] ?? 'now';
168 $fdt = $orig_event['finish'] ?? 'now';
170 $syear = DateTimeFormat::local($sdt, 'Y');
171 $smonth = DateTimeFormat::local($sdt, 'm');
172 $sday = DateTimeFormat::local($sdt, 'd');
174 $shour = !empty($orig_event) ? DateTimeFormat::local($sdt, 'H') : '00';
175 $sminute = !empty($orig_event) ? DateTimeFormat::local($sdt, 'i') : '00';
177 $fyear = DateTimeFormat::local($fdt, 'Y');
178 $fmonth = DateTimeFormat::local($fdt, 'm');
179 $fday = DateTimeFormat::local($fdt, 'd');
181 $fhour = !empty($orig_event) ? DateTimeFormat::local($fdt, 'H') : '00';
182 $fminute = !empty($orig_event) ? DateTimeFormat::local($fdt, 'i') : '00';
184 if (!$cid && in_array($mode, [self::MODE_NEW, self::MODE_COPY])) {
185 $acl = ACL::getFullSelectorHTML($this->page, $this->session->getLocalUserId(), false, ACL::getDefaultUserPermissions($orig_event));
190 // If we copy an old event, we need to remove the ID and URI
191 // from the original event.
192 if ($mode === self::MODE_COPY) {
197 $this->page['aside'] .= CalendarExport::getHTML($this->session->getLocalUserId());
199 $tpl = Renderer::getMarkupTemplate('calendar/event_form.tpl');
201 return Renderer::replaceMacros($tpl, [
202 '$post' => 'calendar/api/create',
207 '$title' => $this->t('Event details'),
208 '$desc' => $this->t('Starting date and Title are required.'),
209 '$s_text' => $this->t('Event Starts:') . ' <span class="required" title="' . $this->t('Required') . '">*</span>',
210 '$s_dsel' => Temporal::getDateTimeField(
212 \DateTime::createFromFormat('Y', intval($syear) + 5),
213 \DateTime::createFromFormat('Y-m-d H:i', "$syear-$smonth-$sday $shour:$sminute"),
214 $this->t('Event Starts:'),
223 '$n_text' => $this->t('Finish date/time is not known or not relevant'),
224 '$n_checked' => $n_checked,
225 '$f_text' => $this->t('Event Finishes:'),
226 '$f_dsel' => Temporal::getDateTimeField(
228 \DateTime::createFromFormat('Y', intval($fyear) + 5),
229 \DateTime::createFromFormat('Y-m-d H:i', "$fyear-$fmonth-$fday $fhour:$fminute"),
230 $this->t('Event Finishes:'),
237 '$t_text' => $this->t('Title (BBCode not allowed)') . ' <span class="required" title="' . $this->t('Required') . '">*</span>',
238 '$t_orig' => $t_orig,
239 '$d_text' => $this->t('Description (BBCode allowed)'),
240 '$d_orig' => $d_orig,
241 '$l_text' => $this->t('Location (BBCode not allowed)'),
242 '$l_orig' => $l_orig,
243 '$summary' => ['summary', $this->t('Title (BBCode not allowed)'), $t_orig, '', '*'],
244 '$sh_text' => $this->t('Share this event'),
245 '$share' => ['share', $this->t('Share this event'), $share_checked, '', $share_disabled],
246 '$sh_checked' => $share_checked,
247 '$nofinish' => ['nofinish', $this->t('Finish date/time is not known or not relevant'), $n_checked],
248 '$preview' => $this->t('Preview'),
250 '$submit' => $this->t('Submit'),
251 '$basic' => $this->t('Basic'),
252 '$advanced' => $this->t('Advanced'),
253 '$permissions' => $this->t('Permissions'),