Unify titles of tutorial series parts
[GitHub/WoltLab/woltlab.github.io.git] / docs / tutorial / series / part_3.md
CommitLineData
376b2543 1# Part 3: Person Page and Comments
88aa7dc5
MS
2
3In this part of our tutorial series, we will add a new front end page to our package that is dedicated to each person and shows their personal details.
4To make good use of this new page and introduce a new API of WoltLab Suite, we will add the opportunity for users to comment on the person using WoltLab Suite’s reusable comment functionality.
5
6
7## Package Functionality
8
7e276cf9 9In addition to the existing functions from [part 1](part_1.md), the package will provide the following possibilities/functions after this part of the tutorial:
88aa7dc5
MS
10
11- Details page for each person linked in the front end person list
12- Comment on people on their respective page (can be disabled per person)
13- User online location for person details page with name and link to person details page
14- Create menu items linking to specific person details pages
15
16
17## Used Components
18
7e276cf9 19In addition to the components used in [part 1](part_1.md), we will use the [objectType package installation plugin](../../package/pip/object-type.md), use the [comment API](../../php/api/comments.md), create a [runtime cache](../../php/api/caches_runtime-caches.md), and create a page handler.
88aa7dc5
MS
20
21
22## Package Structure
23
7e276cf9 24The complete package will have the following file structure (including the files from [part 1](part_1.md)):
88aa7dc5
MS
25
26```
27├── acpMenu.xml
28├── acptemplates
60ed94fa
MS
29│ ├── personAdd.tpl
30│ └── personList.tpl
88aa7dc5 31├── files
60ed94fa
MS
32│ └── lib
33│ ├── acp
34│ │ ├── form
35│ │ │ ├── PersonAddForm.class.php
36│ │ │ └── PersonEditForm.class.php
37│ │ └── page
38│ │ └── PersonListPage.class.php
39│ ├── data
40│ │ └── person
41│ │ ├── Person.class.php
42│ │ ├── PersonAction.class.php
43│ │ ├── PersonEditor.class.php
44│ │ └── PersonList.class.php
45│ ├── page
46│ │ ├── PersonListPage.class.php
47│ │ └── PersonPage.class.php
48│ └── system
49│ ├── cache
50│ │ └── runtime
51│ │ └── PersonRuntimeCache.class.php
52│ ├── comment
53│ │ └── manager
54│ │ └── PersonCommentManager.class.php
55│ └── page
56│ └── handler
57│ └── PersonPageHandler.class.php
88aa7dc5
MS
58├── install.sql
59├── language
60ed94fa
MS
60│ ├── de.xml
61│ └── en.xml
88aa7dc5
MS
62├── menuItem.xml
63├── objectType.xml
64├── package.xml
65├── page.xml
66├── templates
60ed94fa
MS
67│ ├── person.tpl
68│ └── personList.tpl
88aa7dc5
MS
69└── userGroupOption.xml
70```
71
c51176db 72!!! warning "We will not mention every code change between the first part and this part, as we only want to focus on the important, new parts of the code. For example, there is a new `Person::getLink()` method and new language items have been added. For all changes, please refer to the [source code on GitHub]({jinja{ repo_url }}tree/{jinja{ edit_uri.split("/")[1] }}/snippets/tutorial/tutorial-series/part-3)."
88aa7dc5
MS
73
74
75## Runtime Cache
76
21609ed2 77To reduce the number of database queries when different APIs require person objects, we implement a [runtime cache](../../php/api/caches_runtime-caches.md) for people:
88aa7dc5 78
85e6151d
MS
79```php
80--8<-- "tutorial/tutorial-series/part-3/files/lib/system/cache/runtime/PersonRuntimeCache.class.php"
81```
88aa7dc5
MS
82
83
84## Comments
85
86To allow users to comment on people, we need to tell the system that people support comments.
87This is done by registering a `com.woltlab.wcf.comment.commentableContent` object type whose processor implements [ICommentManager](https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/comment/manager/ICommentManager.class.php):
88
85e6151d
MS
89```xml
90--8<-- "tutorial/tutorial-series/part-3/objectType.xml"
91```
88aa7dc5
MS
92
93The `PersonCommentManager` class extended `ICommentManager`’s default implementation [AbstractCommentManager](https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/comment/manager/AbstractCommentManager.class.php):
94
85e6151d
MS
95```php
96--8<-- "tutorial/tutorial-series/part-3/files/lib/system/comment/manager/PersonCommentManager.class.php"
97```
88aa7dc5
MS
98
99- First, the system is told the names of the permissions via the `$permission*` properties.
21609ed2 100 More information about comment permissions can be found [here](../../php/api/comments.md#user-group-options).
88aa7dc5
MS
101- The `getLink()` method returns the link to the person with the passed comment id.
102 As in `isAccessible()`, `PersonRuntimeCache` is used to potentially save database queries.
103- The `isAccessible()` method checks if the active user can access the relevant person.
104 As we do not have any special restrictions for accessing people, we only need to check if the person exists.
105- The `getTitle()` method returns the title used for comments and responses, which is just a generic language item in this case.
106- The `updateCounter()` updates the comments’ counter of the person.
107 We have added a new `comments` database table column to the `wcf1_person` database table in order to keep track on the number of comments.
108
abb300ed 109Additionally, we have added a new `enableComments` database table column to the `wcf1_person` database table whose value can be set when creating or editing a person in the ACP.
88aa7dc5
MS
110With this option, comments on individual people can be disabled.
111
9003992d 112!!! info "Liking comments is already built-in and only requires some extra code in the `PersonPage` class for showing the likes of pre-loaded comments."
88aa7dc5
MS
113
114
115## Person Page
116
117### `PersonPage`
118
85e6151d
MS
119```php
120--8<-- "tutorial/tutorial-series/part-3/files/lib/page/PersonPage.class.php"
121```
88aa7dc5
MS
122
123The `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()`.
124The rest of the code only handles fetching the list of comments on the requested person.
125In `readData()`, this list is fetched using `CommentHandler::getCommentList()` if comments are enabled for the person.
126The `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.
127
128### `person.tpl`
129
85e6151d
MS
130```tpl
131--8<-- "tutorial/tutorial-series/part-3/templates/person.tpl"
132```
88aa7dc5
MS
133
134For now, the `person` template is still very empty and only shows the comments in the content area.
eb0aecac 135The 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.
88aa7dc5 136The `ul#personCommentList` elements has five additional `data-` attributes required by the JavaScript API for comments for loading more comments or creating new ones.
eb0aecac
MS
137The `commentListAddComment` template adds the WYSIWYG support.
138The attribute `wysiwygSelector` should be the id of the comment list `personCommentList` with an additional `AddComment` suffix.
88aa7dc5
MS
139
140### `page.xml`
141
85e6151d
MS
142```xml
143--8<-- "tutorial/tutorial-series/part-3/page.xml"
144```
88aa7dc5
MS
145
146The `page.xml` file has been extended for the new person page with identifier `com.woltlab.wcf.people.Person`.
147Compared to the pre-existing `com.woltlab.wcf.people.PersonList` page, there are four differences:
148
1491. It has a `<handler>` element with a class name as value.
150 This aspect will be discussed in more detail in the next section.
1511. There are no `<content>` elements because, both, the title and the content of the page are dynamically generated in the template.
1521. The `<requireObjectID>` tells the system that this page requires an object id to properly work, in this case a valid person id.
1531. This page has a `<parent>` page, the person list page.
154 In general, the details page for any type of object that is listed on a different page has the list page as its parent.
155
156### `PersonPageHandler`
157
85e6151d
MS
158```php
159--8<-- "tutorial/tutorial-series/part-3/files/lib/system/page/handler/PersonPageHandler.class.php"
160```
88aa7dc5
MS
161
162Like any page handler, the `PersonPageHandler` class has to implement the [IMenuPageHandler](https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/page/handler/IMenuPageHandler.class.php) interface, which should be done by extending the [AbstractMenuPageHandler](https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/page/handler/AbstractMenuPageHandler.class.php) class.
163As we want administrators to link to specific people in menus, for example, we have to also implement the [ILookupPageHandler](https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/page/handler/ILookupPageHandler.class.php) interface by extending the [AbstractLookupPageHandler](https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/page/handler/AbstractLookupPageHandler.class.php) class.
164
165For the `ILookupPageHandler` interface, we need to implement three methods:
166
1671. `getLink($objectID)` returns the link to the person page with the given id.
168 In this case, we simply delegate this method call to the `Person` object returned by `PersonRuntimeCache::getObject()`.
1691. `isValid($objectID)` returns `true` if the person with the given id exists, otherwise `false`.
170 Here, we use `PersonRuntimeCache::getObject()` again and check if the return value is `null`, which is the case for non-existing people.
1711. `lookup($searchString)` is used when setting up an internal link and when searching for the linked person.
172 This method simply searches the first and last name of the people and returns an array with the person data.
173 While the `link`, the `objectID`, and the `title` element are self-explanatory, the `image` element can either contain an HTML `<img>` tag, which is displayed next to the search result (WoltLab Suite uses an image tag for users showing their avatar, for example), or a FontAwesome icon class (starting with `fa-`).
174
175Additionally, the class also implements [IOnlineLocationPageHandler](https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/page/handler/IOnlineLocationPageHandler.class.php) which is used to determine the online location of users.
176To ensure upwards-compatibility if the `IOnlineLocationPageHandler` interface changes, the [TOnlineLocationPageHandler](https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/page/handler/TOnlineLocationPageHandler.class.php) trait is used.
177The `IOnlineLocationPageHandler` interface requires two methods to be implemented:
178
1791. `getOnlineLocation(Page $page, UserOnline $user)` returns the textual description of the online location.
180 The language item for the user online locations should use the pattern `wcf.page.onlineLocation.{page identifier}`.
1811. `prepareOnlineLocation(Page $page, UserOnline $user)` is called for each user online before the `getOnlineLocation()` calls.
182 In this case, calling `prepareOnlineLocation()` first enables us to add all relevant person ids to the person runtime cache so that for all `getOnlineLocation()` calls combined, only one database query is necessary to fetch all person objects.
183
184---
185
186This concludes the third part of our tutorial series after which each person has a dedicated page on which people can comment on the person.
187
c51176db 188The complete source code of this part can be found on [GitHub]({jinja{ repo_url }}tree/{jinja{ edit_uri.split("/")[1] }}/snippets/tutorial/tutorial-series/part-3).
88aa7dc5 189