getApp() !== Application::APP_ID) { throw new UnknownNotificationException(); } $notification->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath(Application::APP_ID, 'app-dark.svg'))); $params = $notification->getSubjectParameters(); switch ($notification->getSubject()) { case NotificationPusher::SUBJECT_CARD_MOVED: $this->prepareCardMoved($notification, $params); return $notification; case NotificationPusher::SUBJECT_WORKFLOW_DISABLED: $this->prepareWorkflowDisabled($notification, $params); return $notification; default: throw new UnknownNotificationException(); } } private function prepareCardMoved(INotification $notification, array $params): void { $cardId = $notification->getObjectId(); $boardId = (string)($params['boardId'] ?? ''); $boardTitle = (string)($params['boardTitle'] ?? ''); $targetStackTitle = (string)($params['targetStackTitle'] ?? ''); $cardUrl = $this->urlGenerator->getAbsoluteURL('/apps/deck/board/' . $boardId . '/card/' . $cardId); // Every title is user input and goes in as a rich object, never into // the template itself — a title containing "{…}" would otherwise be // read as a placeholder. $objects = [ 'deck-card' => [ 'type' => 'deck-card', 'id' => $cardId, 'name' => (string)($params['cardTitle'] ?? ''), 'boardname' => $boardTitle, 'stackname' => $targetStackTitle, 'link' => $cardUrl, ], 'deck-board' => [ 'type' => 'deck-board', 'id' => $boardId, 'name' => $boardTitle, 'link' => $this->urlGenerator->getAbsoluteURL('/apps/deck/board/' . $boardId), ], 'source-stack' => [ 'type' => 'highlight', 'id' => (string)($params['sourceStackId'] ?? ''), 'name' => (string)($params['sourceStackTitle'] ?? ''), ], 'target-stack' => [ 'type' => 'highlight', 'id' => (string)($params['targetStackId'] ?? ''), 'name' => $targetStackTitle, ], ]; $notification->setLink($cardUrl); self::setText( $notification, '{deck-card} wurde nach {target-stack} verschoben', sprintf( 'Die Karte auf {deck-board} %s und wurde automatisch von {source-stack} nach {target-stack} verschoben.', // Missing on notifications from before the start date existed, // which were all about due dates. TriggerDate::describeReason((string)($params['triggerDate'] ?? TriggerDate::DUE)), ), $objects, ); } private function prepareWorkflowDisabled(INotification $notification, array $params): void { $settingsUrl = $this->urlGenerator->getAbsoluteURL('/settings/user/' . Application::APP_ID); $objects = [ 'workflow' => [ 'type' => 'highlight', 'id' => $notification->getObjectId(), 'name' => (string)($params['workflowTitle'] ?? ''), 'link' => $settingsUrl, ], ]; $notification->setLink($settingsUrl); self::setText( $notification, 'Workflow {workflow} wurde deaktiviert', sprintf( 'Er wurde automatisch ausgeschaltet, weil %s, und verschiebt keine Karten mehr. Lösche ihn oder stelle ein vorhandenes Board und vorhandene Stapel ein, um ihn wieder zu aktivieren.', NotificationMailer::describeBrokenTarget((string)($params['brokenTarget'] ?? '')), ), $objects, ); } /** * Sets the rich texts and their plain fallback (used by clients without * rich text support), with titles in German quotes there. * * @param array $objects */ private static function setText(INotification $notification, string $subject, string $message, array $objects): void { $plain = []; foreach ($objects as $key => $object) { $plain['{' . $key . '}'] = '„' . $object['name'] . '“'; } // strtr() replaces in a single pass, so a title that itself contains // a placeholder is left as it is. $notification->setParsedSubject(strtr($subject, $plain)) ->setRichSubject($subject, $objects) ->setParsedMessage(strtr($message, $plain)) ->setRichMessage($message, $objects); } }