3 <html lang=
"en" class=
"no-js">
7 <meta name=
"viewport" content=
"width=device-width,initial-scale=1">
12 <link rel=
"shortcut icon" href=
"../../../assets/default.favicon.ico">
13 <meta name=
"generator" content=
"mkdocs-1.1.2, mkdocs-material-7.0.5">
17 <title>User Notifications - WoltLab Suite Documentation
</title>
21 <link rel=
"stylesheet" href=
"../../../assets/stylesheets/main.77f3fd56.min.css">
24 <link rel=
"stylesheet" href=
"../../../assets/stylesheets/palette.7fa14f5b.min.css">
28 <meta name=
"theme-color" content=
"#009485">
37 <link rel=
"stylesheet" href=
"../../../stylesheets/extra.css">
51 <body dir=
"ltr" data-md-color-scheme=
"" data-md-color-primary=
"teal" data-md-color-accent=
"">
55 <input class=
"md-toggle" data-md-toggle=
"drawer" type=
"checkbox" id=
"__drawer" autocomplete=
"off">
56 <input class=
"md-toggle" data-md-toggle=
"search" type=
"checkbox" id=
"__search" autocomplete=
"off">
57 <label class=
"md-overlay" for=
"__drawer"></label>
58 <div data-md-component=
"skip">
61 <a href=
"#user-notifications" class=
"md-skip">
66 <div data-md-component=
"announce">
68 <aside class=
"md-announce">
69 <div class=
"md-announce__inner md-grid md-typeset">
71 <a href=
"https://www.woltlab.com">Back to
<strong>woltlab.com
</strong></a>
80 <header class=
"md-header" data-md-component=
"header">
81 <nav class=
"md-header__inner md-grid" aria-label=
"Header">
82 <a href=
"../../.." title=
"WoltLab Suite Documentation" class=
"md-header__button md-logo" aria-label=
"WoltLab Suite Documentation">
84 <img src=
"../../../assets/logo.png" alt=
"logo">
87 <label class=
"md-header__button md-icon" for=
"__drawer">
88 <svg xmlns=
"http://www.w3.org/2000/svg" viewBox=
"0 0 24 24"><path d=
"M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2z"/></svg>
90 <div class=
"md-header__title" data-md-component=
"header-title">
91 <div class=
"md-header__ellipsis">
92 <div class=
"md-header__topic">
93 <span class=
"md-ellipsis">
94 WoltLab Suite Documentation
97 <div class=
"md-header__topic" data-md-component=
"header-topic">
98 <span class=
"md-ellipsis">
106 <div class=
"md-header__options">
110 <label class=
"md-header__button md-icon" for=
"__search">
111 <svg xmlns=
"http://www.w3.org/2000/svg" viewBox=
"0 0 24 24"><path d=
"M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z"/></svg>
114 <div class=
"md-search" data-md-component=
"search" role=
"dialog">
115 <label class=
"md-search__overlay" for=
"__search"></label>
116 <div class=
"md-search__inner" role=
"search">
117 <form class=
"md-search__form" name=
"search">
118 <input type=
"text" class=
"md-search__input" name=
"query" aria-label=
"Search" placeholder=
"Search" autocapitalize=
"off" autocorrect=
"off" autocomplete=
"off" spellcheck=
"false" data-md-component=
"search-query" data-md-state=
"active" required
>
119 <label class=
"md-search__icon md-icon" for=
"__search">
120 <svg xmlns=
"http://www.w3.org/2000/svg" viewBox=
"0 0 24 24"><path d=
"M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z"/></svg>
121 <svg xmlns=
"http://www.w3.org/2000/svg" viewBox=
"0 0 24 24"><path d=
"M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"/></svg>
123 <button type=
"reset" class=
"md-search__icon md-icon" aria-label=
"Clear" tabindex=
"-1">
124 <svg xmlns=
"http://www.w3.org/2000/svg" viewBox=
"0 0 24 24"><path d=
"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/></svg>
127 <div class=
"md-search__output">
128 <div class=
"md-search__scrollwrap" data-md-scrollfix
>
129 <div class=
"md-search-result" data-md-component=
"search-result">
130 <div class=
"md-search-result__meta">
133 <ol class=
"md-search-result__list"></ol>
144 <div class=
"md-container" data-md-component=
"container">
149 <main class=
"md-main" data-md-component=
"main">
150 <div class=
"md-main__inner md-grid">
154 <div class=
"md-sidebar md-sidebar--primary" data-md-component=
"sidebar" data-md-type=
"navigation" >
155 <div class=
"md-sidebar__scrollwrap">
156 <div class=
"md-sidebar__inner">
162 <nav class=
"md-nav md-nav--primary" aria-label=
"Navigation" data-md-level=
"0">
163 <label class=
"md-nav__title" for=
"__drawer">
164 <a href=
"../../.." title=
"WoltLab Suite Documentation" class=
"md-nav__button md-logo" aria-label=
"WoltLab Suite Documentation">
166 <img src=
"../../../assets/logo.png" alt=
"logo">
169 WoltLab Suite Documentation
172 <ul class=
"md-nav__list" data-md-scrollfix
>
181 <li class=
"md-nav__item">
182 <a href=
"../../../getting-started/" class=
"md-nav__link">
199 <li class=
"md-nav__item md-nav__item--active md-nav__item--nested">
202 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_2" type=
"checkbox" id=
"__nav_2" checked
>
204 <label class=
"md-nav__link" for=
"__nav_2">
206 <span class=
"md-nav__icon md-icon"></span>
208 <nav class=
"md-nav" aria-label=
"PHP API" data-md-level=
"1">
209 <label class=
"md-nav__title" for=
"__nav_2">
210 <span class=
"md-nav__icon md-icon"></span>
213 <ul class=
"md-nav__list" data-md-scrollfix
>
219 <li class=
"md-nav__item">
220 <a href=
"../../pages/" class=
"md-nav__link">
231 <li class=
"md-nav__item">
232 <a href=
"../../database-objects/" class=
"md-nav__link">
243 <li class=
"md-nav__item">
244 <a href=
"../../database-access/" class=
"md-nav__link">
255 <li class=
"md-nav__item">
256 <a href=
"../../exceptions/" class=
"md-nav__link">
270 <li class=
"md-nav__item md-nav__item--active md-nav__item--nested">
273 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_2_5" type=
"checkbox" id=
"__nav_2_5" checked
>
275 <label class=
"md-nav__link" for=
"__nav_2_5">
277 <span class=
"md-nav__icon md-icon"></span>
279 <nav class=
"md-nav" aria-label=
"API" data-md-level=
"2">
280 <label class=
"md-nav__title" for=
"__nav_2_5">
281 <span class=
"md-nav__icon md-icon"></span>
284 <ul class=
"md-nav__list" data-md-scrollfix
>
290 <li class=
"md-nav__item">
291 <a href=
"../caches/" class=
"md-nav__link">
302 <li class=
"md-nav__item">
303 <a href=
"../comments/" class=
"md-nav__link">
314 <li class=
"md-nav__item">
315 <a href=
"../cronjobs/" class=
"md-nav__link">
326 <li class=
"md-nav__item">
327 <a href=
"../events/" class=
"md-nav__link">
339 <li class=
"md-nav__item md-nav__item--nested">
342 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_2_5_5" type=
"checkbox" id=
"__nav_2_5_5" >
344 <label class=
"md-nav__link" for=
"__nav_2_5_5">
346 <span class=
"md-nav__icon md-icon"></span>
348 <nav class=
"md-nav" aria-label=
"Form Builder" data-md-level=
"3">
349 <label class=
"md-nav__title" for=
"__nav_2_5_5">
350 <span class=
"md-nav__icon md-icon"></span>
353 <ul class=
"md-nav__list" data-md-scrollfix
>
359 <li class=
"md-nav__item">
360 <a href=
"../form_builder/overview/" class=
"md-nav__link">
371 <li class=
"md-nav__item">
372 <a href=
"../form_builder/structure/" class=
"md-nav__link">
383 <li class=
"md-nav__item">
384 <a href=
"../form_builder/form_fields/" class=
"md-nav__link">
395 <li class=
"md-nav__item">
396 <a href=
"../form_builder/validation_data/" class=
"md-nav__link">
407 <li class=
"md-nav__item">
408 <a href=
"../form_builder/dependencies/" class=
"md-nav__link">
425 <li class=
"md-nav__item">
426 <a href=
"../package_installation_plugins/" class=
"md-nav__link">
427 Package Installation Plugins
437 <li class=
"md-nav__item">
438 <a href=
"../user_activity_points/" class=
"md-nav__link">
451 <li class=
"md-nav__item md-nav__item--active">
453 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"toc" type=
"checkbox" id=
"__toc">
458 <label class=
"md-nav__link md-nav__link--active" for=
"__toc">
460 <span class=
"md-nav__icon md-icon"></span>
463 <a href=
"./" class=
"md-nav__link md-nav__link--active">
468 <nav class=
"md-nav md-nav--secondary" aria-label=
"Table of contents">
474 <label class=
"md-nav__title" for=
"__toc">
475 <span class=
"md-nav__icon md-icon"></span>
478 <ul class=
"md-nav__list" data-md-component=
"toc" data-md-scrollfix
>
480 <li class=
"md-nav__item">
481 <a href=
"#objecttypexml" class=
"md-nav__link">
487 <li class=
"md-nav__item">
488 <a href=
"#usernotificationeventxml" class=
"md-nav__link">
489 userNotificationEvent.xml
494 <li class=
"md-nav__item">
495 <a href=
"#firing-events" class=
"md-nav__link">
501 <li class=
"md-nav__item">
502 <a href=
"#marking-notifications-as-confirmed" class=
"md-nav__link">
503 Marking Notifications as Confirmed
520 <li class=
"md-nav__item">
521 <a href=
"../sitemaps/" class=
"md-nav__link">
538 <li class=
"md-nav__item">
539 <a href=
"../../code-style/" class=
"md-nav__link">
550 <li class=
"md-nav__item">
551 <a href=
"../../apps/" class=
"md-nav__link">
562 <li class=
"md-nav__item">
563 <a href=
"../../gdpr/" class=
"md-nav__link">
584 <li class=
"md-nav__item md-nav__item--nested">
587 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_3" type=
"checkbox" id=
"__nav_3" >
589 <label class=
"md-nav__link" for=
"__nav_3">
590 Languages, Templates & CSS
591 <span class=
"md-nav__icon md-icon"></span>
593 <nav class=
"md-nav" aria-label=
"Languages, Templates & CSS" data-md-level=
"1">
594 <label class=
"md-nav__title" for=
"__nav_3">
595 <span class=
"md-nav__icon md-icon"></span>
596 Languages, Templates & CSS
598 <ul class=
"md-nav__list" data-md-scrollfix
>
604 <li class=
"md-nav__item">
605 <a href=
"../../../view/languages/" class=
"md-nav__link">
616 <li class=
"md-nav__item">
617 <a href=
"../../../view/templates/" class=
"md-nav__link">
628 <li class=
"md-nav__item">
629 <a href=
"../../../view/css/" class=
"md-nav__link">
650 <li class=
"md-nav__item md-nav__item--nested">
653 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_4" type=
"checkbox" id=
"__nav_4" >
655 <label class=
"md-nav__link" for=
"__nav_4">
657 <span class=
"md-nav__icon md-icon"></span>
659 <nav class=
"md-nav" aria-label=
"JavaScript API" data-md-level=
"1">
660 <label class=
"md-nav__title" for=
"__nav_4">
661 <span class=
"md-nav__icon md-icon"></span>
664 <ul class=
"md-nav__list" data-md-scrollfix
>
670 <li class=
"md-nav__item">
671 <a href=
"../../../javascript/general-usage/" class=
"md-nav__link">
683 <li class=
"md-nav__item md-nav__item--nested">
686 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_4_2" type=
"checkbox" id=
"__nav_4_2" >
688 <label class=
"md-nav__link" for=
"__nav_4_2">
690 <span class=
"md-nav__icon md-icon"></span>
692 <nav class=
"md-nav" aria-label=
"New API" data-md-level=
"2">
693 <label class=
"md-nav__title" for=
"__nav_4_2">
694 <span class=
"md-nav__icon md-icon"></span>
697 <ul class=
"md-nav__list" data-md-scrollfix
>
703 <li class=
"md-nav__item">
704 <a href=
"../../../javascript/new-api_writing-a-module/" class=
"md-nav__link">
715 <li class=
"md-nav__item">
716 <a href=
"../../../javascript/new-api_data-structures/" class=
"md-nav__link">
727 <li class=
"md-nav__item">
728 <a href=
"../../../javascript/new-api_core/" class=
"md-nav__link">
739 <li class=
"md-nav__item">
740 <a href=
"../../../javascript/new-api_dom/" class=
"md-nav__link">
751 <li class=
"md-nav__item">
752 <a href=
"../../../javascript/new-api_events/" class=
"md-nav__link">
763 <li class=
"md-nav__item">
764 <a href=
"../../../javascript/new-api_ajax/" class=
"md-nav__link">
775 <li class=
"md-nav__item">
776 <a href=
"../../../javascript/new-api_dialogs/" class=
"md-nav__link">
787 <li class=
"md-nav__item">
788 <a href=
"../../../javascript/new-api_browser/" class=
"md-nav__link">
789 Browser and Screen Sizes
799 <li class=
"md-nav__item">
800 <a href=
"../../../javascript/new-api_ui/" class=
"md-nav__link">
817 <li class=
"md-nav__item">
818 <a href=
"../../../javascript/legacy-api/" class=
"md-nav__link">
829 <li class=
"md-nav__item">
830 <a href=
"../../../javascript/helper-functions/" class=
"md-nav__link">
841 <li class=
"md-nav__item">
842 <a href=
"../../../javascript/code-snippets/" class=
"md-nav__link">
863 <li class=
"md-nav__item md-nav__item--nested">
866 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_5" type=
"checkbox" id=
"__nav_5" >
868 <label class=
"md-nav__link" for=
"__nav_5">
870 <span class=
"md-nav__icon md-icon"></span>
872 <nav class=
"md-nav" aria-label=
"Package Components" data-md-level=
"1">
873 <label class=
"md-nav__title" for=
"__nav_5">
874 <span class=
"md-nav__icon md-icon"></span>
877 <ul class=
"md-nav__list" data-md-scrollfix
>
883 <li class=
"md-nav__item">
884 <a href=
"../../../package/package-xml/" class=
"md-nav__link">
896 <li class=
"md-nav__item md-nav__item--nested">
899 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_5_2" type=
"checkbox" id=
"__nav_5_2" >
901 <label class=
"md-nav__link" for=
"__nav_5_2">
903 <span class=
"md-nav__icon md-icon"></span>
905 <nav class=
"md-nav" aria-label=
"PIPs" data-md-level=
"2">
906 <label class=
"md-nav__title" for=
"__nav_5_2">
907 <span class=
"md-nav__icon md-icon"></span>
910 <ul class=
"md-nav__list" data-md-scrollfix
>
916 <li class=
"md-nav__item">
917 <a href=
"../../../package/pip/" class=
"md-nav__link">
928 <li class=
"md-nav__item">
929 <a href=
"../../../package/pip/acl-option/" class=
"md-nav__link">
940 <li class=
"md-nav__item">
941 <a href=
"../../../package/pip/acp-menu/" class=
"md-nav__link">
952 <li class=
"md-nav__item">
953 <a href=
"../../../package/pip/acp-search-provider/" class=
"md-nav__link">
964 <li class=
"md-nav__item">
965 <a href=
"../../../package/pip/acp-template/" class=
"md-nav__link">
976 <li class=
"md-nav__item">
977 <a href=
"../../../package/pip/bbcode/" class=
"md-nav__link">
988 <li class=
"md-nav__item">
989 <a href=
"../../../package/pip/box/" class=
"md-nav__link">
1000 <li class=
"md-nav__item">
1001 <a href=
"../../../package/pip/clipboard-action/" class=
"md-nav__link">
1012 <li class=
"md-nav__item">
1013 <a href=
"../../../package/pip/core-object/" class=
"md-nav__link">
1024 <li class=
"md-nav__item">
1025 <a href=
"../../../package/pip/cronjob/" class=
"md-nav__link">
1036 <li class=
"md-nav__item">
1037 <a href=
"../../../package/pip/event-listener/" class=
"md-nav__link">
1048 <li class=
"md-nav__item">
1049 <a href=
"../../../package/pip/file/" class=
"md-nav__link">
1060 <li class=
"md-nav__item">
1061 <a href=
"../../../package/pip/language/" class=
"md-nav__link">
1072 <li class=
"md-nav__item">
1073 <a href=
"../../../package/pip/media-provider/" class=
"md-nav__link">
1084 <li class=
"md-nav__item">
1085 <a href=
"../../../package/pip/menu/" class=
"md-nav__link">
1096 <li class=
"md-nav__item">
1097 <a href=
"../../../package/pip/menu-item/" class=
"md-nav__link">
1108 <li class=
"md-nav__item">
1109 <a href=
"../../../package/pip/object-type/" class=
"md-nav__link">
1120 <li class=
"md-nav__item">
1121 <a href=
"../../../package/pip/object-type-definition/" class=
"md-nav__link">
1122 objectTypeDefinition
1132 <li class=
"md-nav__item">
1133 <a href=
"../../../package/pip/option/" class=
"md-nav__link">
1144 <li class=
"md-nav__item">
1145 <a href=
"../../../package/pip/page/" class=
"md-nav__link">
1156 <li class=
"md-nav__item">
1157 <a href=
"../../../package/pip/pip/" class=
"md-nav__link">
1168 <li class=
"md-nav__item">
1169 <a href=
"../../../package/pip/script/" class=
"md-nav__link">
1180 <li class=
"md-nav__item">
1181 <a href=
"../../../package/pip/smiley/" class=
"md-nav__link">
1192 <li class=
"md-nav__item">
1193 <a href=
"../../../package/pip/sql/" class=
"md-nav__link">
1204 <li class=
"md-nav__item">
1205 <a href=
"../../../package/pip/style/" class=
"md-nav__link">
1216 <li class=
"md-nav__item">
1217 <a href=
"../../../package/pip/template/" class=
"md-nav__link">
1228 <li class=
"md-nav__item">
1229 <a href=
"../../../package/pip/template-listener/" class=
"md-nav__link">
1240 <li class=
"md-nav__item">
1241 <a href=
"../../../package/pip/user-group-option/" class=
"md-nav__link">
1252 <li class=
"md-nav__item">
1253 <a href=
"../../../package/pip/user-menu/" class=
"md-nav__link">
1264 <li class=
"md-nav__item">
1265 <a href=
"../../../package/pip/user-notification-event/" class=
"md-nav__link">
1266 userNotificationEvent
1276 <li class=
"md-nav__item">
1277 <a href=
"../../../package/pip/user-option/" class=
"md-nav__link">
1288 <li class=
"md-nav__item">
1289 <a href=
"../../../package/pip/user-profile-menu/" class=
"md-nav__link">
1306 <li class=
"md-nav__item">
1307 <a href=
"../../../package/database-php-api/" class=
"md-nav__link">
1328 <li class=
"md-nav__item md-nav__item--nested">
1331 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_6" type=
"checkbox" id=
"__nav_6" >
1333 <label class=
"md-nav__link" for=
"__nav_6">
1335 <span class=
"md-nav__icon md-icon"></span>
1337 <nav class=
"md-nav" aria-label=
"Migration" data-md-level=
"1">
1338 <label class=
"md-nav__title" for=
"__nav_6">
1339 <span class=
"md-nav__icon md-icon"></span>
1342 <ul class=
"md-nav__list" data-md-scrollfix
>
1349 <li class=
"md-nav__item md-nav__item--nested">
1352 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_6_1" type=
"checkbox" id=
"__nav_6_1" >
1354 <label class=
"md-nav__link" for=
"__nav_6_1">
1355 Migrating from WSC
5.3
1356 <span class=
"md-nav__icon md-icon"></span>
1358 <nav class=
"md-nav" aria-label=
"Migrating from WSC 5.3" data-md-level=
"2">
1359 <label class=
"md-nav__title" for=
"__nav_6_1">
1360 <span class=
"md-nav__icon md-icon"></span>
1361 Migrating from WSC
5.3
1363 <ul class=
"md-nav__list" data-md-scrollfix
>
1369 <li class=
"md-nav__item">
1370 <a href=
"../../../migration/wsc53/php/" class=
"md-nav__link">
1381 <li class=
"md-nav__item">
1382 <a href=
"../../../migration/wsc53/session/" class=
"md-nav__link">
1383 Session Handling and Authentication
1393 <li class=
"md-nav__item">
1394 <a href=
"../../../migration/wsc53/javascript/" class=
"md-nav__link">
1405 <li class=
"md-nav__item">
1406 <a href=
"../../../migration/wsc53/templates/" class=
"md-nav__link">
1417 <li class=
"md-nav__item">
1418 <a href=
"../../../migration/wsc53/libraries/" class=
"md-nav__link">
1419 Third Party Libraries
1436 <li class=
"md-nav__item md-nav__item--nested">
1439 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_6_2" type=
"checkbox" id=
"__nav_6_2" >
1441 <label class=
"md-nav__link" for=
"__nav_6_2">
1442 Migrating from WSC
5.2
1443 <span class=
"md-nav__icon md-icon"></span>
1445 <nav class=
"md-nav" aria-label=
"Migrating from WSC 5.2" data-md-level=
"2">
1446 <label class=
"md-nav__title" for=
"__nav_6_2">
1447 <span class=
"md-nav__icon md-icon"></span>
1448 Migrating from WSC
5.2
1450 <ul class=
"md-nav__list" data-md-scrollfix
>
1456 <li class=
"md-nav__item">
1457 <a href=
"../../../migration/wsc52/php/" class=
"md-nav__link">
1468 <li class=
"md-nav__item">
1469 <a href=
"../../../migration/wsc52/templates/" class=
"md-nav__link">
1470 Templates and Languages
1480 <li class=
"md-nav__item">
1481 <a href=
"../../../migration/wsc52/libraries/" class=
"md-nav__link">
1482 Third Party Libraries
1499 <li class=
"md-nav__item md-nav__item--nested">
1502 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_6_3" type=
"checkbox" id=
"__nav_6_3" >
1504 <label class=
"md-nav__link" for=
"__nav_6_3">
1505 Migrating from WSC
3.1
1506 <span class=
"md-nav__icon md-icon"></span>
1508 <nav class=
"md-nav" aria-label=
"Migrating from WSC 3.1" data-md-level=
"2">
1509 <label class=
"md-nav__title" for=
"__nav_6_3">
1510 <span class=
"md-nav__icon md-icon"></span>
1511 Migrating from WSC
3.1
1513 <ul class=
"md-nav__list" data-md-scrollfix
>
1519 <li class=
"md-nav__item">
1520 <a href=
"../../../migration/wsc31/php/" class=
"md-nav__link">
1538 <li class=
"md-nav__item md-nav__item--nested">
1541 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_6_4" type=
"checkbox" id=
"__nav_6_4" >
1543 <label class=
"md-nav__link" for=
"__nav_6_4">
1544 Migrating from WSC
3.0
1545 <span class=
"md-nav__icon md-icon"></span>
1547 <nav class=
"md-nav" aria-label=
"Migrating from WSC 3.0" data-md-level=
"2">
1548 <label class=
"md-nav__title" for=
"__nav_6_4">
1549 <span class=
"md-nav__icon md-icon"></span>
1550 Migrating from WSC
3.0
1552 <ul class=
"md-nav__list" data-md-scrollfix
>
1558 <li class=
"md-nav__item">
1559 <a href=
"../../../migration/wsc30/php/" class=
"md-nav__link">
1570 <li class=
"md-nav__item">
1571 <a href=
"../../../migration/wsc30/javascript/" class=
"md-nav__link">
1582 <li class=
"md-nav__item">
1583 <a href=
"../../../migration/wsc30/templates/" class=
"md-nav__link">
1594 <li class=
"md-nav__item">
1595 <a href=
"../../../migration/wsc30/css/" class=
"md-nav__link">
1606 <li class=
"md-nav__item">
1607 <a href=
"../../../migration/wsc30/package/" class=
"md-nav__link">
1625 <li class=
"md-nav__item md-nav__item--nested">
1628 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_6_5" type=
"checkbox" id=
"__nav_6_5" >
1630 <label class=
"md-nav__link" for=
"__nav_6_5">
1631 Migrating from WCF
2.1
1632 <span class=
"md-nav__icon md-icon"></span>
1634 <nav class=
"md-nav" aria-label=
"Migrating from WCF 2.1" data-md-level=
"2">
1635 <label class=
"md-nav__title" for=
"__nav_6_5">
1636 <span class=
"md-nav__icon md-icon"></span>
1637 Migrating from WCF
2.1
1639 <ul class=
"md-nav__list" data-md-scrollfix
>
1645 <li class=
"md-nav__item">
1646 <a href=
"../../../migration/wcf21/php/" class=
"md-nav__link">
1657 <li class=
"md-nav__item">
1658 <a href=
"../../../migration/wcf21/templates/" class=
"md-nav__link">
1669 <li class=
"md-nav__item">
1670 <a href=
"../../../migration/wcf21/css/" class=
"md-nav__link">
1681 <li class=
"md-nav__item">
1682 <a href=
"../../../migration/wcf21/package/" class=
"md-nav__link">
1709 <li class=
"md-nav__item md-nav__item--nested">
1712 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_7" type=
"checkbox" id=
"__nav_7" >
1714 <label class=
"md-nav__link" for=
"__nav_7">
1716 <span class=
"md-nav__icon md-icon"></span>
1718 <nav class=
"md-nav" aria-label=
"Tutorials" data-md-level=
"1">
1719 <label class=
"md-nav__title" for=
"__nav_7">
1720 <span class=
"md-nav__icon md-icon"></span>
1723 <ul class=
"md-nav__list" data-md-scrollfix
>
1730 <li class=
"md-nav__item md-nav__item--nested">
1733 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_7_1" type=
"checkbox" id=
"__nav_7_1" >
1735 <label class=
"md-nav__link" for=
"__nav_7_1">
1737 <span class=
"md-nav__icon md-icon"></span>
1739 <nav class=
"md-nav" aria-label=
"Tutorial Series" data-md-level=
"2">
1740 <label class=
"md-nav__title" for=
"__nav_7_1">
1741 <span class=
"md-nav__icon md-icon"></span>
1744 <ul class=
"md-nav__list" data-md-scrollfix
>
1750 <li class=
"md-nav__item">
1751 <a href=
"../../../tutorial/series/overview/" class=
"md-nav__link">
1762 <li class=
"md-nav__item">
1763 <a href=
"../../../tutorial/series/part_1/" class=
"md-nav__link">
1774 <li class=
"md-nav__item">
1775 <a href=
"../../../tutorial/series/part_2/" class=
"md-nav__link">
1786 <li class=
"md-nav__item">
1787 <a href=
"../../../tutorial/series/part_3/" class=
"md-nav__link">
1814 <div class=
"md-sidebar md-sidebar--secondary" data-md-component=
"sidebar" data-md-type=
"toc" >
1815 <div class=
"md-sidebar__scrollwrap">
1816 <div class=
"md-sidebar__inner">
1818 <nav class=
"md-nav md-nav--secondary" aria-label=
"Table of contents">
1824 <label class=
"md-nav__title" for=
"__toc">
1825 <span class=
"md-nav__icon md-icon"></span>
1828 <ul class=
"md-nav__list" data-md-component=
"toc" data-md-scrollfix
>
1830 <li class=
"md-nav__item">
1831 <a href=
"#objecttypexml" class=
"md-nav__link">
1837 <li class=
"md-nav__item">
1838 <a href=
"#usernotificationeventxml" class=
"md-nav__link">
1839 userNotificationEvent.xml
1844 <li class=
"md-nav__item">
1845 <a href=
"#firing-events" class=
"md-nav__link">
1851 <li class=
"md-nav__item">
1852 <a href=
"#marking-notifications-as-confirmed" class=
"md-nav__link">
1853 Marking Notifications as Confirmed
1866 <div class=
"md-content" data-md-component=
"content">
1867 <article class=
"md-content__inner md-typeset">
1871 <h1 id=
"user-notifications">User Notifications
<a class=
"headerlink" href=
"#user-notifications" title=
"Permanent link">#
</a></h1>
1872 <p>WoltLab Suite includes a powerful user notification system that supports notifications directly shown on the website and emails sent immediately or on a daily basis.
</p>
1873 <h2 id=
"objecttypexml"><code>objectType.xml
</code><a class=
"headerlink" href=
"#objecttypexml" title=
"Permanent link">#
</a></h2>
1874 <p>For any type of object related to events, you have to define an object type for the object type definition
<code>com.woltlab.wcf.notification.objectType
</code>:
</p>
1875 <div class=
"highlight"><pre><span></span><code><span class=
"cp"><?xml version=
"1.0" encoding=
"UTF-
8"?
></span>
1876 <span class=
"nt"><data
</span> <span class=
"na">xmlns=
</span><span class=
"s">"http://www.woltlab.com
"</span> <span class=
"na">xmlns:xsi=
</span><span class=
"s">"http://www.w3.org/
2001/XMLSchema-instance
"</span> <span class=
"na">xsi:schemaLocation=
</span><span class=
"s">"http://www.woltlab.com http://www.woltlab.com/XSD/
2019/objectType.xsd
"</span><span class=
"nt">></span>
1877 <span class=
"nt"><import
></span>
1878 <span class=
"nt"><type
></span>
1879 <span class=
"nt"><name
></span>com.woltlab.example.foo
<span class=
"nt"></name
></span>
1880 <span class=
"nt"><definitionname
></span>com.woltlab.wcf.notification.objectType
<span class=
"nt"></definitionname
></span>
1881 <span class=
"nt"><classname
></span>example\system\user\notification\object\type\FooUserNotificationObjectType
<span class=
"nt"></classname
></span>
1882 <span class=
"nt"><category
></span>com.woltlab.example
<span class=
"nt"></category
></span>
1883 <span class=
"nt"></type
></span>
1884 <span class=
"nt"></import
></span>
1885 <span class=
"nt"></data
></span>
1887 <p>The referenced class
<code>FooUserNotificationObjectType
</code> has to implement the
<a href=
"https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/user/notification/object/type/IUserNotificationObjectType.class.php">IUserNotificationObjectType
</a> interface, which should be done by extending
<a href=
"https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/user/notification/object/type/AbstractUserNotificationObjectType.class.php">AbstractUserNotificationObjectType
</a>.
</p>
1888 <div class=
"highlight"><pre><span></span><code><span class=
"o"><?
</span><span class=
"nx">php
</span>
1889 <span class=
"k">namespace
</span> <span class=
"nx">example\system\user\notification\object\type
</span><span class=
"p">;
</span>
1890 <span class=
"k">use
</span> <span class=
"nx">example\data\foo\Foo
</span><span class=
"p">;
</span>
1891 <span class=
"k">use
</span> <span class=
"nx">example\data\foo\FooList
</span><span class=
"p">;
</span>
1892 <span class=
"k">use
</span> <span class=
"nx">example\system\user\notification\object\FooUserNotificationObject
</span><span class=
"p">;
</span>
1893 <span class=
"k">use
</span> <span class=
"nx">wcf\system\user\notification\object\type\AbstractUserNotificationObjectType
</span><span class=
"p">;
</span>
1895 <span class=
"sd">/**
</span>
1896 <span class=
"sd"> * Represents a foo as a notification object type.
</span>
1897 <span class=
"sd"> *
</span>
1898 <span class=
"sd"> * @author Matthias Schmidt
</span>
1899 <span class=
"sd"> * @copyright
2001-
2017 WoltLab GmbH
</span>
1900 <span class=
"sd"> * @license WoltLab License
<http://www.woltlab.com/license-agreement.html
></span>
1901 <span class=
"sd"> * @package WoltLabSuite\Example\System\User\Notification\Object\Type
</span>
1902 <span class=
"sd"> */
</span>
1903 <span class=
"k">class
</span> <span class=
"nc">FooUserNotificationObjectType
</span> <span class=
"k">extends
</span> <span class=
"nx">AbstractUserNotificationObjectType
</span> <span class=
"p">{
</span>
1904 <span class=
"sd">/**
</span>
1905 <span class=
"sd"> * @inheritDoc
</span>
1906 <span class=
"sd"> */
</span>
1907 <span class=
"k">protected
</span> <span class=
"k">static
</span> <span class=
"nv">$decoratorClassName
</span> <span class=
"o">=
</span> <span class=
"nx">FooUserNotificationObject
</span><span class=
"o">::
</span><span class=
"na">class
</span><span class=
"p">;
</span>
1909 <span class=
"sd">/**
</span>
1910 <span class=
"sd"> * @inheritDoc
</span>
1911 <span class=
"sd"> */
</span>
1912 <span class=
"k">protected
</span> <span class=
"k">static
</span> <span class=
"nv">$objectClassName
</span> <span class=
"o">=
</span> <span class=
"nx">Foo
</span><span class=
"o">::
</span><span class=
"na">class
</span><span class=
"p">;
</span>
1914 <span class=
"sd">/**
</span>
1915 <span class=
"sd"> * @inheritDoc
</span>
1916 <span class=
"sd"> */
</span>
1917 <span class=
"k">protected
</span> <span class=
"k">static
</span> <span class=
"nv">$objectListClassName
</span> <span class=
"o">=
</span> <span class=
"nx">FooList
</span><span class=
"o">::
</span><span class=
"na">class
</span><span class=
"p">;
</span>
1918 <span class=
"p">}
</span>
1920 <p>You have to set the class names of the database object (
<code>$objectClassName
</code>) and the related list (
<code>$objectListClassName
</code>).
1921 Additionally, you have to create a class that implements the
<a href=
"https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/user/notification/object/IUserNotificationObject.class.php">IUserNotificationObject
</a> whose name you have to set as the value of the
<code>$decoratorClassName
</code> property.
</p>
1922 <div class=
"highlight"><pre><span></span><code><span class=
"o"><?
</span><span class=
"nx">php
</span>
1923 <span class=
"k">namespace
</span> <span class=
"nx">example\system\user\notification\object
</span><span class=
"p">;
</span>
1924 <span class=
"k">use
</span> <span class=
"nx">example\data\foo\Foo
</span><span class=
"p">;
</span>
1925 <span class=
"k">use
</span> <span class=
"nx">wcf\data\DatabaseObjectDecorator
</span><span class=
"p">;
</span>
1926 <span class=
"k">use
</span> <span class=
"nx">wcf\system\user\notification\object\IUserNotificationObject
</span><span class=
"p">;
</span>
1928 <span class=
"sd">/**
</span>
1929 <span class=
"sd"> * Represents a foo as a notification object.
</span>
1930 <span class=
"sd"> *
</span>
1931 <span class=
"sd"> * @author Matthias Schmidt
</span>
1932 <span class=
"sd"> * @copyright
2001-
2017 WoltLab GmbH
</span>
1933 <span class=
"sd"> * @license WoltLab License
<http://www.woltlab.com/license-agreement.html
></span>
1934 <span class=
"sd"> * @package WoltLabSuite\Example\System\User\Notification\Object
</span>
1935 <span class=
"sd"> *
</span>
1936 <span class=
"sd"> * @method Foo getDecoratedObject()
</span>
1937 <span class=
"sd"> * @mixin Foo
</span>
1938 <span class=
"sd"> */
</span>
1939 <span class=
"k">class
</span> <span class=
"nc">FooUserNotificationObject
</span> <span class=
"k">extends
</span> <span class=
"nx">DatabaseObjectDecorator
</span> <span class=
"k">implements
</span> <span class=
"nx">IUserNotificationObject
</span> <span class=
"p">{
</span>
1940 <span class=
"sd">/**
</span>
1941 <span class=
"sd"> * @inheritDoc
</span>
1942 <span class=
"sd"> */
</span>
1943 <span class=
"k">protected
</span> <span class=
"k">static
</span> <span class=
"nv">$baseClass
</span> <span class=
"o">=
</span> <span class=
"nx">Foo
</span><span class=
"o">::
</span><span class=
"na">class
</span><span class=
"p">;
</span>
1945 <span class=
"sd">/**
</span>
1946 <span class=
"sd"> * @inheritDoc
</span>
1947 <span class=
"sd"> */
</span>
1948 <span class=
"k">public
</span> <span class=
"k">function
</span> <span class=
"nf">getTitle
</span><span class=
"p">()
</span> <span class=
"p">{
</span>
1949 <span class=
"k">return
</span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getDecoratedObject
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">getTitle
</span><span class=
"p">();
</span>
1950 <span class=
"p">}
</span>
1952 <span class=
"sd">/**
</span>
1953 <span class=
"sd"> * @inheritDoc
</span>
1954 <span class=
"sd"> */
</span>
1955 <span class=
"k">public
</span> <span class=
"k">function
</span> <span class=
"nf">getURL
</span><span class=
"p">()
</span> <span class=
"p">{
</span>
1956 <span class=
"k">return
</span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getDecoratedObject
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">getLink
</span><span class=
"p">();
</span>
1957 <span class=
"p">}
</span>
1959 <span class=
"sd">/**
</span>
1960 <span class=
"sd"> * @inheritDoc
</span>
1961 <span class=
"sd"> */
</span>
1962 <span class=
"k">public
</span> <span class=
"k">function
</span> <span class=
"nf">getAuthorID
</span><span class=
"p">()
</span> <span class=
"p">{
</span>
1963 <span class=
"k">return
</span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getDecoratedObject
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">userID
</span><span class=
"p">;
</span>
1964 <span class=
"p">}
</span>
1965 <span class=
"p">}
</span>
1968 <li>The
<code>getTitle()
</code> method returns the title of the object.
1969 In this case, we assume that the
<code>Foo
</code> class has implemented the
<a href=
"https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/data/ITitledObject.class.php">ITitledObject
</a> interface so that the decorated
<code>Foo
</code> can handle this method call itself.
</li>
1970 <li>The
<code>getURL()
</code> method returns the link to the object.
1971 As for the
<code>getTitle()
</code>, we assume that the
<code>Foo
</code> class has implemented the
<a href=
"https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/data/ILinkableObject.class.php">ILinkableObject
</a> interface so that the decorated
<code>Foo
</code> can also handle this method call itself.
</li>
1972 <li>The
<code>getAuthorID()
</code> method returns the id of the user who created the decorated
<code>Foo
</code> object.
1973 We assume that
<code>Foo
</code> objects have a
<code>userID
</code> property that contains this id.
</li>
1975 <h2 id=
"usernotificationeventxml"><code>userNotificationEvent.xml
</code><a class=
"headerlink" href=
"#usernotificationeventxml" title=
"Permanent link">#
</a></h2>
1976 <p>Each event that you fire in your package needs to be registered using the
<a href=
"../../../package/pip/user-notification-event/">user notification event package installation plugin
</a>.
1977 An example file might look like this:
</p>
1978 <div class=
"highlight"><pre><span></span><code><span class=
"cp"><?xml version=
"1.0" encoding=
"UTF-
8"?
></span>
1979 <span class=
"nt"><data
</span> <span class=
"na">xmlns=
</span><span class=
"s">"http://www.woltlab.com
"</span> <span class=
"na">xmlns:xsi=
</span><span class=
"s">"http://www.w3.org/
2001/XMLSchema-instance
"</span> <span class=
"na">xsi:schemaLocation=
</span><span class=
"s">"http://www.woltlab.com http://www.woltlab.com/XSD/
2019/userNotificationEvent.xsd
"</span><span class=
"nt">></span>
1980 <span class=
"nt"><import
></span>
1981 <span class=
"nt"><event
></span>
1982 <span class=
"nt"><name
></span>bar
<span class=
"nt"></name
></span>
1983 <span class=
"nt"><objecttype
></span>com.woltlab.example.foo
<span class=
"nt"></objecttype
></span>
1984 <span class=
"nt"><classname
></span>example\system\user\notification\event\FooUserNotificationEvent
<span class=
"nt"></classname
></span>
1985 <span class=
"nt"><preset
></span>1<span class=
"nt"></preset
></span>
1986 <span class=
"nt"></event
></span>
1987 <span class=
"nt"></import
></span>
1988 <span class=
"nt"></data
></span>
1990 <p>Here, you reference the user notification object type created via
<code>objectType.xml
</code>.
1991 The referenced class in the
<code><classname
></code> element has to implement the
<a href=
"https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/user/notification/event/IUserNotificationEvent.class.php">IUserNotificationEvent
</a> interface by extending the
<a href=
"https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/user/notification/event/AbstractUserNotificationEvent.class.php">AbstractUserNotificationEvent
</a> class or the
<a href=
"https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/user/notification/event/AbstractSharedUserNotificationEvent.class.php">AbstractSharedUserNotificationEvent
</a> class if you want to pre-load additional data before processing notifications.
1992 In
<code>AbstractSharedUserNotificationEvent::prepare()
</code>, you can, for example, tell runtime caches to prepare to load certain objects which then are loaded all at once when the objects are needed.
</p>
1993 <div class=
"highlight"><pre><span></span><code><span class=
"o"><?
</span><span class=
"nx">php
</span>
1994 <span class=
"k">namespace
</span> <span class=
"nx">example\system\user\notification\event
</span><span class=
"p">;
</span>
1995 <span class=
"k">use
</span> <span class=
"nx">example\system\cache\runtime\BazRuntimeCache
</span><span class=
"p">;
</span>
1996 <span class=
"k">use
</span> <span class=
"nx">example\system\user\notification\object\FooUserNotificationObject
</span><span class=
"p">;
</span>
1997 <span class=
"k">use
</span> <span class=
"nx">wcf\system\email\Email
</span><span class=
"p">;
</span>
1998 <span class=
"k">use
</span> <span class=
"nx">wcf\system\request\LinkHandler
</span><span class=
"p">;
</span>
1999 <span class=
"k">use
</span> <span class=
"nx">wcf\system\user\notification\event\AbstractSharedUserNotificationEvent
</span><span class=
"p">;
</span>
2001 <span class=
"sd">/**
</span>
2002 <span class=
"sd"> * Notification event for foos.
</span>
2003 <span class=
"sd"> *
</span>
2004 <span class=
"sd"> * @author Matthias Schmidt
</span>
2005 <span class=
"sd"> * @copyright
2001-
2017 WoltLab GmbH
</span>
2006 <span class=
"sd"> * @license WoltLab License
<http://www.woltlab.com/license-agreement.html
></span>
2007 <span class=
"sd"> * @package WoltLabSuite\Example\System\User\Notification\Event
</span>
2008 <span class=
"sd"> *
</span>
2009 <span class=
"sd"> * @method FooUserNotificationObject getUserNotificationObject()
</span>
2010 <span class=
"sd"> */
</span>
2011 <span class=
"k">class
</span> <span class=
"nc">FooUserNotificationEvent
</span> <span class=
"k">extends
</span> <span class=
"nx">AbstractSharedUserNotificationEvent
</span> <span class=
"p">{
</span>
2012 <span class=
"sd">/**
</span>
2013 <span class=
"sd"> * @inheritDoc
</span>
2014 <span class=
"sd"> */
</span>
2015 <span class=
"k">protected
</span> <span class=
"nv">$stackable
</span> <span class=
"o">=
</span> <span class=
"k">true
</span><span class=
"p">;
</span>
2017 <span class=
"sd">/** @noinspection PhpMissingParentCallCommonInspection */
</span>
2018 <span class=
"sd">/**
</span>
2019 <span class=
"sd"> * @inheritDoc
</span>
2020 <span class=
"sd"> */
</span>
2021 <span class=
"k">public
</span> <span class=
"k">function
</span> <span class=
"nf">checkAccess
</span><span class=
"p">()
</span> <span class=
"p">{
</span>
2022 <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getUserNotificationObject
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">setBaz
</span><span class=
"p">(
</span><span class=
"nx">BazRuntimeCache
</span><span class=
"o">::
</span><span class=
"na">getInstance
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">getObject
</span><span class=
"p">(
</span><span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getUserNotificationObject
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">bazID
</span><span class=
"p">));
</span>
2024 <span class=
"k">if
</span> <span class=
"p">(
</span><span class=
"o">!
</span><span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getUserNotificationObject
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">isAccessible
</span><span class=
"p">())
</span> <span class=
"p">{
</span>
2025 <span class=
"c1">// do some cleanup, if necessary
</span>
2027 <span class=
"k">return
</span> <span class=
"k">false
</span><span class=
"p">;
</span>
2028 <span class=
"p">}
</span>
2030 <span class=
"k">return
</span> <span class=
"k">true
</span><span class=
"p">;
</span>
2031 <span class=
"p">}
</span>
2033 <span class=
"sd">/** @noinspection PhpMissingParentCallCommonInspection */
</span>
2034 <span class=
"sd">/**
</span>
2035 <span class=
"sd"> * @inheritDoc
</span>
2036 <span class=
"sd"> */
</span>
2037 <span class=
"k">public
</span> <span class=
"k">function
</span> <span class=
"nf">getEmailMessage
</span><span class=
"p">(
</span><span class=
"nv">$notificationType
</span> <span class=
"o">=
</span> <span class=
"s1">'instant
'</span><span class=
"p">)
</span> <span class=
"p">{
</span>
2038 <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getUserNotificationObject
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">setBaz
</span><span class=
"p">(
</span><span class=
"nx">BazRuntimeCache
</span><span class=
"o">::
</span><span class=
"na">getInstance
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">getObject
</span><span class=
"p">(
</span><span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getUserNotificationObject
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">bazID
</span><span class=
"p">));
</span>
2040 <span class=
"nv">$messageID
</span> <span class=
"o">=
</span> <span class=
"s1">'<com.woltlab.example.baz/
'</span><span class=
"o">.
</span><span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getUserNotificationObject
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">bazID
</span><span class=
"o">.
</span><span class=
"s1">'@
'</span><span class=
"o">.
</span><span class=
"nx">Email
</span><span class=
"o">::
</span><span class=
"na">getHost
</span><span class=
"p">()
</span><span class=
"o">.
</span><span class=
"s1">'>'</span><span class=
"p">;
</span>
2042 <span class=
"k">return
</span> <span class=
"p">[
</span>
2043 <span class=
"s1">'application
'</span> <span class=
"o">=
></span> <span class=
"s1">'example
'</span><span class=
"p">,
</span>
2044 <span class=
"s1">'in-reply-to
'</span> <span class=
"o">=
></span> <span class=
"p">[
</span><span class=
"nv">$messageID
</span><span class=
"p">],
</span>
2045 <span class=
"s1">'message-id
'</span> <span class=
"o">=
></span> <span class=
"s1">'com.woltlab.example.foo/
'</span><span class=
"o">.
</span><span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getUserNotificationObject
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">fooID
</span><span class=
"p">,
</span>
2046 <span class=
"s1">'references
'</span> <span class=
"o">=
></span> <span class=
"p">[
</span><span class=
"nv">$messageID
</span><span class=
"p">],
</span>
2047 <span class=
"s1">'template
'</span> <span class=
"o">=
></span> <span class=
"s1">'email_notification_foo
'</span>
2048 <span class=
"p">];
</span>
2049 <span class=
"p">}
</span>
2051 <span class=
"sd">/**
</span>
2052 <span class=
"sd"> * @inheritDoc
</span>
2053 <span class=
"sd"> * @since
5.0</span>
2054 <span class=
"sd"> */
</span>
2055 <span class=
"k">public
</span> <span class=
"k">function
</span> <span class=
"nf">getEmailTitle
</span><span class=
"p">()
</span> <span class=
"p">{
</span>
2056 <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getUserNotificationObject
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">setBaz
</span><span class=
"p">(
</span><span class=
"nx">BazRuntimeCache
</span><span class=
"o">::
</span><span class=
"na">getInstance
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">getObject
</span><span class=
"p">(
</span><span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getUserNotificationObject
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">bazID
</span><span class=
"p">));
</span>
2058 <span class=
"k">return
</span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getLanguage
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">getDynamicVariable
</span><span class=
"p">(
</span><span class=
"s1">'example.foo.notification.mail.title
'</span><span class=
"p">,
</span> <span class=
"p">[
</span>
2059 <span class=
"s1">'userNotificationObject
'</span> <span class=
"o">=
></span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getUserNotificationObject
</span><span class=
"p">()
</span>
2060 <span class=
"p">]);
</span>
2061 <span class=
"p">}
</span>
2063 <span class=
"sd">/** @noinspection PhpMissingParentCallCommonInspection */
</span>
2064 <span class=
"sd">/**
</span>
2065 <span class=
"sd"> * @inheritDoc
</span>
2066 <span class=
"sd"> */
</span>
2067 <span class=
"k">public
</span> <span class=
"k">function
</span> <span class=
"nf">getEventHash
</span><span class=
"p">()
</span> <span class=
"p">{
</span>
2068 <span class=
"k">return
</span> <span class=
"nb">sha1
</span><span class=
"p">(
</span><span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">eventID
</span> <span class=
"o">.
</span> <span class=
"s1">'-
'</span> <span class=
"o">.
</span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getUserNotificationObject
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">bazID
</span><span class=
"p">);
</span>
2069 <span class=
"p">}
</span>
2071 <span class=
"sd">/**
</span>
2072 <span class=
"sd"> * @inheritDoc
</span>
2073 <span class=
"sd"> */
</span>
2074 <span class=
"k">public
</span> <span class=
"k">function
</span> <span class=
"nf">getLink
</span><span class=
"p">()
</span> <span class=
"p">{
</span>
2075 <span class=
"k">return
</span> <span class=
"nx">LinkHandler
</span><span class=
"o">::
</span><span class=
"na">getInstance
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">getLink
</span><span class=
"p">(
</span><span class=
"s1">'Foo
'</span><span class=
"p">,
</span> <span class=
"p">[
</span>
2076 <span class=
"s1">'application
'</span> <span class=
"o">=
></span> <span class=
"s1">'example
'</span><span class=
"p">,
</span>
2077 <span class=
"s1">'object
'</span> <span class=
"o">=
></span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getUserNotificationObject
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">getDecoratedObject
</span><span class=
"p">()
</span>
2078 <span class=
"p">]);
</span>
2079 <span class=
"p">}
</span>
2081 <span class=
"sd">/**
</span>
2082 <span class=
"sd"> * @inheritDoc
</span>
2083 <span class=
"sd"> */
</span>
2084 <span class=
"k">public
</span> <span class=
"k">function
</span> <span class=
"nf">getMessage
</span><span class=
"p">()
</span> <span class=
"p">{
</span>
2085 <span class=
"nv">$authors
</span> <span class=
"o">=
</span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getAuthors
</span><span class=
"p">();
</span>
2086 <span class=
"nv">$count
</span> <span class=
"o">=
</span> <span class=
"nb">count
</span><span class=
"p">(
</span><span class=
"nv">$authors
</span><span class=
"p">);
</span>
2088 <span class=
"k">if
</span> <span class=
"p">(
</span><span class=
"nv">$count
</span> <span class=
"o">></span> <span class=
"mi">1</span><span class=
"p">)
</span> <span class=
"p">{
</span>
2089 <span class=
"k">if
</span> <span class=
"p">(
</span><span class=
"nb">isset
</span><span class=
"p">(
</span><span class=
"nv">$authors
</span><span class=
"p">[
</span><span class=
"mi">0</span><span class=
"p">]))
</span> <span class=
"p">{
</span>
2090 <span class=
"nb">unset
</span><span class=
"p">(
</span><span class=
"nv">$authors
</span><span class=
"p">[
</span><span class=
"mi">0</span><span class=
"p">]);
</span>
2091 <span class=
"p">}
</span>
2092 <span class=
"nv">$count
</span> <span class=
"o">=
</span> <span class=
"nb">count
</span><span class=
"p">(
</span><span class=
"nv">$authors
</span><span class=
"p">);
</span>
2094 <span class=
"k">return
</span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getLanguage
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">getDynamicVariable
</span><span class=
"p">(
</span><span class=
"s1">'example.foo.notification.message.stacked
'</span><span class=
"p">,
</span> <span class=
"p">[
</span>
2095 <span class=
"s1">'author
'</span> <span class=
"o">=
></span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">author
</span><span class=
"p">,
</span>
2096 <span class=
"s1">'authors
'</span> <span class=
"o">=
></span> <span class=
"nb">array_values
</span><span class=
"p">(
</span><span class=
"nv">$authors
</span><span class=
"p">),
</span>
2097 <span class=
"s1">'count
'</span> <span class=
"o">=
></span> <span class=
"nv">$count
</span><span class=
"p">,
</span>
2098 <span class=
"s1">'guestTimesTriggered
'</span> <span class=
"o">=
></span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">notification
</span><span class=
"o">-
></span><span class=
"na">guestTimesTriggered
</span><span class=
"p">,
</span>
2099 <span class=
"s1">'message
'</span> <span class=
"o">=
></span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getUserNotificationObject
</span><span class=
"p">(),
</span>
2100 <span class=
"s1">'others
'</span> <span class=
"o">=
></span> <span class=
"nv">$count
</span> <span class=
"o">-
</span> <span class=
"mi">1</span>
2101 <span class=
"p">]);
</span>
2102 <span class=
"p">}
</span>
2104 <span class=
"k">return
</span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getLanguage
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">getDynamicVariable
</span><span class=
"p">(
</span><span class=
"s1">'example.foo.notification.message
'</span><span class=
"p">,
</span> <span class=
"p">[
</span>
2105 <span class=
"s1">'author
'</span> <span class=
"o">=
></span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">author
</span><span class=
"p">,
</span>
2106 <span class=
"s1">'userNotificationObject
'</span> <span class=
"o">=
></span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getUserNotificationObject
</span><span class=
"p">()
</span>
2107 <span class=
"p">]);
</span>
2108 <span class=
"p">}
</span>
2110 <span class=
"sd">/**
</span>
2111 <span class=
"sd"> * @inheritDoc
</span>
2112 <span class=
"sd"> */
</span>
2113 <span class=
"k">public
</span> <span class=
"k">function
</span> <span class=
"nf">getTitle
</span><span class=
"p">()
</span> <span class=
"p">{
</span>
2114 <span class=
"nv">$count
</span> <span class=
"o">=
</span> <span class=
"nb">count
</span><span class=
"p">(
</span><span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getAuthors
</span><span class=
"p">());
</span>
2115 <span class=
"k">if
</span> <span class=
"p">(
</span><span class=
"nv">$count
</span> <span class=
"o">></span> <span class=
"mi">1</span><span class=
"p">)
</span> <span class=
"p">{
</span>
2116 <span class=
"k">return
</span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getLanguage
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">getDynamicVariable
</span><span class=
"p">(
</span><span class=
"s1">'example.foo.notification.title.stacked
'</span><span class=
"p">,
</span> <span class=
"p">[
</span>
2117 <span class=
"s1">'count
'</span> <span class=
"o">=
></span> <span class=
"nv">$count
</span><span class=
"p">,
</span>
2118 <span class=
"s1">'timesTriggered
'</span> <span class=
"o">=
></span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">notification
</span><span class=
"o">-
></span><span class=
"na">timesTriggered
</span>
2119 <span class=
"p">]);
</span>
2120 <span class=
"p">}
</span>
2122 <span class=
"k">return
</span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getLanguage
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">get
</span><span class=
"p">(
</span><span class=
"s1">'example.foo.notification.title
'</span><span class=
"p">);
</span>
2123 <span class=
"p">}
</span>
2125 <span class=
"sd">/**
</span>
2126 <span class=
"sd"> * @inheritDoc
</span>
2127 <span class=
"sd"> */
</span>
2128 <span class=
"k">protected
</span> <span class=
"k">function
</span> <span class=
"nf">prepare
</span><span class=
"p">()
</span> <span class=
"p">{
</span>
2129 <span class=
"nx">BazRuntimeCache
</span><span class=
"o">::
</span><span class=
"na">getInstance
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">cacheObjectID
</span><span class=
"p">(
</span><span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">getUserNotificationObject
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">bazID
</span><span class=
"p">);
</span>
2130 <span class=
"p">}
</span>
2131 <span class=
"p">}
</span>
2134 <li>The
<code>$stackable
</code> property is
<code>false
</code> by default and has to be explicitly set to
<code>true
</code> if stacking of notifications should be enabled.
2135 Stacking of notification does not create new notifications for the same event for a certain object if the related action as been triggered by different users.
2136 For example, if something is liked by one user and then liked again by another user before the recipient of the notification has confirmed it, the existing notification will be amended to include both users who liked the content.
2137 Stacking can thus be used to avoid cluttering the notification list of users.
</li>
2138 <li>The
<code>checkAccess()
</code> method makes sure that the active user still has access to the object related to the notification.
2139 If that is not the case, the user notification system will automatically deleted the user notification based on the return value of the method.
2140 If you have any cached values related to notifications, you should also reset these values here.
</li>
2141 <li>The
<code>getEmailMessage()
</code> method return data to create the instant email or the daily summary email.
2142 For instant emails (
<code>$notificationType = 'instant'
</code>), you have to return an array like the one shown in the code above with the following components:
</li>
2143 <li><code>application
</code>:
2144 abbreviation of application
</li>
2145 <li><code>in-reply-to
</code> (optional):
2146 message id of the notification for the parent item and used to improve the ordering in threaded email clients
</li>
2147 <li><code>message-id
</code> (optional):
2148 message id of the notification mail and has to be used in
<code>in-reply-to
</code> and
<code>references
</code> for follow up mails
</li>
2149 <li><code>references
</code> (optional):
2150 all of the message ids of parent items (i.e. recursive in-reply-to)
</li>
2151 <li><code>template
</code>:
2152 name of the template used to render the email body, should start with
<code>email_
</code></li>
2153 <li><code>variables
</code> (optional):
2154 template variables passed to the email template where they can be accessed via
<code>$notificationContent[variables]
</code></li>
2156 <p>For daily emails (
<code>$notificationType = 'daily'
</code>), only
<code>application
</code>,
<code>template
</code>, and
<code>variables
</code> are supported.
2157 - The
<code>getEmailTitle()
</code> returns the title of the instant email sent to the user.
2158 By default,
<code>getEmailTitle()
</code> simply calls
<code>getTitle()
</code>.
2159 - The
<code>getEventHash()
</code> method returns a hash by which user notifications are grouped.
2160 Here, we want to group them not by the actual
<code>Foo
</code> object but by its parent
<code>Baz
</code> object and thus overwrite the default implementation provided by
<code>AbstractUserNotificationEvent
</code>.
2161 - The
<code>getLink()
</code> returns the link to the
<code>Foo
</code> object the notification belongs to.
2162 - The
<code>getMessage()
</code> method and the
<code>getTitle()
</code> return the message and the title of the user notification respectively.
2163 By checking the value of
<code>count($this-
>getAuthors())
</code>, we check if the notification is stacked, thus if the event has been triggered for multiple users so that different languages items are used.
2164 If your notification event does not support stacking, this distinction is not necessary.
2165 - The
<code>prepare()
</code> method is called for each user notification before all user notifications are rendered.
2166 This allows to tell runtime caches to prepare to load objects later on (see
<a href=
"../caches_runtime-caches/">Runtime Caches
</a>).
</p>
2167 <h2 id=
"firing-events">Firing Events
<a class=
"headerlink" href=
"#firing-events" title=
"Permanent link">#
</a></h2>
2168 <p>When the action related to a user notification is executed, you can use
<code>UserNotificationHandler::fireEvent()
</code> to create the notifications:
</p>
2169 <div class=
"highlight"><pre><span></span><code><span class=
"nv">$recipientIDs
</span> <span class=
"o">=
</span> <span class=
"p">[];
</span> <span class=
"c1">// fill with user ids of the recipients of the notification
</span>
2170 <span class=
"nx">UserNotificationHandler
</span><span class=
"o">::
</span><span class=
"na">getInstance
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">fireEvent
</span><span class=
"p">(
</span>
2171 <span class=
"s1">'bar
'</span><span class=
"p">,
</span> <span class=
"c1">// event name
</span>
2172 <span class=
"s1">'com.woltlab.example.foo
'</span><span class=
"p">,
</span> <span class=
"c1">// event object type name
</span>
2173 <span class=
"k">new
</span> <span class=
"nx">FooUserNotificationObject
</span><span class=
"p">(
</span><span class=
"k">new
</span> <span class=
"nx">Foo
</span><span class=
"p">(
</span><span class=
"nv">$fooID
</span><span class=
"p">)),
</span> <span class=
"c1">// object related to the event
</span>
2174 <span class=
"nv">$recipientIDs
</span>
2175 <span class=
"p">);
</span>
2177 <h2 id=
"marking-notifications-as-confirmed">Marking Notifications as Confirmed
<a class=
"headerlink" href=
"#marking-notifications-as-confirmed" title=
"Permanent link">#
</a></h2>
2178 <p>In some instances, you might want to manually mark user notifications as confirmed without the user manually confirming them, for example when they visit the page that is related to the user notification.
2179 In this case, you can use
<code>UserNotificationHandler::markAsConfirmed()
</code>:
</p>
2180 <div class=
"highlight"><pre><span></span><code><span class=
"nv">$recipientIDs
</span> <span class=
"o">=
</span> <span class=
"p">[];
</span> <span class=
"c1">// fill with user ids of the recipients of the notification
</span>
2181 <span class=
"nv">$fooIDs
</span> <span class=
"o">=
</span> <span class=
"p">[];
</span> <span class=
"c1">// fill with ids of related foo objects
</span>
2182 <span class=
"nx">UserNotificationHandler
</span><span class=
"o">::
</span><span class=
"na">getInstance
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">markAsConfirmed
</span><span class=
"p">(
</span>
2183 <span class=
"s1">'bar
'</span><span class=
"p">,
</span> <span class=
"c1">// event name
</span>
2184 <span class=
"s1">'com.woltlab.example.foo
'</span><span class=
"p">,
</span> <span class=
"c1">// event object type name
</span>
2185 <span class=
"nv">$recipientIDs
</span><span class=
"p">,
</span>
2186 <span class=
"nv">$fooIDs
</span>
2187 <span class=
"p">);
</span>
2202 <footer class=
"md-footer">
2204 <nav class=
"md-footer__inner md-grid" aria-label=
"Footer">
2206 <a href=
"../user_activity_points/" class=
"md-footer__link md-footer__link--prev" rel=
"prev">
2207 <div class=
"md-footer__button md-icon">
2208 <svg xmlns=
"http://www.w3.org/2000/svg" viewBox=
"0 0 24 24"><path d=
"M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"/></svg>
2210 <div class=
"md-footer__title">
2211 <div class=
"md-ellipsis">
2212 <span class=
"md-footer__direction">
2215 User Activity Points
2221 <a href=
"../sitemaps/" class=
"md-footer__link md-footer__link--next" rel=
"next">
2222 <div class=
"md-footer__title">
2223 <div class=
"md-ellipsis">
2224 <span class=
"md-footer__direction">
2230 <div class=
"md-footer__button md-icon">
2231 <svg xmlns=
"http://www.w3.org/2000/svg" viewBox=
"0 0 24 24"><path d=
"M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4z"/></svg>
2237 <div class=
"md-footer-meta md-typeset">
2238 <div class=
"md-footer-meta__inner md-grid">
2239 <div class=
"md-footer-copyright">
2241 <div class=
"md-footer-copyright__highlight">
2242 Copyright ©
2020 WoltLab GmbH
2246 <a href=
"https://squidfunk.github.io/mkdocs-material/" target=
"_blank" rel=
"noopener">
2251 <div class=
"md-footer-copyright">
2252 <a href=
"https://www.woltlab.com/legal-notice/">Legal Notice
</a>
2253 <a href=
"https://www.woltlab.com/privacy-policy/">Privacy Policy
</a>
2260 <div class=
"md-dialog" data-md-component=
"dialog">
2261 <div class=
"md-dialog__inner md-typeset"></div>
2263 <script id=
"__config" type=
"application/json">{
"base":
"../../..",
"features": [],
"translations": {
"clipboard.copy":
"Copy to clipboard",
"clipboard.copied":
"Copied to clipboard",
"search.config.lang":
"en",
"search.config.pipeline":
"trimmer, stopWordFilter",
"search.config.separator":
"[\\s\\-]+",
"search.placeholder":
"Search",
"search.result.placeholder":
"Type to start searching",
"search.result.none":
"No matching documents",
"search.result.one":
"1 matching document",
"search.result.other":
"# matching documents",
"search.result.more.one":
"1 more on this page",
"search.result.more.other":
"# more on this page",
"search.result.term.missing":
"Missing"},
"search":
"../../../assets/javascripts/workers/search.fb4a9340.min.js",
"version": {
"provider":
"mike"}}
</script>
2266 <script src=
"../../../assets/javascripts/bundle.5cf3e710.min.js"></script>