ILIAS  trunk Revision v12.0_alpha-377-g3641b37b9db
class.ilPersonalNotificationsSettingsGUI.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
31
36{
37 protected Container $dic;
40 protected array $pushProvider;
41
42 public function __construct(?Container $dic = null)
43 {
44 if ($dic === null) {
45 global $DIC;
46 $dic = $DIC;
47 }
48 $this->dic = $dic;
49 $this->repo = new PushRepository($this->dic->database(), $this->dic->user());
50 $provider = [];
51 foreach (require PushNotificationObjective::PATH() as $class) {
52 $provider[] = new $class();
53 }
54 $this->pushProvider = $provider;
55 }
56
57 public function executeCommand(): void
58 {
59 if ((new ilSetting('notifications'))->get('enable_push') !== '1') {
60 $this->dic->ui()->mainTemplate()->setOnScreenMessage(
61 $this->dic->ui()->mainTemplate()::MESSAGE_TYPE_FAILURE,
62 $this->dic->language()->txt('permission_denied')
63 );
64 $this->dic->ui()->mainTemplate()->printToStdout();
65 return;
66 }
67
68 $this->dic->language()->loadLanguageModule('notifications_adm');
69 $this->dic->ui()->mainTemplate()->setTitle($this->dic->language()->txt('push_settings'));
70 $this->dic->ui()->mainTemplate()->setTitleIcon(ilUtil::getImagePath('standard/icon_nota.svg'));
71 $this->dic->tabs()->addTab('client', $this->dic->language()->txt('client_settings'), $this->dic->ctrl()->getLinkTargetByClass(self::class, 'showClientSettings'));
72 if ($this->pushProvider !== []) {
73 $this->dic->tabs()->addTab('user', $this->dic->language()->txt('user_settings'), $this->dic->ctrl()->getLinkTargetByClass(self::class, 'showUserSettings'));
74 }
75
76 switch ($this->dic->ctrl()->getCmd()) {
77 case 'showUserSettings':
78 $this->dic->tabs()->activateTab('user');
79 if ($this->pushProvider !== []) {
80 $this->dic->ui()->mainTemplate()->setContent($this->dic->ui()->renderer()->render($this->getForm()));
81 $this->dic->ui()->mainTemplate()->printToStdout();
82 } else {
83 $this->dic->ctrl()->redirectByClass(self::class, 'showClientSettings');
84 }
85 break;
86 case 'saveUserSettings':
87 $this->dic->tabs()->activateTab('user');
88 $form = $this->getForm()->withRequest($this->dic->http()->request());
89 $data = $form->getData();
90 if ($data !== null) {
91 $active = [];
92 foreach ($data['provider'] ?? [] as $key => $value) {
93 if ($value === true) {
94 $active[] = $key;
95 }
96 }
97 $this->dic->user()->setPref('push_notification_provider', json_encode($active));
98 $this->dic->user()->update();
99 $this->dic->ui()->mainTemplate()->setOnScreenMessage(
100 $this->dic->ui()->mainTemplate()::MESSAGE_TYPE_SUCCESS,
101 $this->dic->language()->txt('saved_successfully')
102 );
103 }
104 $this->dic->ui()->mainTemplate()->setContent($this->dic->ui()->renderer()->render($form));
105 $this->dic->ui()->mainTemplate()->printToStdout();
106 break;
107 case 'addSubscription':
108 $this->addSubscription();
109 break;
110 case 'removeSubscription':
111 $this->removeSubscription();
112 break;
113 case 'showClientSettings':
114 default:
115 $this->dic->tabs()->activateTab('client');
116 if (!($this->dic->http()->wrapper()->post()->has('auth') && $this->dic->http()->wrapper()->post()->has('perm'))) {
117 $this->fetchClientData();
118 }
119 $this->showClientSettings();
120 }
121 }
122
123 protected function checkSubscription(string $auth): bool
124 {
125 if ($auth === '') {
126 return true;
127 }
128 foreach ($this->repo->getUserSubscriptions() as $subscription) {
129 if ($auth === $subscription->getAuth()) {
130 return true;
131 }
132 }
133
134 return false;
135 }
136
137 protected function addSubscription(): void
138 {
139 $data = json_decode(
140 $this->dic->http()->wrapper()->post()->retrieve('subscription', $this->dic->refinery()->to()->string()),
141 true,
142 512,
143 JSON_THROW_ON_ERROR
144 );
145 if (!$this->checkSubscription($data['keys']['auth'])) {
146 $this->repo->addSubscription(new PushSubscription(
147 $data['endpoint'],
148 $data['keys']['auth'],
149 $data['keys']['p256dh']
150 ));
151 }
152
154 $this->dic->user(),
155 $this->dic->language()->txt('push_subscription_successfull'),
156 $this->dic->language()->txt('push_subscription_successfull_desc')
157 );
158 }
159
160 protected function removeSubscription(): void
161 {
162 $auth = $this->dic->http()->wrapper()->post()->retrieve('auth', $this->dic->refinery()->to()->string());
163 if ($this->checkSubscription($auth)) {
164 $this->repo->deleteSubscription($auth);
165 }
166 }
167
168 protected function showClientSettings(): void
169 {
170 $this->dic->ui()->mainTemplate()->addJavaScript('assets/js/push-subscription.js');
171
172 $auth = $this->dic->http()->wrapper()->post()->retrieve('auth', $this->dic->refinery()->kindlyTo()->string());
173 $perm = $this->dic->http()->wrapper()->post()->retrieve('perm', $this->dic->refinery()->kindlyTo()->string());
174 $agent = $this->dic->http()->request()->getServerParams()['HTTP_USER_AGENT'] ?? '';
175
176 if ($perm === 'denied') {
177 $this->dic->ui()->mainTemplate()->setOnScreenMessage(
178 $this->dic->ui()->mainTemplate()::MESSAGE_TYPE_QUESTION,
179 $this->dic->language()->txt('push_client_inactive')
180 );
181 }
182 if (!$this->checkSubscription($auth)) {
183 $this->dic->ui()->mainTemplate()->setOnScreenMessage(
184 $this->dic->ui()->mainTemplate()::MESSAGE_TYPE_FAILURE,
185 $this->dic->language()->txt('push_client_already_used')
186 );
187 }
188 if ($perm !== 'granted' && preg_match('/(Edg\/)/', $agent)) {
189 $this->dic->ui()->mainTemplate()->setOnScreenMessage(
190 $this->dic->ui()->mainTemplate()::MESSAGE_TYPE_INFO,
191 $this->dic->language()->txt('push_client_edge_case')
192 );
193 }
194 if ($perm === '' && preg_match('/(Mac)/', $agent)) {
195 $this->dic->ui()->mainTemplate()->setOnScreenMessage(
196 $this->dic->ui()->mainTemplate()::MESSAGE_TYPE_INFO,
197 $this->dic->language()->txt('push_client_ios_case')
198 );
199 }
200
201 if ($this->checkSubscription($auth) && ($perm === 'granted' || $perm === 'default')) {
202 $public_key = (new ilSetting('notifications'))->get('application_server_key');
203 $target = $this->dic->ctrl()->getLinkTargetByClass(self::class, 'default');
204 $toggle = $this->dic->ui()->factory()->button()->toggle($this->dic->language()->txt('activate'), '', '')
205 ->withEngagedState($auth !== '')
206 ->withAdditionalOnLoadCode(static fn($id) => "il.Notifications.initToggle($id, '$public_key', '$target')");
207 $this->dic->ui()->mainTemplate()->setContent($this->dic->ui()->renderer()->render($toggle));
208 }
209
210 $this->dic->ui()->mainTemplate()->printToStdout();
211 }
212
216 protected function fetchClientData(): never
217 {
218 $target = ILIAS_HTTP_PATH . '/' . $this->dic->ctrl()->getLinkTargetByClass(self::class, 'showClientSettings');
219
220 $this->dic->ui()->mainTemplate()->setContent($this->dic->ui()->renderer()->render(
221 $this->dic->ui()->factory()->legacy()->content('')->withOnLoadCode(
222 static fn($id) => "
223 navigator.serviceWorker.ready.then((reg) => {
224 (reg.pushManager || {getSubscription: () => Promise.resolve(null)}).getSubscription().then((sub) => {
225 const form = document.createElement('form');
226 form.method = 'post';
227 form.action = '$target';
228 let auth = document.createElement('input');
229 auth.name = 'auth';
230 auth.value = (sub === null) ? '' : sub.toJSON().keys.auth;
231 form.appendChild(auth);
232 perm = document.createElement('input');
233 perm.name = 'perm';
234 perm.value = (typeof Notification === 'undefined') ? '' : Notification.permission;
235 form.appendChild(perm);
236 document.body.appendChild(form);
237 form.submit();
238 })
239 });
240 "
241 )
242 ));
243 $this->dic->ui()->mainTemplate()->printToStdout();
244 $this->dic->http()->close();
245 }
246
247 public function getForm(): Form
248 {
249 $provider = [];
250 $prefs = json_decode($this->dic->user()->getPref('push_notification_provider') ?? '[]');
251 foreach ($this->pushProvider as $p) {
252 $provider[$p->getIdentifier()] = $this->dic->ui()->factory()->input()->field()->checkbox(
253 $p->getName($this->dic->language()),
254 $p->getDescription($this->dic->language()),
255 )->withValue(in_array($p->getIdentifier(), $prefs));
256 }
257
258 return $this->dic->ui()->factory()->input()->container()->form()->standard(
259 $this->dic->ctrl()->getLinkTargetByClass(self::class, 'saveUserSettings'),
260 [
261 'provider' => $this->dic->ui()->factory()->input()->field()->section(
262 $provider,
263 $this->dic->language()->txt('available_providers'),
264 )
265 ]
266 );
267 }
268}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
Customizing of pimple-DIC for ILIAS.
Definition: Container.php:36
This is the lowest common denominator of all popular browsers.
@ilCtrl_IsCalledBy ilPersonalNotificationsSettingsGUI: ilNotificationGUI
fetchClientData()
Respond a self-submitting form to fetch client data for push notifications.
ILIAS Setting Class.
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
This describes commonalities between all forms.
Definition: Form.php:34
$provider
Definition: ltitoken.php:80
global $DIC
Definition: shib_login.php:26