Skip to content

Commit d6640ae

Browse files
authored
Merge pull request #549 from WoltLab/6.2-tutorial-series
Check that the tutorial series is up to date with 6.2
2 parents 59fc50d + ff7b514 commit d6640ae

File tree

114 files changed

+642
-565
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

114 files changed

+642
-565
lines changed

docs/tutorial/series/overview.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ Note that in the context of this example, not every added feature might make per
99
- [Part 1: Base Structure](part_1.md)
1010
- [Part 2: Event and Template Listeners](part_2.md)
1111
- [Part 3: Person Page and Comments](part_3.md)
12+
<!---
1213
- [Part 4: Box and Box Conditions](part_4.md)
1314
- [Part 5: Person Information](part_5.md)
1415
- [Part 6: Activity Points and Activity Events](part_6.md)
16+
-->

docs/tutorial/series/part_1.md

Lines changed: 71 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ The package should provide the following possibilities/functions:
1818
We will use the following package installation plugins:
1919

2020
- [acpTemplate package installation plugin](../../package/pip/acp-template.md),
21-
- [acpMenu package installation plugin](../../package/pip/acp-menu.md),
2221
- [database package installation plugin](../../package/pip/database.md),
2322
- [file package installation plugin](../../package/pip/file.md),
2423
- [language package installation plugin](../../package/pip/language.md),
@@ -27,45 +26,68 @@ We will use the following package installation plugins:
2726
- [template package installation plugin](../../package/pip/template.md),
2827
- [userGroupOption package installation plugin](../../package/pip/user-group-option.md),
2928

30-
use [database objects](../../php/database-objects.md), create [pages](../../php/pages.md) and use [templates](../../view/templates.md).
29+
In addition, we use the following features:
30+
31+
- [ACP menu items](../../package/acp-menu-items.md)
32+
- [bootstrap scripts](../../package/bootstrap-scripts.md)
33+
- [database objects](../../php/database-objects.md)
34+
- [pages](../../php/pages.md)
35+
- [templates](../../view/templates.md)
3136

3237

3338
## Package Structure
3439

3540
The package will have the following file structure:
3641

3742
```
38-
├── acpMenu.xml
3943
├── acptemplates
40-
├── personAdd.tpl
41-
└── personList.tpl
44+
   ├── personAdd.tpl
45+
   └── personList.tpl
4246
├── files
43-
│ ├── acp
44-
│ │ └── database
45-
│ │ └── install_com.woltlab.wcf.people.php
46-
│ └── lib
47-
│ ├── acp
48-
│ │ ├── form
49-
│ │ │ ├── PersonAddForm.class.php
50-
│ │ │ └── PersonEditForm.class.php
51-
│ │ └── page
52-
│ │ └── PersonListPage.class.php
53-
│ ├── data
54-
│ │ └── person
55-
│ │ ├── Person.class.php
56-
│ │ ├── PersonAction.class.php
57-
│ │ ├── PersonEditor.class.php
58-
│ │ └── PersonList.class.php
59-
│ └── page
60-
│ └── PersonListPage.class.php
47+
│   ├── acp
48+
│   │   └── database
49+
│   │   └── install_com.woltlab.wcf.people.php
50+
│   └── lib
51+
│   ├── acp
52+
│   │   ├── form
53+
│   │   │   ├── PersonAddForm.class.php
54+
│   │   │   └── PersonEditForm.class.php
55+
│   │   └── page
56+
│   │   └── PersonListPage.class.php
57+
│   ├── bootstrap
58+
│   │   └── com.woltlab.wcf.people.php
59+
│   ├── data
60+
│   │   └── person
61+
│   │   ├── Person.class.php
62+
│   │   ├── PersonAction.class.php
63+
│   │   ├── PersonEditor.class.php
64+
│   │   └── PersonList.class.php
65+
│   ├── event
66+
│   │   └── gridView
67+
│   │   └── admin
68+
│   │   └── PersonGridViewInitialized.class.php
69+
│   ├── page
70+
│   │   └── PersonListPage.class.php
71+
│   └── system
72+
│   ├── endpoint
73+
│   │   └── controller
74+
│   │   └── core
75+
│   │   └── persons
76+
│   │   └── DeletePerson.class.php
77+
│   ├── gridView
78+
│   │   └── admin
79+
│   │   └── PersonGridView.class.php
80+
│   └── interaction
81+
│   └── admin
82+
│   └── PersonInteractions.class.php
6183
├── language
62-
├── de.xml
63-
└── en.xml
84+
   ├── de.xml
85+
   └── en.xml
6486
├── menuItem.xml
6587
├── package.xml
6688
├── page.xml
6789
├── templates
68-
└── personList.tpl
90+
   └── personList.tpl
6991
└── userGroupOption.xml
7092
```
7193

@@ -163,18 +185,20 @@ We need to create three menu items:
163185
1. a third level menu item for the people list page, and
164186
1. a fourth level menu item for the form to add new people.
165187

188+
We create the [menu entries](../../package/acp-menu-items.md) using a [bootstrap script](../../package/bootstrap-scripts.md):
189+
166190
{jinja{ codebox(
167-
title="acpMenu.xml",
168-
language="xml",
169-
filepath="tutorial/tutorial-series/part-1/acpMenu.xml"
191+
title="files/lib/bootstrap/com.woltlab.wcf.people.php",
192+
language="php",
193+
filepath="tutorial/tutorial-series/part-1/files/lib/bootstrap/com.woltlab.wcf.people.php"
170194
) }}
171195

172196
We choose `wcf.acp.menu.link.content` as the parent menu item for the first menu item `wcf.acp.menu.link.person` because the people we are managing is just one form of content.
173197
The fourth level menu item `wcf.acp.menu.link.person.add` will only be shown as an icon and thus needs an additional element `icon` which takes a FontAwesome icon class as value.
174198

175199
### People List
176200

177-
To list the people in the ACP, we need a `PersonListPage` class and a `personList` template.
201+
To list the people in the ACP, we need the classes `PersonListPage`, `PersonGridView`, and a `personList` template.
178202

179203
#### `PersonListPage`
180204

@@ -184,13 +208,26 @@ To list the people in the ACP, we need a `PersonListPage` class and a `personLis
184208
filepath="tutorial/tutorial-series/part-1/files/lib/acp/page/PersonListPage.class.php"
185209
) }}
186210

187-
As WoltLab Suite Core already provides a powerful default implementation of a sortable page, our work here is minimal:
211+
`PersonListPage` uses a [grid view](../../php/api/grid_views.md) to display the list of people, our work here is minimal:
188212

189213
1. We need to set the active ACP menu item via the `$activeMenuItem`.
190214
1. `$neededPermissions` contains a list of permissions of which the user needs to have at least one in order to see the person list.
191215
We use the same permission for both the menu item and the page.
192-
1. The database object list class whose name is provided via `$objectListClassName` and that handles fetching the people from database is the `PersonList` class, which we have already created.
193-
1. To validate the sort field passed with the request, we set `$validSortFields` to the available database table columns.
216+
1. Implement the method `createGridView()` and return the grid view that should be used to render the list of people.
217+
218+
#### `PersonGridView`
219+
220+
{jinja{ codebox(
221+
title="files/lib/system/gridView/admin/PersonGridView.class.php",
222+
language="php",
223+
filepath="tutorial/tutorial-series/part-1/files/lib/system/gridView/admin/PersonGridView.class.php"
224+
) }}
225+
226+
The following features are defined in the grid view:
227+
228+
1. The columns to be displayed and their order.
229+
1. Which columns can be sorted and what their default sorting is.
230+
1. What interaction options the user has with the displayed items.
194231

195232
#### `personList.tpl`
196233

@@ -207,17 +244,7 @@ We will go piece by piece through the template code:
207244
1. We set the content header and additional provide a button to create a new person in the content header navigation.
208245
1. As not all people are listed on the same page if many people have been created, we need a pagination for which we use the `pages` template plugin.
209246
The `{hascontent}{content}{/content}{/hascontent}` construct ensures the `.paginationTop` element is only shown if the `pages` template plugin has a return value, thus if a pagination is necessary.
210-
1. Now comes the main part of the page, the list of the people, which will only be displayed if any people exist.
211-
Otherwise, an info box is displayed using the generic `wcf.global.noItems` language item.
212-
The `$objects` template variable is automatically assigned by `wcf\page\MultipleLinkPage` and contains the `PersonList` object used to read the people from database.
213-
The table itself consists of a `thead` and a `tbody` element and is extendable with more columns using the template events `columnHeads` and `columns`.
214-
In general, every table should provide these events.
215-
The default structure of a table is used here so that the first column of the content rows contains icons to edit and to delete the row (and provides another standard event `rowButtons`) and that the second column contains the ID of the person.
216-
The table can be sorted by clicking on the head of each column.
217-
The used variables `$sortField` and `$sortOrder` are automatically assigned to the template by `SortablePage`.
218-
1. The `.contentFooter` element is only shown if people exist as it basically repeats the `.contentHeaderNavigation` and `.paginationTop` element.
219-
1. The delete button for each person shown in the `.columnIcon` element relies on the global [`WoltLabSuite/Core/Ui/Object/Action`](../../migration/wsc53/javascript.md#wcfactiondelete-and-wcfactiontoggle) module which only requires the `jsObjectActionContainer` CSS class in combination with the `data-object-action-class-name` attribute for the `table` element, the `jsObjectActionObject` CSS class for each person's `tr` element in combination with the `data-object-id` attribute, and lastly the delete button itself, which is created with the [`objectAction` template plugin](../../view/template-plugins.md#view/template-plugins/#54-objectaction).
220-
1. The [`.jsReloadPageWhenEmpty` CSS class](../../migration/wsc53/javascript.md#wcftableemptytablehandler) on the `tbody` element ensures that once all persons on the page have been deleted, the page is reloaded.
247+
1. For the main part of the page we only need to call the `render()` method of the grid view.
221248
1. Lastly, the `footer` template is included that terminates the page.
222249
You also have to include this template for every page!
223250

docs/tutorial/series/part_2.md

Lines changed: 18 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -40,23 +40,24 @@ The package will have the following file structure:
4040
```
4141
├── eventListener.xml
4242
├── files
43-
│ ├── acp
44-
│ │ └── database
45-
│ │ └── install_com.woltlab.wcf.people.birthday.php
46-
│ └── lib
47-
│ └── system
48-
│ └── event
49-
│ └── listener
50-
│ ├── BirthdayPersonAddFormListener.class.php
51-
│ └── BirthdaySortFieldPersonListPageListener.class.php
43+
│   ├── acp
44+
│   │   └── database
45+
│   │   └── install_com.woltlab.wcf.people.birthday.php
46+
│   └── lib
47+
│   ├── bootstrap
48+
│   │   └── com.woltlab.wcf.people.birthday.php
49+
│   └── system
50+
│   └── event
51+
│   └── listener
52+
│   └── BirthdayPersonAddFormListener.class.php
5253
├── language
53-
├── de.xml
54-
└── en.xml
54+
   ├── de.xml
55+
   └── en.xml
5556
├── package.xml
5657
├── templateListener.xml
57-
── templates
58-
├── __personListBirthday.tpl
59-
└── __personListBirthdaySortField.tpl
58+
── templates
59+
│   ├── __personListBirthday.tpl
60+
│   └── __personListBirthdaySortField.tpl
6061
```
6162

6263

@@ -118,35 +119,14 @@ The language item `wcf.person.birthday` used in the label is the only new one fo
118119

119120
## Adding Birthday Table Column in ACP
120121

121-
To add a birthday column to the person list page in the ACP, we need three parts:
122-
123-
1. an event listener that makes the `birthday` database table column a valid sort field,
124-
1. a template listener that adds the birthday column to the table’s head, and
125-
1. a template listener that adds the birthday column to the table’s rows.
126-
127-
The first part is a very simple class:
122+
To add a birthday column to the person list page in the ACP, we need to listen to the `PersonGridViewInitialized` event and add the additional column:
128123

129124
{jinja{ codebox(
130-
title="files/lib/system/event/listener/BirthdaySortFieldPersonListPageListener.class.php",
125+
title="files/lib/bootstrap/com.woltlab.wcf.people.birthday.php",
131126
language="php",
132-
filepath="tutorial/tutorial-series/part-2/files/lib/system/event/listener/BirthdaySortFieldPersonListPageListener.class.php"
127+
filepath="tutorial/tutorial-series/part-2/files/lib/bootstrap/com.woltlab.wcf.people.birthday.php"
133128
) }}
134129

135-
!!! info "We use `SortablePage` as a type hint instead of `wcf\acp\page\PersonListPage` because we will be using the same event listener class in the front end to also allow sorting that list by birthday."
136-
137-
As the relevant template codes are only one line each, we will simply put them directly in the `templateListener.xml` file that will be shown [later on](#templatelistenerxml).
138-
The code for the table head is similar to the other `th` elements:
139-
140-
```smarty
141-
<th class="columnDate columnBirthday{if $sortField == 'birthday'} active {$sortOrder}{/if}"><a href="{link controller='PersonList'}pageNo={$pageNo}&sortField=birthday&sortOrder={if $sortField == 'birthday' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.person.birthday{/lang}</a></th>
142-
```
143-
144-
For the table body’s column, we need to make sure that the birthday is only show if it is actually set:
145-
146-
```smarty
147-
<td class="columnDate columnBirthday">{if $person->birthday}{$person->birthday}{/if}</td>
148-
```
149-
150130

151131
## Adding Birthday in Front End
152132

docs/tutorial/series/part_3.md

Lines changed: 55 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -24,50 +24,66 @@ In addition to the components used in [part 1](part_1.md), we will use the [obje
2424
The complete package will have the following file structure (including the files from [part 1](part_1.md)):
2525

2626
```
27-
├── acpMenu.xml
2827
├── acptemplates
29-
├── personAdd.tpl
30-
└── personList.tpl
28+
   ├── personAdd.tpl
29+
   └── personList.tpl
3130
├── files
32-
│ ├── acp
33-
│ │ └── database
34-
│ │ └── install_com.woltlab.wcf.people.php
35-
│ └── lib
36-
│ ├── acp
37-
│ │ ├── form
38-
│ │ │ ├── PersonAddForm.class.php
39-
│ │ │ └── PersonEditForm.class.php
40-
│ │ └── page
41-
│ │ └── PersonListPage.class.php
42-
│ ├── data
43-
│ │ └── person
44-
│ │ ├── Person.class.php
45-
│ │ ├── PersonAction.class.php
46-
│ │ ├── PersonEditor.class.php
47-
│ │ └── PersonList.class.php
48-
│ ├── page
49-
│ │ ├── PersonListPage.class.php
50-
│ │ └── PersonPage.class.php
51-
│ └── system
52-
│ ├── cache
53-
│ │ └── runtime
54-
│ │ └── PersonRuntimeCache.class.php
55-
│ ├── comment
56-
│ │ └── manager
57-
│ │ └── PersonCommentManager.class.php
58-
│ └── page
59-
│ └── handler
60-
│ └── PersonPageHandler.class.php
31+
│   ├── acp
32+
│   │   └── database
33+
│   │   └── install_com.woltlab.wcf.people.php
34+
│   └── lib
35+
│   ├── acp
36+
│   │   ├── form
37+
│   │   │   ├── PersonAddForm.class.php
38+
│   │   │   └── PersonEditForm.class.php
39+
│   │   └── page
40+
│   │   └── PersonListPage.class.php
41+
│   ├── bootstrap
42+
│   │   └── com.woltlab.wcf.people.php
43+
│   ├── data
44+
│   │   └── person
45+
│   │   ├── Person.class.php
46+
│   │   ├── PersonAction.class.php
47+
│   │   ├── PersonEditor.class.php
48+
│   │   └── PersonList.class.php
49+
│   ├── event
50+
│   │   └── gridView
51+
│   │   └── admin
52+
│   │   └── PersonGridViewInitialized.class.php
53+
│   ├── page
54+
│   │   ├── PersonListPage.class.php
55+
│   │   └── PersonPage.class.php
56+
│   └── system
57+
│   ├── cache
58+
│   │   └── runtime
59+
│   │   └── PersonRuntimeCache.class.php
60+
│   ├── comment
61+
│   │   └── manager
62+
│   │   └── PersonCommentManager.class.php
63+
│   ├── endpoint
64+
│   │   └── controller
65+
│   │   └── core
66+
│   │   └── persons
67+
│   │   └── DeletePerson.class.php
68+
│   ├── gridView
69+
│   │   └── admin
70+
│   │   └── PersonGridView.class.php
71+
│   ├── interaction
72+
│   │   └── admin
73+
│   │   └── PersonInteractions.class.php
74+
│   └── page
75+
│   └── handler
76+
│   └── PersonPageHandler.class.php
6177
├── language
62-
├── de.xml
63-
└── en.xml
78+
   ├── de.xml
79+
   └── en.xml
6480
├── menuItem.xml
6581
├── objectType.xml
6682
├── package.xml
6783
├── page.xml
6884
├── templates
69-
├── person.tpl
70-
└── personList.tpl
85+
   ├── person.tpl
86+
   └── personList.tpl
7187
└── userGroupOption.xml
7288
```
7389

@@ -132,8 +148,8 @@ With this option, comments on individual people can be disabled.
132148

133149
The `PersonPage` class is similar to the `PersonEditForm` in the ACP in that it reads the id of the requested person from the request data and validates the id in `readParameters()`.
134150
The rest of the code only handles fetching the list of comments on the requested person.
135-
In `readData()`, this list is fetched using `CommentHandler::getCommentList()` if comments are enabled for the person.
136-
The `assignVariables()` method assigns some additional template variables like `$commentCanAdd`, which is `1` if the active person can add comments and is `0` otherwise, `$lastCommentTime`, which contains the UNIX timestamp of the last comment, and `$likeData`, which contains data related to the likes for the disabled comments.
151+
In `readData()`, this list is fetched using a `CommentsView` if comments are enabled for the person.
152+
The `assignVariables()` method assigns this view as a template variable.
137153

138154
### `person.tpl`
139155

@@ -144,10 +160,7 @@ The `assignVariables()` method assigns some additional template variables like `
144160
) }}
145161

146162
For now, the `person` template is still very empty and only shows the comments in the content area.
147-
The template code shown for comments is very generic and used in this form in many locations as it only sets the header of the comment list and the container `ul#personCommentList` element for the comments shown by `commentList` template.
148-
The `ul#personCommentList` elements has five additional `data-` attributes required by the JavaScript API for comments for loading more comments or creating new ones.
149-
The `commentListAddComment` template adds the WYSIWYG support.
150-
The attribute `wysiwygSelector` should be the id of the comment list `personCommentList` with an additional `AddComment` suffix.
163+
For the main part of the page we only need to call the `render()` method of the `CommentsView`.
151164

152165
### `page.xml`
153166

0 commit comments

Comments
 (0)