3 <html lang=
"en" class=
"no-js">
7 <meta name=
"viewport" content=
"width=device-width,initial-scale=1">
12 <link rel=
"icon" href=
"../../../assets/default.favicon.ico">
13 <meta name=
"generator" content=
"mkdocs-1.1.2, mkdocs-material-7.1.0">
17 <title>Events - WoltLab Suite Documentation
</title>
21 <link rel=
"stylesheet" href=
"../../../assets/stylesheets/main.33e2939f.min.css">
24 <link rel=
"stylesheet" href=
"../../../assets/stylesheets/palette.ef6f36e2.min.css">
28 <meta name=
"theme-color" content=
"#009485">
38 <link rel=
"stylesheet" href=
"../../../stylesheets/extra.css">
52 <body dir=
"ltr" data-md-color-scheme=
"" data-md-color-primary=
"teal" data-md-color-accent=
"">
55 <script>function __prefix(e){return new URL(
"../../..",location).pathname+
"."+e}function __get(e,t=localStorage){return JSON.parse(t.getItem(__prefix(e)))}
</script>
57 <input class=
"md-toggle" data-md-toggle=
"drawer" type=
"checkbox" id=
"__drawer" autocomplete=
"off">
58 <input class=
"md-toggle" data-md-toggle=
"search" type=
"checkbox" id=
"__search" autocomplete=
"off">
59 <label class=
"md-overlay" for=
"__drawer"></label>
60 <div data-md-component=
"skip">
63 <a href=
"#events" class=
"md-skip">
68 <div data-md-component=
"announce">
70 <aside class=
"md-announce">
71 <div class=
"md-announce__inner md-grid md-typeset">
73 <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" data-md-component=
"logo">
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">
109 <label class=
"md-header__button md-icon" for=
"__search">
110 <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>
113 <div class=
"md-search" data-md-component=
"search" role=
"dialog">
114 <label class=
"md-search__overlay" for=
"__search"></label>
115 <div class=
"md-search__inner" role=
"search">
116 <form class=
"md-search__form" name=
"search">
117 <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
>
118 <label class=
"md-search__icon md-icon" for=
"__search">
119 <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>
120 <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>
122 <button type=
"reset" class=
"md-search__icon md-icon" aria-label=
"Clear" tabindex=
"-1">
123 <svg xmlns=
"http://www.w3.org/2000/svg" viewBox=
"0 0 24 24"><path d=
"M19 6.41 17.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>
126 <div class=
"md-search__output">
127 <div class=
"md-search__scrollwrap" data-md-scrollfix
>
128 <div class=
"md-search-result" data-md-component=
"search-result">
129 <div class=
"md-search-result__meta">
132 <ol class=
"md-search-result__list"></ol>
140 <div class=
"md-header__source">
142 <a href=
"https://github.com/WoltLab/docs.woltlab.com/" title=
"Go to repository" class=
"md-source" data-md-component=
"source">
143 <div class=
"md-source__icon md-icon">
145 <svg xmlns=
"http://www.w3.org/2000/svg" viewBox=
"0 0 448 512"><path d=
"M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
147 <div class=
"md-source__repository">
156 <div class=
"md-container" data-md-component=
"container">
161 <main class=
"md-main" data-md-component=
"main">
162 <div class=
"md-main__inner md-grid">
166 <div class=
"md-sidebar md-sidebar--primary" data-md-component=
"sidebar" data-md-type=
"navigation" >
167 <div class=
"md-sidebar__scrollwrap">
168 <div class=
"md-sidebar__inner">
172 <nav class=
"md-nav md-nav--primary" aria-label=
"Navigation" data-md-level=
"0">
173 <label class=
"md-nav__title" for=
"__drawer">
174 <a href=
"../../.." title=
"WoltLab Suite Documentation" class=
"md-nav__button md-logo" aria-label=
"WoltLab Suite Documentation" data-md-component=
"logo">
176 <img src=
"../../../assets/logo.png" alt=
"logo">
179 WoltLab Suite Documentation
182 <div class=
"md-nav__source">
184 <a href=
"https://github.com/WoltLab/docs.woltlab.com/" title=
"Go to repository" class=
"md-source" data-md-component=
"source">
185 <div class=
"md-source__icon md-icon">
187 <svg xmlns=
"http://www.w3.org/2000/svg" viewBox=
"0 0 448 512"><path d=
"M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
189 <div class=
"md-source__repository">
195 <ul class=
"md-nav__list" data-md-scrollfix
>
204 <li class=
"md-nav__item">
205 <a href=
"../../../getting-started/" class=
"md-nav__link">
222 <li class=
"md-nav__item md-nav__item--active md-nav__item--nested">
225 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_2" type=
"checkbox" id=
"__nav_2" checked
>
227 <label class=
"md-nav__link" for=
"__nav_2">
229 <span class=
"md-nav__icon md-icon"></span>
231 <nav class=
"md-nav" aria-label=
"PHP API" data-md-level=
"1">
232 <label class=
"md-nav__title" for=
"__nav_2">
233 <span class=
"md-nav__icon md-icon"></span>
236 <ul class=
"md-nav__list" data-md-scrollfix
>
242 <li class=
"md-nav__item">
243 <a href=
"../../pages/" class=
"md-nav__link">
254 <li class=
"md-nav__item">
255 <a href=
"../../database-objects/" class=
"md-nav__link">
266 <li class=
"md-nav__item">
267 <a href=
"../../database-access/" class=
"md-nav__link">
278 <li class=
"md-nav__item">
279 <a href=
"../../exceptions/" class=
"md-nav__link">
293 <li class=
"md-nav__item md-nav__item--active md-nav__item--nested">
296 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_2_5" type=
"checkbox" id=
"__nav_2_5" checked
>
298 <label class=
"md-nav__link" for=
"__nav_2_5">
300 <span class=
"md-nav__icon md-icon"></span>
302 <nav class=
"md-nav" aria-label=
"API" data-md-level=
"2">
303 <label class=
"md-nav__title" for=
"__nav_2_5">
304 <span class=
"md-nav__icon md-icon"></span>
307 <ul class=
"md-nav__list" data-md-scrollfix
>
314 <li class=
"md-nav__item md-nav__item--nested">
317 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_2_5_1" type=
"checkbox" id=
"__nav_2_5_1" >
319 <label class=
"md-nav__link" for=
"__nav_2_5_1">
321 <span class=
"md-nav__icon md-icon"></span>
323 <nav class=
"md-nav" aria-label=
"Caches" data-md-level=
"3">
324 <label class=
"md-nav__title" for=
"__nav_2_5_1">
325 <span class=
"md-nav__icon md-icon"></span>
328 <ul class=
"md-nav__list" data-md-scrollfix
>
334 <li class=
"md-nav__item">
335 <a href=
"../caches/" class=
"md-nav__link">
346 <li class=
"md-nav__item">
347 <a href=
"../caches_persistent-caches/" class=
"md-nav__link">
358 <li class=
"md-nav__item">
359 <a href=
"../caches_runtime-caches/" class=
"md-nav__link">
376 <li class=
"md-nav__item">
377 <a href=
"../comments/" class=
"md-nav__link">
388 <li class=
"md-nav__item">
389 <a href=
"../cronjobs/" class=
"md-nav__link">
402 <li class=
"md-nav__item md-nav__item--active">
404 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"toc" type=
"checkbox" id=
"__toc">
409 <label class=
"md-nav__link md-nav__link--active" for=
"__toc">
411 <span class=
"md-nav__icon md-icon"></span>
414 <a href=
"./" class=
"md-nav__link md-nav__link--active">
419 <nav class=
"md-nav md-nav--secondary" aria-label=
"Table of contents">
425 <label class=
"md-nav__title" for=
"__toc">
426 <span class=
"md-nav__icon md-icon"></span>
429 <ul class=
"md-nav__list" data-md-component=
"toc" data-md-scrollfix
>
431 <li class=
"md-nav__item">
432 <a href=
"#introductory-example" class=
"md-nav__link">
438 <li class=
"md-nav__item">
439 <a href=
"#listening-to-events" class=
"md-nav__link">
445 <li class=
"md-nav__item">
446 <a href=
"#firing-events" class=
"md-nav__link">
450 <nav class=
"md-nav" aria-label=
"Firing Events">
451 <ul class=
"md-nav__list">
453 <li class=
"md-nav__item">
454 <a href=
"#example-using-parameters-argument" class=
"md-nav__link">
455 Example: Using $parameters argument
465 <li class=
"md-nav__item">
466 <a href=
"#advanced-example-additional-form-field" class=
"md-nav__link">
467 Advanced Example: Additional Form Field
485 <li class=
"md-nav__item md-nav__item--nested">
488 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_2_5_5" type=
"checkbox" id=
"__nav_2_5_5" >
490 <label class=
"md-nav__link" for=
"__nav_2_5_5">
492 <span class=
"md-nav__icon md-icon"></span>
494 <nav class=
"md-nav" aria-label=
"Form Builder" data-md-level=
"3">
495 <label class=
"md-nav__title" for=
"__nav_2_5_5">
496 <span class=
"md-nav__icon md-icon"></span>
499 <ul class=
"md-nav__list" data-md-scrollfix
>
505 <li class=
"md-nav__item">
506 <a href=
"../form_builder/overview/" class=
"md-nav__link">
517 <li class=
"md-nav__item">
518 <a href=
"../form_builder/structure/" class=
"md-nav__link">
529 <li class=
"md-nav__item">
530 <a href=
"../form_builder/form_fields/" class=
"md-nav__link">
541 <li class=
"md-nav__item">
542 <a href=
"../form_builder/validation_data/" class=
"md-nav__link">
553 <li class=
"md-nav__item">
554 <a href=
"../form_builder/dependencies/" class=
"md-nav__link">
571 <li class=
"md-nav__item">
572 <a href=
"../package_installation_plugins/" class=
"md-nav__link">
573 Package Installation Plugins
583 <li class=
"md-nav__item">
584 <a href=
"../user_activity_points/" class=
"md-nav__link">
595 <li class=
"md-nav__item">
596 <a href=
"../user_notifications/" class=
"md-nav__link">
607 <li class=
"md-nav__item">
608 <a href=
"../sitemaps/" class=
"md-nav__link">
625 <li class=
"md-nav__item">
626 <a href=
"../../code-style/" class=
"md-nav__link">
637 <li class=
"md-nav__item">
638 <a href=
"../../apps/" class=
"md-nav__link">
649 <li class=
"md-nav__item">
650 <a href=
"../../gdpr/" class=
"md-nav__link">
671 <li class=
"md-nav__item md-nav__item--nested">
674 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_3" type=
"checkbox" id=
"__nav_3" >
676 <label class=
"md-nav__link" for=
"__nav_3">
677 Languages, Templates & CSS
678 <span class=
"md-nav__icon md-icon"></span>
680 <nav class=
"md-nav" aria-label=
"Languages, Templates & CSS" data-md-level=
"1">
681 <label class=
"md-nav__title" for=
"__nav_3">
682 <span class=
"md-nav__icon md-icon"></span>
683 Languages, Templates & CSS
685 <ul class=
"md-nav__list" data-md-scrollfix
>
691 <li class=
"md-nav__item">
692 <a href=
"../../../view/languages/" class=
"md-nav__link">
703 <li class=
"md-nav__item">
704 <a href=
"../../../view/templates/" class=
"md-nav__link">
715 <li class=
"md-nav__item">
716 <a href=
"../../../view/template-plugins/" class=
"md-nav__link">
727 <li class=
"md-nav__item">
728 <a href=
"../../../view/css/" class=
"md-nav__link">
749 <li class=
"md-nav__item md-nav__item--nested">
752 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_4" type=
"checkbox" id=
"__nav_4" >
754 <label class=
"md-nav__link" for=
"__nav_4">
755 TypeScript and JavaScript API
756 <span class=
"md-nav__icon md-icon"></span>
758 <nav class=
"md-nav" aria-label=
"TypeScript and JavaScript API" data-md-level=
"1">
759 <label class=
"md-nav__title" for=
"__nav_4">
760 <span class=
"md-nav__icon md-icon"></span>
761 TypeScript and JavaScript API
763 <ul class=
"md-nav__list" data-md-scrollfix
>
769 <li class=
"md-nav__item">
770 <a href=
"../../../javascript/general-usage/" class=
"md-nav__link">
781 <li class=
"md-nav__item">
782 <a href=
"../../../javascript/typescript/" class=
"md-nav__link">
794 <li class=
"md-nav__item md-nav__item--nested">
797 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_4_3" type=
"checkbox" id=
"__nav_4_3" >
799 <label class=
"md-nav__link" for=
"__nav_4_3">
801 <span class=
"md-nav__icon md-icon"></span>
803 <nav class=
"md-nav" aria-label=
"New API" data-md-level=
"2">
804 <label class=
"md-nav__title" for=
"__nav_4_3">
805 <span class=
"md-nav__icon md-icon"></span>
808 <ul class=
"md-nav__list" data-md-scrollfix
>
814 <li class=
"md-nav__item">
815 <a href=
"../../../javascript/new-api_writing-a-module/" class=
"md-nav__link">
826 <li class=
"md-nav__item">
827 <a href=
"../../../javascript/new-api_data-structures/" class=
"md-nav__link">
838 <li class=
"md-nav__item">
839 <a href=
"../../../javascript/new-api_core/" class=
"md-nav__link">
850 <li class=
"md-nav__item">
851 <a href=
"../../../javascript/new-api_dom/" class=
"md-nav__link">
862 <li class=
"md-nav__item">
863 <a href=
"../../../javascript/new-api_events/" class=
"md-nav__link">
874 <li class=
"md-nav__item">
875 <a href=
"../../../javascript/new-api_ajax/" class=
"md-nav__link">
886 <li class=
"md-nav__item">
887 <a href=
"../../../javascript/new-api_dialogs/" class=
"md-nav__link">
898 <li class=
"md-nav__item">
899 <a href=
"../../../javascript/new-api_browser/" class=
"md-nav__link">
900 Browser and Screen Sizes
910 <li class=
"md-nav__item">
911 <a href=
"../../../javascript/new-api_ui/" class=
"md-nav__link">
928 <li class=
"md-nav__item">
929 <a href=
"../../../javascript/legacy-api/" class=
"md-nav__link">
940 <li class=
"md-nav__item">
941 <a href=
"../../../javascript/helper-functions/" class=
"md-nav__link">
952 <li class=
"md-nav__item">
953 <a href=
"../../../javascript/code-snippets/" class=
"md-nav__link">
974 <li class=
"md-nav__item md-nav__item--nested">
977 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_5" type=
"checkbox" id=
"__nav_5" >
979 <label class=
"md-nav__link" for=
"__nav_5">
981 <span class=
"md-nav__icon md-icon"></span>
983 <nav class=
"md-nav" aria-label=
"Package Components" data-md-level=
"1">
984 <label class=
"md-nav__title" for=
"__nav_5">
985 <span class=
"md-nav__icon md-icon"></span>
988 <ul class=
"md-nav__list" data-md-scrollfix
>
994 <li class=
"md-nav__item">
995 <a href=
"../../../package/package-xml/" class=
"md-nav__link">
1007 <li class=
"md-nav__item md-nav__item--nested">
1010 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_5_2" type=
"checkbox" id=
"__nav_5_2" >
1012 <label class=
"md-nav__link" for=
"__nav_5_2">
1014 <span class=
"md-nav__icon md-icon"></span>
1016 <nav class=
"md-nav" aria-label=
"PIPs" data-md-level=
"2">
1017 <label class=
"md-nav__title" for=
"__nav_5_2">
1018 <span class=
"md-nav__icon md-icon"></span>
1021 <ul class=
"md-nav__list" data-md-scrollfix
>
1027 <li class=
"md-nav__item">
1028 <a href=
"../../../package/pip/" class=
"md-nav__link">
1039 <li class=
"md-nav__item">
1040 <a href=
"../../../package/pip/acl-option/" class=
"md-nav__link">
1051 <li class=
"md-nav__item">
1052 <a href=
"../../../package/pip/acp-menu/" class=
"md-nav__link">
1063 <li class=
"md-nav__item">
1064 <a href=
"../../../package/pip/acp-search-provider/" class=
"md-nav__link">
1075 <li class=
"md-nav__item">
1076 <a href=
"../../../package/pip/acp-template/" class=
"md-nav__link">
1087 <li class=
"md-nav__item">
1088 <a href=
"../../../package/pip/bbcode/" class=
"md-nav__link">
1099 <li class=
"md-nav__item">
1100 <a href=
"../../../package/pip/box/" class=
"md-nav__link">
1111 <li class=
"md-nav__item">
1112 <a href=
"../../../package/pip/clipboard-action/" class=
"md-nav__link">
1123 <li class=
"md-nav__item">
1124 <a href=
"../../../package/pip/core-object/" class=
"md-nav__link">
1135 <li class=
"md-nav__item">
1136 <a href=
"../../../package/pip/cronjob/" class=
"md-nav__link">
1147 <li class=
"md-nav__item">
1148 <a href=
"../../../package/pip/database/" class=
"md-nav__link">
1159 <li class=
"md-nav__item">
1160 <a href=
"../../../package/pip/event-listener/" class=
"md-nav__link">
1171 <li class=
"md-nav__item">
1172 <a href=
"../../../package/pip/file/" class=
"md-nav__link">
1183 <li class=
"md-nav__item">
1184 <a href=
"../../../package/pip/language/" class=
"md-nav__link">
1195 <li class=
"md-nav__item">
1196 <a href=
"../../../package/pip/media-provider/" class=
"md-nav__link">
1207 <li class=
"md-nav__item">
1208 <a href=
"../../../package/pip/menu/" class=
"md-nav__link">
1219 <li class=
"md-nav__item">
1220 <a href=
"../../../package/pip/menu-item/" class=
"md-nav__link">
1231 <li class=
"md-nav__item">
1232 <a href=
"../../../package/pip/object-type/" class=
"md-nav__link">
1243 <li class=
"md-nav__item">
1244 <a href=
"../../../package/pip/object-type-definition/" class=
"md-nav__link">
1245 objectTypeDefinition
1255 <li class=
"md-nav__item">
1256 <a href=
"../../../package/pip/option/" class=
"md-nav__link">
1267 <li class=
"md-nav__item">
1268 <a href=
"../../../package/pip/page/" class=
"md-nav__link">
1279 <li class=
"md-nav__item">
1280 <a href=
"../../../package/pip/pip/" class=
"md-nav__link">
1291 <li class=
"md-nav__item">
1292 <a href=
"../../../package/pip/script/" class=
"md-nav__link">
1303 <li class=
"md-nav__item">
1304 <a href=
"../../../package/pip/smiley/" class=
"md-nav__link">
1315 <li class=
"md-nav__item">
1316 <a href=
"../../../package/pip/sql/" class=
"md-nav__link">
1327 <li class=
"md-nav__item">
1328 <a href=
"../../../package/pip/style/" class=
"md-nav__link">
1339 <li class=
"md-nav__item">
1340 <a href=
"../../../package/pip/template/" class=
"md-nav__link">
1351 <li class=
"md-nav__item">
1352 <a href=
"../../../package/pip/template-listener/" class=
"md-nav__link">
1363 <li class=
"md-nav__item">
1364 <a href=
"../../../package/pip/user-group-option/" class=
"md-nav__link">
1375 <li class=
"md-nav__item">
1376 <a href=
"../../../package/pip/user-menu/" class=
"md-nav__link">
1387 <li class=
"md-nav__item">
1388 <a href=
"../../../package/pip/user-notification-event/" class=
"md-nav__link">
1389 userNotificationEvent
1399 <li class=
"md-nav__item">
1400 <a href=
"../../../package/pip/user-option/" class=
"md-nav__link">
1411 <li class=
"md-nav__item">
1412 <a href=
"../../../package/pip/user-profile-menu/" class=
"md-nav__link">
1429 <li class=
"md-nav__item">
1430 <a href=
"../../../package/database-php-api/" class=
"md-nav__link">
1451 <li class=
"md-nav__item md-nav__item--nested">
1454 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_6" type=
"checkbox" id=
"__nav_6" >
1456 <label class=
"md-nav__link" for=
"__nav_6">
1458 <span class=
"md-nav__icon md-icon"></span>
1460 <nav class=
"md-nav" aria-label=
"Migration" data-md-level=
"1">
1461 <label class=
"md-nav__title" for=
"__nav_6">
1462 <span class=
"md-nav__icon md-icon"></span>
1465 <ul class=
"md-nav__list" data-md-scrollfix
>
1472 <li class=
"md-nav__item md-nav__item--nested">
1475 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_6_1" type=
"checkbox" id=
"__nav_6_1" >
1477 <label class=
"md-nav__link" for=
"__nav_6_1">
1478 Migrating from WSC
5.3
1479 <span class=
"md-nav__icon md-icon"></span>
1481 <nav class=
"md-nav" aria-label=
"Migrating from WSC 5.3" data-md-level=
"2">
1482 <label class=
"md-nav__title" for=
"__nav_6_1">
1483 <span class=
"md-nav__icon md-icon"></span>
1484 Migrating from WSC
5.3
1486 <ul class=
"md-nav__list" data-md-scrollfix
>
1492 <li class=
"md-nav__item">
1493 <a href=
"../../../migration/wsc53/php/" class=
"md-nav__link">
1504 <li class=
"md-nav__item">
1505 <a href=
"../../../migration/wsc53/session/" class=
"md-nav__link">
1506 Session Handling and Authentication
1516 <li class=
"md-nav__item">
1517 <a href=
"../../../migration/wsc53/javascript/" class=
"md-nav__link">
1518 TypeScript and JavaScript
1528 <li class=
"md-nav__item">
1529 <a href=
"../../../migration/wsc53/templates/" class=
"md-nav__link">
1540 <li class=
"md-nav__item">
1541 <a href=
"../../../migration/wsc53/libraries/" class=
"md-nav__link">
1542 Third Party Libraries
1559 <li class=
"md-nav__item md-nav__item--nested">
1562 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_6_2" type=
"checkbox" id=
"__nav_6_2" >
1564 <label class=
"md-nav__link" for=
"__nav_6_2">
1565 Migrating from WSC
5.2
1566 <span class=
"md-nav__icon md-icon"></span>
1568 <nav class=
"md-nav" aria-label=
"Migrating from WSC 5.2" data-md-level=
"2">
1569 <label class=
"md-nav__title" for=
"__nav_6_2">
1570 <span class=
"md-nav__icon md-icon"></span>
1571 Migrating from WSC
5.2
1573 <ul class=
"md-nav__list" data-md-scrollfix
>
1579 <li class=
"md-nav__item">
1580 <a href=
"../../../migration/wsc52/php/" class=
"md-nav__link">
1591 <li class=
"md-nav__item">
1592 <a href=
"../../../migration/wsc52/templates/" class=
"md-nav__link">
1593 Templates and Languages
1603 <li class=
"md-nav__item">
1604 <a href=
"../../../migration/wsc52/libraries/" class=
"md-nav__link">
1605 Third Party Libraries
1622 <li class=
"md-nav__item md-nav__item--nested">
1625 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_6_3" type=
"checkbox" id=
"__nav_6_3" >
1627 <label class=
"md-nav__link" for=
"__nav_6_3">
1628 Migrating from WSC
3.1
1629 <span class=
"md-nav__icon md-icon"></span>
1631 <nav class=
"md-nav" aria-label=
"Migrating from WSC 3.1" data-md-level=
"2">
1632 <label class=
"md-nav__title" for=
"__nav_6_3">
1633 <span class=
"md-nav__icon md-icon"></span>
1634 Migrating from WSC
3.1
1636 <ul class=
"md-nav__list" data-md-scrollfix
>
1642 <li class=
"md-nav__item">
1643 <a href=
"../../../migration/wsc31/php/" class=
"md-nav__link">
1661 <li class=
"md-nav__item md-nav__item--nested">
1664 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_6_4" type=
"checkbox" id=
"__nav_6_4" >
1666 <label class=
"md-nav__link" for=
"__nav_6_4">
1667 Migrating from WSC
3.0
1668 <span class=
"md-nav__icon md-icon"></span>
1670 <nav class=
"md-nav" aria-label=
"Migrating from WSC 3.0" data-md-level=
"2">
1671 <label class=
"md-nav__title" for=
"__nav_6_4">
1672 <span class=
"md-nav__icon md-icon"></span>
1673 Migrating from WSC
3.0
1675 <ul class=
"md-nav__list" data-md-scrollfix
>
1681 <li class=
"md-nav__item">
1682 <a href=
"../../../migration/wsc30/php/" class=
"md-nav__link">
1693 <li class=
"md-nav__item">
1694 <a href=
"../../../migration/wsc30/javascript/" class=
"md-nav__link">
1705 <li class=
"md-nav__item">
1706 <a href=
"../../../migration/wsc30/templates/" class=
"md-nav__link">
1717 <li class=
"md-nav__item">
1718 <a href=
"../../../migration/wsc30/css/" class=
"md-nav__link">
1729 <li class=
"md-nav__item">
1730 <a href=
"../../../migration/wsc30/package/" class=
"md-nav__link">
1748 <li class=
"md-nav__item md-nav__item--nested">
1751 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_6_5" type=
"checkbox" id=
"__nav_6_5" >
1753 <label class=
"md-nav__link" for=
"__nav_6_5">
1754 Migrating from WCF
2.1
1755 <span class=
"md-nav__icon md-icon"></span>
1757 <nav class=
"md-nav" aria-label=
"Migrating from WCF 2.1" data-md-level=
"2">
1758 <label class=
"md-nav__title" for=
"__nav_6_5">
1759 <span class=
"md-nav__icon md-icon"></span>
1760 Migrating from WCF
2.1
1762 <ul class=
"md-nav__list" data-md-scrollfix
>
1768 <li class=
"md-nav__item">
1769 <a href=
"../../../migration/wcf21/php/" class=
"md-nav__link">
1780 <li class=
"md-nav__item">
1781 <a href=
"../../../migration/wcf21/templates/" class=
"md-nav__link">
1792 <li class=
"md-nav__item">
1793 <a href=
"../../../migration/wcf21/css/" class=
"md-nav__link">
1804 <li class=
"md-nav__item">
1805 <a href=
"../../../migration/wcf21/package/" class=
"md-nav__link">
1832 <li class=
"md-nav__item md-nav__item--nested">
1835 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_7" type=
"checkbox" id=
"__nav_7" >
1837 <label class=
"md-nav__link" for=
"__nav_7">
1839 <span class=
"md-nav__icon md-icon"></span>
1841 <nav class=
"md-nav" aria-label=
"Tutorials" data-md-level=
"1">
1842 <label class=
"md-nav__title" for=
"__nav_7">
1843 <span class=
"md-nav__icon md-icon"></span>
1846 <ul class=
"md-nav__list" data-md-scrollfix
>
1853 <li class=
"md-nav__item md-nav__item--nested">
1856 <input class=
"md-nav__toggle md-toggle" data-md-toggle=
"__nav_7_1" type=
"checkbox" id=
"__nav_7_1" >
1858 <label class=
"md-nav__link" for=
"__nav_7_1">
1860 <span class=
"md-nav__icon md-icon"></span>
1862 <nav class=
"md-nav" aria-label=
"Tutorial Series" data-md-level=
"2">
1863 <label class=
"md-nav__title" for=
"__nav_7_1">
1864 <span class=
"md-nav__icon md-icon"></span>
1867 <ul class=
"md-nav__list" data-md-scrollfix
>
1873 <li class=
"md-nav__item">
1874 <a href=
"../../../tutorial/series/overview/" class=
"md-nav__link">
1885 <li class=
"md-nav__item">
1886 <a href=
"../../../tutorial/series/part_1/" class=
"md-nav__link">
1897 <li class=
"md-nav__item">
1898 <a href=
"../../../tutorial/series/part_2/" class=
"md-nav__link">
1909 <li class=
"md-nav__item">
1910 <a href=
"../../../tutorial/series/part_3/" class=
"md-nav__link">
1937 <div class=
"md-sidebar md-sidebar--secondary" data-md-component=
"sidebar" data-md-type=
"toc" >
1938 <div class=
"md-sidebar__scrollwrap">
1939 <div class=
"md-sidebar__inner">
1941 <nav class=
"md-nav md-nav--secondary" aria-label=
"Table of contents">
1947 <label class=
"md-nav__title" for=
"__toc">
1948 <span class=
"md-nav__icon md-icon"></span>
1951 <ul class=
"md-nav__list" data-md-component=
"toc" data-md-scrollfix
>
1953 <li class=
"md-nav__item">
1954 <a href=
"#introductory-example" class=
"md-nav__link">
1955 Introductory Example
1960 <li class=
"md-nav__item">
1961 <a href=
"#listening-to-events" class=
"md-nav__link">
1967 <li class=
"md-nav__item">
1968 <a href=
"#firing-events" class=
"md-nav__link">
1972 <nav class=
"md-nav" aria-label=
"Firing Events">
1973 <ul class=
"md-nav__list">
1975 <li class=
"md-nav__item">
1976 <a href=
"#example-using-parameters-argument" class=
"md-nav__link">
1977 Example: Using $parameters argument
1987 <li class=
"md-nav__item">
1988 <a href=
"#advanced-example-additional-form-field" class=
"md-nav__link">
1989 Advanced Example: Additional Form Field
2002 <div class=
"md-content" data-md-component=
"content">
2003 <article class=
"md-content__inner md-typeset">
2006 <a href=
"https://github.com/WoltLab/docs.woltlab.com/edit/5.4/docs/php/api/events.md" title=
"Edit this page" class=
"md-content__button md-icon">
2007 <svg xmlns=
"http://www.w3.org/2000/svg" viewBox=
"0 0 24 24"><path d=
"M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25z"/></svg>
2011 <h1 id=
"events">Events
<a class=
"headerlink" href=
"#events" title=
"Permanent link">#
</a></h1>
2012 <p>WoltLab Suite's event system allows manipulation of program flows and data without having to change any of the original source code.
2013 At many locations throughout the PHP code of WoltLab Suite Core and mainly through inheritance also in the applications and plugins, so called
<em>events
</em> are fired which trigger registered
<em>event listeners
</em> that get access to the object firing the event (or at least the class name if the event has been fired in a static method).
</p>
2014 <p>This page focuses on the technical aspects of events and event listeners,
<a href=
"../../../package/pip/event-listener/">the eventListener package installation plugin page
</a> covers how you can actually register an event listener.
2015 A comprehensive list of all available events is provided
<a href=
"../event_list/">here
</a>.
</p>
2016 <h2 id=
"introductory-example">Introductory Example
<a class=
"headerlink" href=
"#introductory-example" title=
"Permanent link">#
</a></h2>
2017 <p>Let's start with a simple example to illustrate how the event system works.
2018 Consider this pre-existing class:
</p>
2019 <div class=
"highlight"><pre><span></span><code><span class=
"o"><?
</span><span class=
"nx">php
</span>
2020 <span class=
"k">namespace
</span> <span class=
"nx">wcf\system\example
</span><span class=
"p">;
</span>
2021 <span class=
"k">use
</span> <span class=
"nx">wcf\system\event\EventHandler
</span><span class=
"p">;
</span>
2023 <span class=
"k">class
</span> <span class=
"nc">ExampleComponent
</span> <span class=
"p">{
</span>
2024 <span class=
"k">public
</span> <span class=
"nv">$var
</span> <span class=
"o">=
</span> <span class=
"mi">1</span><span class=
"p">;
</span>
2026 <span class=
"k">public
</span> <span class=
"k">function
</span> <span class=
"nf">getVar
</span><span class=
"p">()
</span> <span class=
"p">{
</span>
2027 <span class=
"nx">EventHandler
</span><span class=
"o">::
</span><span class=
"na">getInstance
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">fireAction
</span><span class=
"p">(
</span><span class=
"nv">$this
</span><span class=
"p">,
</span> <span class=
"s1">'getVar
'</span><span class=
"p">);
</span>
2029 <span class=
"k">return
</span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">var
</span><span class=
"p">;
</span>
2030 <span class=
"p">}
</span>
2031 <span class=
"p">}
</span>
2033 <p>where an event with event name
<code>getVar
</code> is fired in the
<code>getVar()
</code> method.
</p>
2034 <p>If you create an object of this class and call the
<code>getVar()
</code> method, the return value will be
<code>1</code>, of course:
</p>
2035 <div class=
"highlight"><pre><span></span><code><span class=
"o"><?
</span><span class=
"nx">php
</span>
2037 <span class=
"nv">$example
</span> <span class=
"o">=
</span> <span class=
"k">new
</span> <span class=
"nx">wcf\system\example\ExampleComponent
</span><span class=
"p">();
</span>
2038 <span class=
"k">if
</span> <span class=
"p">(
</span><span class=
"nv">$example
</span><span class=
"o">-
></span><span class=
"na">getVar
</span><span class=
"p">()
</span> <span class=
"o">==
</span> <span class=
"mi">1</span><span class=
"p">)
</span> <span class=
"p">{
</span>
2039 <span class=
"k">echo
</span> <span class=
"s2">"var is
1!
"</span><span class=
"p">;
</span>
2040 <span class=
"p">}
</span>
2041 <span class=
"k">else
</span> <span class=
"k">if
</span> <span class=
"p">(
</span><span class=
"nv">$example
</span><span class=
"o">-
></span><span class=
"na">getVar
</span><span class=
"p">()
</span> <span class=
"o">==
</span> <span class=
"mi">2</span><span class=
"p">)
</span> <span class=
"p">{
</span>
2042 <span class=
"k">echo
</span> <span class=
"s2">"var is
2!
"</span><span class=
"p">;
</span>
2043 <span class=
"p">}
</span>
2044 <span class=
"k">else
</span> <span class=
"p">{
</span>
2045 <span class=
"k">echo
</span> <span class=
"s2">"No, var is neither
1 nor
2.
"</span><span class=
"p">;
</span>
2046 <span class=
"p">}
</span>
2048 <span class=
"c1">// output: var is
1!
</span>
2050 <p>Now, consider that we have registered the following event listener to this event:
</p>
2051 <div class=
"highlight"><pre><span></span><code><span class=
"o"><?
</span><span class=
"nx">php
</span>
2052 <span class=
"k">namespace
</span> <span class=
"nx">wcf\system\event\listener
</span><span class=
"p">;
</span>
2054 <span class=
"k">class
</span> <span class=
"nc">ExampleEventListener
</span> <span class=
"k">implements
</span> <span class=
"nx">IParameterizedEventListener
</span> <span class=
"p">{
</span>
2055 <span class=
"k">public
</span> <span class=
"k">function
</span> <span class=
"nf">execute
</span><span class=
"p">(
</span><span class=
"nv">$eventObj
</span><span class=
"p">,
</span> <span class=
"nv">$className
</span><span class=
"p">,
</span> <span class=
"nv">$eventName
</span><span class=
"p">,
</span> <span class=
"k">array
</span> <span class=
"o">&</span><span class=
"nv">$parameters
</span><span class=
"p">)
</span> <span class=
"p">{
</span>
2056 <span class=
"nv">$eventObj
</span><span class=
"o">-
></span><span class=
"na">var
</span> <span class=
"o">=
</span> <span class=
"mi">2</span><span class=
"p">;
</span>
2057 <span class=
"p">}
</span>
2058 <span class=
"p">}
</span>
2060 <p>Whenever the event in the
<code>getVar()
</code> method is called, this method (of the same event listener object) is called.
2061 In this case, the value of the method's first parameter is the
<code>ExampleComponent
</code> object passed as the first argument of the
<code>EventHandler::fireAction()
</code> call in
<code>ExampleComponent::getVar()
</code>.
2062 As
<code>ExampleComponent::$var
</code> is a public property, the event listener code can change it and set it to
<code>2</code>.
</p>
2063 <p>If you now execute the example code from above again, the output will change from
<code>var is
1!
</code> to
<code>var is
2!
</code> because prior to returning the value, the event listener code changes the value from
<code>1</code> to
<code>2</code>.
</p>
2064 <p>This introductory example illustrates how event listeners can change data in a non-intrusive way.
2065 Program flow can be changed, for example, by throwing a
<code>wcf\system\exception\PermissionDeniedException
</code> if some additional constraint to access a page is not fulfilled.
</p>
2066 <h2 id=
"listening-to-events">Listening to Events
<a class=
"headerlink" href=
"#listening-to-events" title=
"Permanent link">#
</a></h2>
2067 <p>In order to listen to events, you need to register the event listener and the event listener itself needs to implement the interface
<code>wcf\system\event\listener\IParameterizedEventListener
</code> which only contains the
<code>execute
</code> method (see example above).
</p>
2068 <p>The first parameter
<code>$eventObj
</code> of the method contains the passed object where the event is fired or the name of the class in which the event is fired if it is fired from a static method.
2069 The second parameter
<code>$className
</code> always contains the name of the class where the event has been fired.
2070 The third parameter
<code>$eventName
</code> provides the name of the event within a class to uniquely identify the exact location in the class where the event has been fired.
2071 The last parameter
<code>$parameters
</code> is a reference to the array which contains additional data passed by the method firing the event.
2072 If no additional data is passed,
<code>$parameters
</code> is empty.
</p>
2073 <h2 id=
"firing-events">Firing Events
<a class=
"headerlink" href=
"#firing-events" title=
"Permanent link">#
</a></h2>
2074 <p>If you write code and want plugins to have access at certain points, you can fire an event on your own.
2075 The only thing to do is to call the
<code>wcf\system\event\EventHandler::fireAction($eventObj, $eventName, array
&$parameters = [])
</code> method and pass the following parameters:
</p>
2077 <li><code>$eventObj
</code> should be
<code>$this
</code> if you fire from an object context, otherwise pass the class name
<code>static::class
</code>.
</li>
2078 <li><code>$eventName
</code> identifies the event within the class and generally has the same name as the method.
2079 In cases, were you might fire more than one event in a method, for example before and after a certain piece of code, you can use the prefixes
<code>before*
</code> and
<code>after*
</code> in your event names.
</li>
2080 <li><code>$parameters
</code> is an optional array which allows you to pass additional data to the event listeners without having to make this data accessible via a property explicitly only created for this purpose.
2081 This additional data can either be just additional information for the event listeners about the context of the method call or allow the event listener to manipulate local data if the code, where the event has been fired, uses the passed data afterwards.
</li>
2083 <h3 id=
"example-using-parameters-argument">Example: Using
<code>$parameters
</code> argument
<a class=
"headerlink" href=
"#example-using-parameters-argument" title=
"Permanent link">#
</a></h3>
2084 <p>Consider the following method which gets some text that the methods parses.
</p>
2085 <div class=
"highlight"><pre><span></span><code><span class=
"o"><?
</span><span class=
"nx">php
</span>
2086 <span class=
"k">namespace
</span> <span class=
"nx">wcf\system\example
</span><span class=
"p">;
</span>
2087 <span class=
"k">use
</span> <span class=
"nx">wcf\system\event\EventHandler
</span><span class=
"p">;
</span>
2089 <span class=
"k">class
</span> <span class=
"nc">ExampleParser
</span> <span class=
"p">{
</span>
2090 <span class=
"k">public
</span> <span class=
"k">function
</span> <span class=
"nf">parse
</span><span class=
"p">(
</span><span class=
"nv">$text
</span><span class=
"p">)
</span> <span class=
"p">{
</span>
2091 <span class=
"c1">// [some parsing done by default]
</span>
2093 <span class=
"nv">$parameters
</span> <span class=
"o">=
</span> <span class=
"p">[
</span><span class=
"s1">'text
'</span> <span class=
"o">=
></span> <span class=
"nv">$text
</span><span class=
"p">];
</span>
2094 <span class=
"nx">EventHandler
</span><span class=
"o">::
</span><span class=
"na">getInstance
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">fireAction
</span><span class=
"p">(
</span><span class=
"nv">$this
</span><span class=
"p">,
</span> <span class=
"s1">'parse
'</span><span class=
"p">,
</span> <span class=
"nv">$parameters
</span><span class=
"p">);
</span>
2096 <span class=
"k">return
</span> <span class=
"nv">$parameters
</span><span class=
"p">[
</span><span class=
"s1">'text
'</span><span class=
"p">];
</span>
2097 <span class=
"p">}
</span>
2098 <span class=
"p">}
</span>
2100 <p>After the default parsing by the method itself, the author wants to enable plugins to do additional parsing and thus fires an event and passes the parsed text as an additional parameter.
2101 Then, a plugin can deliver the following event listener
</p>
2102 <div class=
"highlight"><pre><span></span><code><span class=
"o"><?
</span><span class=
"nx">php
</span>
2103 <span class=
"k">namespace
</span> <span class=
"nx">wcf\system\event\listener
</span><span class=
"p">;
</span>
2105 <span class=
"k">class
</span> <span class=
"nc">ExampleParserEventListener
</span> <span class=
"k">implements
</span> <span class=
"nx">IParameterizedEventListener
</span> <span class=
"p">{
</span>
2106 <span class=
"k">public
</span> <span class=
"k">function
</span> <span class=
"nf">execute
</span><span class=
"p">(
</span><span class=
"nv">$eventObj
</span><span class=
"p">,
</span> <span class=
"nv">$className
</span><span class=
"p">,
</span> <span class=
"nv">$eventName
</span><span class=
"p">,
</span> <span class=
"k">array
</span> <span class=
"o">&</span><span class=
"nv">$parameters
</span><span class=
"p">)
</span> <span class=
"p">{
</span>
2107 <span class=
"nv">$text
</span> <span class=
"o">=
</span> <span class=
"nv">$parameters
</span><span class=
"p">[
</span><span class=
"s1">'text
'</span><span class=
"p">];
</span>
2109 <span class=
"c1">// [some additional parsing which changes $text]
</span>
2111 <span class=
"nv">$parameters
</span><span class=
"p">[
</span><span class=
"s1">'text
'</span><span class=
"p">]
</span> <span class=
"o">=
</span> <span class=
"nv">$text
</span><span class=
"p">;
</span>
2112 <span class=
"p">}
</span>
2113 <span class=
"p">}
</span>
2115 <p>which can access the text via
<code>$parameters['text']
</code>.
</p>
2116 <p>This example can also be perfectly used to illustrate how to name multiple events in the same method.
2117 Let's assume that the author wants to enable plugins to change the text before and after the method does its own parsing and thus fires two events:
</p>
2118 <div class=
"highlight"><pre><span></span><code><span class=
"o"><?
</span><span class=
"nx">php
</span>
2119 <span class=
"k">namespace
</span> <span class=
"nx">wcf\system\example
</span><span class=
"p">;
</span>
2120 <span class=
"k">use
</span> <span class=
"nx">wcf\system\event\EventHandler
</span><span class=
"p">;
</span>
2122 <span class=
"k">class
</span> <span class=
"nc">ExampleParser
</span> <span class=
"p">{
</span>
2123 <span class=
"k">public
</span> <span class=
"k">function
</span> <span class=
"nf">parse
</span><span class=
"p">(
</span><span class=
"nv">$text
</span><span class=
"p">)
</span> <span class=
"p">{
</span>
2124 <span class=
"nv">$parameters
</span> <span class=
"o">=
</span> <span class=
"p">[
</span><span class=
"s1">'text
'</span> <span class=
"o">=
></span> <span class=
"nv">$text
</span><span class=
"p">];
</span>
2125 <span class=
"nx">EventHandler
</span><span class=
"o">::
</span><span class=
"na">getInstance
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">fireAction
</span><span class=
"p">(
</span><span class=
"nv">$this
</span><span class=
"p">,
</span> <span class=
"s1">'beforeParsing
'</span><span class=
"p">,
</span> <span class=
"nv">$parameters
</span><span class=
"p">);
</span>
2126 <span class=
"nv">$text
</span> <span class=
"o">=
</span> <span class=
"nv">$parameters
</span><span class=
"p">[
</span><span class=
"s1">'text
'</span><span class=
"p">];
</span>
2128 <span class=
"c1">// [some parsing done by default]
</span>
2130 <span class=
"nv">$parameters
</span> <span class=
"o">=
</span> <span class=
"p">[
</span><span class=
"s1">'text
'</span> <span class=
"o">=
></span> <span class=
"nv">$text
</span><span class=
"p">];
</span>
2131 <span class=
"nx">EventHandler
</span><span class=
"o">::
</span><span class=
"na">getInstance
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">fireAction
</span><span class=
"p">(
</span><span class=
"nv">$this
</span><span class=
"p">,
</span> <span class=
"s1">'afterParsing
'</span><span class=
"p">,
</span> <span class=
"nv">$parameters
</span><span class=
"p">);
</span>
2133 <span class=
"k">return
</span> <span class=
"nv">$parameters
</span><span class=
"p">[
</span><span class=
"s1">'text
'</span><span class=
"p">];
</span>
2134 <span class=
"p">}
</span>
2135 <span class=
"p">}
</span>
2137 <h2 id=
"advanced-example-additional-form-field">Advanced Example: Additional Form Field
<a class=
"headerlink" href=
"#advanced-example-additional-form-field" title=
"Permanent link">#
</a></h2>
2138 <p>One common reason to use event listeners is to add an additional field to a pre-existing form (in combination with template listeners, which we will not cover here).
2139 We will assume that users are able to do both, create and edit the objects via this form.
2140 The points in the program flow of
<a href=
"../../pages/#abstractform">AbstractForm
</a> that are relevant here are:
</p>
2142 <li>adding object (after the form has been submitted):
</li>
2143 <li>reading the value of the field
</li>
2144 <li>validating the read value
</li>
2146 <p>saving the additional value after successful validation and resetting locally stored value or assigning the current value of the field to the template after unsuccessful validation
</p>
2149 <p>editing object:
</p>
2151 <li>on initial form request:
<ol>
2152 <li>reading the pre-existing value of the edited object
</li>
2153 <li>assigning the field value to the template
</li>
2156 <li>after the form has been submitted:
<ol>
2157 <li>reading the value of the field
</li>
2158 <li>validating the read value
</li>
2159 <li>saving the additional value after successful validation
</li>
2160 <li>assigning the current value of the field to the template
</li>
2164 <p>All of these cases can be covered the by following code in which we assume that
<code>wcf\form\ExampleAddForm
</code> is the form to create example objects and that
<code>wcf\form\ExampleEditForm
</code> extends
<code>wcf\form\ExampleAddForm
</code> and is used for editing existing example objects.
</p>
2165 <div class=
"highlight"><pre><span></span><code><span class=
"o"><?
</span><span class=
"nx">php
</span>
2166 <span class=
"k">namespace
</span> <span class=
"nx">wcf\system\event\listener
</span><span class=
"p">;
</span>
2167 <span class=
"k">use
</span> <span class=
"nx">wcf\form\ExampleAddForm
</span><span class=
"p">;
</span>
2168 <span class=
"k">use
</span> <span class=
"nx">wcf\form\ExampleEditForm
</span><span class=
"p">;
</span>
2169 <span class=
"k">use
</span> <span class=
"nx">wcf\system\exception\UserInputException
</span><span class=
"p">;
</span>
2170 <span class=
"k">use
</span> <span class=
"nx">wcf\system\WCF
</span><span class=
"p">;
</span>
2172 <span class=
"k">class
</span> <span class=
"nc">ExampleAddFormListener
</span> <span class=
"k">implements
</span> <span class=
"nx">IParameterizedEventListener
</span> <span class=
"p">{
</span>
2173 <span class=
"k">protected
</span> <span class=
"nv">$var
</span> <span class=
"o">=
</span> <span class=
"mi">0</span><span class=
"p">;
</span>
2175 <span class=
"k">public
</span> <span class=
"k">function
</span> <span class=
"nf">execute
</span><span class=
"p">(
</span><span class=
"nv">$eventObj
</span><span class=
"p">,
</span> <span class=
"nv">$className
</span><span class=
"p">,
</span> <span class=
"nv">$eventName
</span><span class=
"p">,
</span> <span class=
"k">array
</span> <span class=
"o">&</span><span class=
"nv">$parameters
</span><span class=
"p">)
</span> <span class=
"p">{
</span>
2176 <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"nv">$eventName
</span><span class=
"p">(
</span><span class=
"nv">$eventObj
</span><span class=
"p">);
</span>
2177 <span class=
"p">}
</span>
2179 <span class=
"k">protected
</span> <span class=
"k">function
</span> <span class=
"nf">assignVariables
</span><span class=
"p">()
</span> <span class=
"p">{
</span>
2180 <span class=
"nx">WCF
</span><span class=
"o">::
</span><span class=
"na">getTPL
</span><span class=
"p">()
</span><span class=
"o">-
></span><span class=
"na">assign
</span><span class=
"p">(
</span><span class=
"s1">'var
'</span><span class=
"p">,
</span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">var
</span><span class=
"p">);
</span>
2181 <span class=
"p">}
</span>
2183 <span class=
"k">protected
</span> <span class=
"k">function
</span> <span class=
"nf">readData
</span><span class=
"p">(
</span><span class=
"nx">ExampleEditForm
</span> <span class=
"nv">$eventObj
</span><span class=
"p">)
</span> <span class=
"p">{
</span>
2184 <span class=
"k">if
</span> <span class=
"p">(
</span><span class=
"k">empty
</span><span class=
"p">(
</span><span class=
"nv">$_POST
</span><span class=
"p">))
</span> <span class=
"p">{
</span>
2185 <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">var
</span> <span class=
"o">=
</span> <span class=
"nv">$eventObj
</span><span class=
"o">-
></span><span class=
"na">example
</span><span class=
"o">-
></span><span class=
"na">var
</span><span class=
"p">;
</span>
2186 <span class=
"p">}
</span>
2187 <span class=
"p">}
</span>
2189 <span class=
"k">protected
</span> <span class=
"k">function
</span> <span class=
"nf">readFormParameters
</span><span class=
"p">()
</span> <span class=
"p">{
</span>
2190 <span class=
"k">if
</span> <span class=
"p">(
</span><span class=
"nb">isset
</span><span class=
"p">(
</span><span class=
"nv">$_POST
</span><span class=
"p">[
</span><span class=
"s1">'var
'</span><span class=
"p">]))
</span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">var
</span> <span class=
"o">=
</span> <span class=
"nb">intval
</span><span class=
"p">(
</span><span class=
"nv">$_POST
</span><span class=
"p">[
</span><span class=
"s1">'var
'</span><span class=
"p">]);
</span>
2191 <span class=
"p">}
</span>
2193 <span class=
"k">protected
</span> <span class=
"k">function
</span> <span class=
"nf">save
</span><span class=
"p">(
</span><span class=
"nx">ExampleAddForm
</span> <span class=
"nv">$eventObj
</span><span class=
"p">)
</span> <span class=
"p">{
</span>
2194 <span class=
"nv">$eventObj
</span><span class=
"o">-
></span><span class=
"na">additionalFields
</span> <span class=
"o">=
</span> <span class=
"nb">array_merge
</span><span class=
"p">(
</span><span class=
"nv">$eventObj
</span><span class=
"o">-
></span><span class=
"na">additionalFields
</span><span class=
"p">,
</span> <span class=
"p">[
</span><span class=
"s1">'var
'</span> <span class=
"o">=
></span> <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">var
</span><span class=
"p">]);
</span>
2195 <span class=
"p">}
</span>
2197 <span class=
"k">protected
</span> <span class=
"k">function
</span> <span class=
"nf">saved
</span><span class=
"p">()
</span> <span class=
"p">{
</span>
2198 <span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">var
</span> <span class=
"o">=
</span> <span class=
"mi">0</span><span class=
"p">;
</span>
2199 <span class=
"p">}
</span>
2201 <span class=
"k">protected
</span> <span class=
"k">function
</span> <span class=
"nf">validate
</span><span class=
"p">()
</span> <span class=
"p">{
</span>
2202 <span class=
"k">if
</span> <span class=
"p">(
</span><span class=
"nv">$this
</span><span class=
"o">-
></span><span class=
"na">var
</span> <span class=
"o"><</span> <span class=
"mi">0</span><span class=
"p">)
</span> <span class=
"p">{
</span>
2203 <span class=
"k">throw
</span> <span class=
"k">new
</span> <span class=
"nx">UserInputException
</span><span class=
"p">(
</span><span class=
"s1">'var
'</span><span class=
"p">,
</span> <span class=
"s1">'isNegative
'</span><span class=
"p">);
</span>
2204 <span class=
"p">}
</span>
2205 <span class=
"p">}
</span>
2206 <span class=
"p">}
</span>
2208 <p>The
<code>execute
</code> method in this example just delegates the call to a method with the same name as the event so that this class mimics the structure of a form class itself.
2209 The form object is passed to the methods but is only given in the method signatures as a parameter here whenever the form object is actually used.
2210 Furthermore, the type-hinting of the parameter illustrates in which contexts the method is actually called which will become clear in the following discussion of the individual methods:
</p>
2212 <li><code>assignVariables()
</code> is called for the add and the edit form and simply assigns the current value of the variable to the template.
</li>
2213 <li><code>readData()
</code> reads the pre-existing value of
<code>$var
</code> if the form has not been submitted and thus is only relevant when editing objects which is illustrated by the explicit type-hint of
<code>ExampleEditForm
</code>.
</li>
2214 <li><code>readFormParameters()
</code> reads the value for both, the add and the edit form.
</li>
2215 <li><code>save()
</code> is, of course, also relevant in both cases but requires the form object to store the additional value in the
<code>wcf\form\AbstractForm::$additionalFields
</code> array which can be used if a
<code>var
</code> column has been added to the database table in which the example objects are stored.
</li>
2216 <li><code>saved()
</code> is only called for the add form as it clears the internal value so that in the
<code>assignVariables()
</code> call, the default value will be assigned to the template to create an
"empty" form.
2217 During edits, this current value is the actual value that should be shown.
</li>
2218 <li><code>validate()
</code> also needs to be called in both cases as the input data always has to be validated.
</li>
2220 <p>Lastly, the following XML file has to be used to register the event listeners (you can find more information about how to register event listeners on
<a href=
"../../../package/pip/event-listener/">the eventListener package installation plugin page
</a>):
</p>
2221 <div class=
"highlight"><pre><span></span><code><span class=
"cp"><?xml version=
"1.0" encoding=
"UTF-
8"?
></span>
2222 <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/eventListener.xsd
"</span><span class=
"nt">></span>
2223 <span class=
"nt"><import
></span>
2224 <span class=
"nt"><eventlistener
</span> <span class=
"na">name=
</span><span class=
"s">"exampleAddInherited
"</span><span class=
"nt">></span>
2225 <span class=
"nt"><eventclassname
></span>wcf\form\ExampleAddForm
<span class=
"nt"></eventclassname
></span>
2226 <span class=
"nt"><eventname
></span>assignVariables,readFormParameters,save,validate
<span class=
"nt"></eventname
></span>
2227 <span class=
"nt"><listenerclassname
></span>wcf\system\event\listener\ExampleAddFormListener
<span class=
"nt"></listenerclassname
></span>
2228 <span class=
"nt"><inherit
></span>1<span class=
"nt"></inherit
></span>
2229 <span class=
"nt"></eventlistener
></span>
2231 <span class=
"nt"><eventlistener
</span> <span class=
"na">name=
</span><span class=
"s">"exampleAdd
"</span><span class=
"nt">></span>
2232 <span class=
"nt"><eventclassname
></span>wcf\form\ExampleAddForm
<span class=
"nt"></eventclassname
></span>
2233 <span class=
"nt"><eventname
></span>saved
<span class=
"nt"></eventname
></span>
2234 <span class=
"nt"><listenerclassname
></span>wcf\system\event\listener\ExampleAddFormListener
<span class=
"nt"></listenerclassname
></span>
2235 <span class=
"nt"></eventlistener
></span>
2237 <span class=
"nt"><eventlistener
</span> <span class=
"na">name=
</span><span class=
"s">"exampleEdit
"</span><span class=
"nt">></span>
2238 <span class=
"nt"><eventclassname
></span>wcf\form\ExampleEditForm
<span class=
"nt"></eventclassname
></span>
2239 <span class=
"nt"><eventname
></span>readData
<span class=
"nt"></eventname
></span>
2240 <span class=
"nt"><listenerclassname
></span>wcf\system\event\listener\ExampleAddFormListener
<span class=
"nt"></listenerclassname
></span>
2241 <span class=
"nt"></eventlistener
></span>
2242 <span class=
"nt"></import
></span>
2243 <span class=
"nt"></data
></span>
2250 <div class=
"md-source-date">
2253 Last update:
2021-
01-
08
2272 <footer class=
"md-footer">
2274 <nav class=
"md-footer__inner md-grid" aria-label=
"Footer">
2276 <a href=
"../cronjobs/" class=
"md-footer__link md-footer__link--prev" rel=
"prev">
2277 <div class=
"md-footer__button md-icon">
2278 <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>
2280 <div class=
"md-footer__title">
2281 <div class=
"md-ellipsis">
2282 <span class=
"md-footer__direction">
2291 <a href=
"../form_builder/overview/" class=
"md-footer__link md-footer__link--next" rel=
"next">
2292 <div class=
"md-footer__title">
2293 <div class=
"md-ellipsis">
2294 <span class=
"md-footer__direction">
2300 <div class=
"md-footer__button md-icon">
2301 <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>
2307 <div class=
"md-footer-meta md-typeset">
2308 <div class=
"md-footer-meta__inner md-grid">
2309 <div class=
"md-footer-copyright">
2311 <div class=
"md-footer-copyright__highlight">
2312 Copyright ©
2020 WoltLab GmbH
2316 <a href=
"https://squidfunk.github.io/mkdocs-material/" target=
"_blank" rel=
"noopener">
2321 <div class=
"md-footer-copyright">
2322 <a href=
"https://www.woltlab.com/legal-notice/">Legal Notice
</a>
2323 <a href=
"https://www.woltlab.com/privacy-policy/">Privacy Policy
</a>
2330 <div class=
"md-dialog" data-md-component=
"dialog">
2331 <div class=
"md-dialog__inner md-typeset"></div>
2333 <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.fe42c31b.min.js",
"version": {
"provider":
"mike"}}
</script>
2336 <script src=
"../../../assets/javascripts/bundle.d892486b.min.js"></script>