Comments can now be set to require approval by a moderator before being published. This feature is disabled by default if you do not provide a permission in the manager class, enabling it requires a new permission that has to be provided in a special property of your manage implementation.
-{jinja{ codebox(
- language="php",
- title="files/lib/system/comment/manager/ExampleCommentManager.class.php",
- contents="""
+```php title="files/lib/system/comment/manager/ExampleCommentManager.class.php"
<?php
class ExampleCommentManager extends AbstractCommentManager {
protected $permissionAddWithoutModeration = 'foo.bar.example.canAddCommentWithoutModeration';
}
-"""
-) }}
+```
## Raw HTML in User Activity Events
User activity events were previously encapsulated inside `<div class="htmlContent">…</div>`, with impacts on native elements such as lists. You can now disable the class usage by defining your event as raw HTML:
-{jinja{ codebox(
- language="php",
- title="files/lib/system/user/activity/event/ExampleUserActivityEvent.class.php",
- contents="""
+```php title="files/lib/system/user/activity/event/ExampleUserActivityEvent.class.php"
<?php
class ExampleUserActivityEvent {
// enables raw HTML for output, defaults to `false`
protected $isRawHtml = true;
}
-"""
-) }}
+```
## Permission to View Likes of an Object
Implement the interface `\wcf\data\like\IRestrictedLikeObjectTypeProvider` in your object provider to add support for this new permission check.
-{jinja{ codebox(
- language="php",
- title="files/lib/data/example/LikeableExampleProvider.class.php",
- contents="""
+```php title="files/lib/data/example/LikeableExampleProvider.class.php"
<?php
class LikeableExampleProvider extends ExampleProvider implements IRestrictedLikeObjectTypeProvider, IViewableLikeProvider {
public function canViewLikes(ILikeObject $object) {
return true;
}
}
-"""
-) }}
+```
## Developer Tools: Sync Feature
There's another feature that allows all matching PIPs to be executed in a row using a single button click. In order to solve dependencies on other PIPs, any implementing PIP must also provide the method `getSyncDependencies()` that returns the dependent PIPs in an arbitrary order.
-{jinja{ codebox(
- language="php",
- title="files/lib/data/package/plugin/ExamplePackageInstallationPlugin.class.php",
- contents="""
+```php title="files/lib/data/package/plugin/ExamplePackageInstallationPlugin.class.php"
<?php
class ExamplePackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin implements IIdempotentPackageInstallationPlugin {
public static function getSyncDependencies() {
return [];
}
}
-"""
-) }}
+```
## Media Providers
To adjust entries in the Recent Activity, only three small steps are necessary. First we pass the concrete reaction to the language variable, so that we can use the reaction object there. To do this, we add the following variable to the text of the `\wcf\system\user\activity\event\IUserActivityEvent` object: `$event->reactionType`. Typically we name the variable `reactionType`. In the second step, we mark the event as compatible. Therefore we set the parameter `supportsReactions` in the [`objectType.xml`](../../package/pip/object-type.md) to `1`. So for example the entry looks like this:
-{jinja{ codebox(
-language="xml",
-title="objectType.xml",
-contents="""
+```xml title="objectType.xml"
<type>
<name>com.woltlab.example.likeableObject.recentActivityEvent</name>
<definitionname>com.woltlab.wcf.user.recentActivityEvent</definitionname>
- <classname>wcf\system\\user\activity\event\LikeableObjectUserActivityEvent</classname>
+ <classname>wcf\system\user\activity\event\LikeableObjectUserActivityEvent</classname>
<supportsReactions>1</supportsReactions>
</type>
-"""
-)}}
+```
Finally we modify our language variable. To ensure a consistent usability, the same formulations should be used as in the WoltLab Suite Core.
If comments send notifications, they must also be updated. The language variables are changed in the same way as described in the section [Notifications / Language](like.md#Language-Variables). After that comment must be marked as compatible. Therefore we set the parameter `supportsReactions` in the [`objectType.xml`](../../package/pip/object-type.md) to `1`. So for example the entry looks like this:
-{jinja{ codebox(
-language="xml",
-title="objectType.xml",
-contents="""
+```xml title="objectType.xml"
<type>
<name>com.woltlab.wcf.objectComment.response.like.notification</name>
<definitionname>com.woltlab.wcf.notification.objectType</definitionname>
- <classname>wcf\system\\user\notification\object\type\LikeUserNotificationObjectType</classname>
+ <classname>wcf\system\user\notification\object\type\LikeUserNotificationObjectType</classname>
<category>com.woltlab.example</category>
<supportsReactions>1</supportsReactions>
</type>
-"""
-)}}
+```
## Forward Compatibility
First, we create the PHP class that provides our interface to provide the data. The class must implement interface `wcf\system\user\content\provider\IUserContentProvider` in any case. Mostly we process data which is based on [`wcf\data\DatabaseObject`](../../php/database-objects.md). In this case, the WoltLab Suite provides an abstract class `wcf\system\user\content\provider\AbstractDatabaseUserContentProvider` that can be used to automatically generates the standardized classes to generate the list and deletes objects via the DatabaseObjectAction. For example, if we would create a content provider for comments, the class would look like this:
-{jinja{ codebox(
-language="php",
-title="files/lib/system/user/content/provider/CommentUserContentProvider.class.php",
-contents="""
+```php title="files/lib/system/user/content/provider/CommentUserContentProvider.class.php"
<?php
-namespace wcf\system\\user\content\provider;
+namespace wcf\system\user\content\provider;
use wcf\data\comment\Comment;
/**
* @author Joshua Ruesweg
* @copyright 2001-2018 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\\User\Content\Provider
+ * @package WoltLabSuite\Core\System\User\Content\Provider
* @since 5.2
*/
class CommentUserContentProvider extends AbstractDatabaseUserContentProvider {
return Comment::class;
}
}
-"""
-)}}
+```
### Object Type
## PHP Database API
WoltLab Suite 5.2 introduces a new way to update the database scheme:
-[database PHP API](../../package/database-php-api.md).
\ No newline at end of file
+[database PHP API](../../package/database-php-api.md).
Example:
-{jinja{ codebox(
- language="php",
- title="files/lib/data/foo/Foo.class.php",
- contents="""
+```php title="files/lib/data/foo/Foo.class.php"
class Foo extends DatabaseObject implements IPopoverObject {
public function getPopoverLinkClass() {
return 'fooLink';
}
}
-"""
-)}}
+```
-{jinja{ codebox(
- language="php",
- title="files/lib/data/foo/FooAction.class.php",
- contents="""
+```php title="files/lib/data/foo/FooAction.class.php"
class FooAction extends AbstractDatabaseObjectAction implements IPopoverAction {
public function validateGetPopover() {
// …
];
}
}
-"""
-)}}
+```
```js
require(['WoltLabSuite/Core/Controller/Popover'], function(ControllerPopover) {
ControllerPopover.init({
className: 'fooLink',
- dboAction: 'wcf\\data∑foo\\FooAction',
+ dboAction: 'wcf\\data\\foo\\FooAction',
identifier: 'com.woltlab.wcf.foo'
});
});
Adding your own multi-factor method requires the implementation of a single object type:
-{jinja{ codebox(
- language="xml",
- title="objectType.xml",
- contents="""
+```xml title="objectType.xml"
<type>
<name>com.example.multifactor.foobar</name>
<definitionname>com.woltlab.wcf.multifactor</definitionname>
<icon><!-- Font Awesome 4 Icon Name goes here. --></icon>
<priority><!-- Determines the sort order, higher priority will be preferred for authentication. --></priority>
- <classname>wcf\system\\user\multifactor\FoobarMultifactorMethod</classname>
+ <classname>wcf\system\user\multifactor\FoobarMultifactorMethod</classname>
</type>
-"""
-)}}
+```
The given classname must implement the [`IMultifactorMethod`](https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/user/multifactor/IMultifactorMethod.class.php) interface.
Previously:
-{jinja{ codebox(
- language="php",
- title="lib/action/ExampleRedirectAction.class.php",
- contents="""
+```php title="lib/action/ExampleRedirectAction.class.php"
<?php
-namespace wcf\\action;
+namespace wcf\action;
-use wcf\\system\\request\\LinkHandler;
-use wcf\\util\\HeaderUtil;
+use wcf\system\request\LinkHandler;
+use wcf\util\HeaderUtil;
final class ExampleRedirectAction extends AbstractAction
{
exit;
}
}
-"""
-) }}
+```
Now:
-{jinja{ codebox(
- language="php",
- title="lib/action/ExampleRedirectAction.class.php",
- contents="""
+```php title="lib/action/ExampleRedirectAction.class.php"
<?php
-namespace wcf\\action;
+namespace wcf\action;
-use Laminas\\Diactoros\\Response\\RedirectResponse;
-use wcf\\system\\request\\LinkHandler;
+use Laminas\Diactoros\Response\RedirectResponse;
+use wcf\system\request\LinkHandler;
final class ExampleRedirectAction extends AbstractAction
{
);
}
}
-"""
-) }}
+```
#### Migrating JSON responses
Previously:
-{jinja{ codebox(
- language="php",
- title="lib/action/ExampleJsonAction.class.php",
- contents="""
+```php title="lib/action/ExampleJsonAction.class.php"
<?php
-namespace wcf\\action;
+namespace wcf\action;
-use wcf\\util\\JSON;
+use wcf\util\JSON;
final class ExampleJsonAction extends AbstractAction
{
exit;
}
}
-"""
-) }}
+```
Now:
-{jinja{ codebox(
- language="php",
- title="lib/action/ExampleJsonAction.class.php",
- contents="""
+```php title="lib/action/ExampleJsonAction.class.php"
<?php
-namespace wcf\\action;
+namespace wcf\action;
-use Laminas\\Diactoros\\Response\\JsonResponse;
+use Laminas\Diactoros\Response\JsonResponse;
final class ExampleJsonAction extends AbstractAction
{
]);
}
}
-"""
-) }}
+```
## Events
EventHandler::getInstance()->fireAction($this, 'valueAvailable', $parameters);
```
-{jinja{ codebox(
- language="php",
- title="lib/system/event/listener/ValueDumpListener.class.php",
- contents="""
+```php title="lib/system/event/listener/ValueDumpListener.class.php"
<?php
-namespace wcf\\system\\event\\listener;
+namespace wcf\system\event\listener;
-use wcf\\form\\ValueForm;
+use wcf\form\ValueForm;
final class ValueDumpListener implements IParameterizedEventListener
{
var_dump($parameters['value']);
}
}
-"""
-) }}
+```
Now:
EventHandler::getInstance()->fire(new ValueAvailable(\random_int(1, 1024)));
```
-{jinja{ codebox(
- language="php",
- title="lib/system/foo/event/ValueAvailable.class.php",
- contents="""
+```php title="lib/system/foo/event/ValueAvailable.class.php"
<?php
-namespace wcf\\system\\foo\\event;
+namespace wcf\system\foo\event;
-use wcf\\system\\event\\IEvent;
+use wcf\system\event\IEvent;
final class ValueAvailable implements IEvent
{
return $this->value;
}
}
-"""
-) }}
+```
-{jinja{ codebox(
- language="php",
- title="lib/system/event/listener/ValueDumpListener.class.php",
- contents="""
+```php title="lib/system/event/listener/ValueDumpListener.class.php"
<?php
-namespace wcf\\system\\event\\listener;
+namespace wcf\system\event\listener;
-use wcf\\system\\foo\event\\ValueAvailable;
+use wcf\system\foo\event\ValueAvailable;
final class ValueDumpListener
{
var_dump($event->getValue());
}
}
-"""
-) }}
+```
See [WoltLab/WCF#4000](https://github.com/WoltLab/WCF/pull/4000) and [WoltLab/WCF#4265](https://github.com/WoltLab/WCF/pull/4265) for details.
Example:
-{jinja{ codebox(
- language="php",
- title="wcfsetup/install/files/lib/data/user/User.class.php",
- contents="""
+```php title="wcfsetup/install/files/lib/data/user/User.class.php"
<?php
-namespace wcf\\data\\user;
+namespace wcf\data\user;
// …
// …
}
-"""
-) }}
+```
The first step to support activity points is to register an object type for the `com.woltlab.wcf.user.activityPointEvent` object type definition for created person information and specify the default number of points awarded per piece of information:
-{jinja{ codebox(
- language="xml",
- title="objectType.xml",
- contents="""
+```xml title="objectType.xml"
<type>
<name>com.woltlab.wcf.people.information</name>
<definitionname>com.woltlab.wcf.user.activityPointEvent</definitionname>
<points>2</points>
</type>
- """
-) }}
+```
Additionally, the phrase `wcf.user.activityPoint.objectType.com.woltlab.wcf.people.information` (in general: `wcf.user.activityPoint.objectType.{objectType}`) has to be added.
Lastly, we have to add two components for updating data:
First, we register a new rebuild data worker
-{jinja{ codebox(
-language="xml",
-title="objectType.xml",
-contents="""
+```xml title="objectType.xml"
<type>
<name>com.woltlab.wcf.people.information</name>
<definitionname>com.woltlab.wcf.rebuildData</definitionname>
<classname>wcf\system\worker\PersonInformationRebuildDataWorker</classname>
</type>
-"""
-) }}
+```
{jinja{ codebox(
title="files/lib/system/worker/PersonInformationRebuildDataWorker.class.php",
Second, we add an event listener for `UserActivityPointItemsRebuildDataWorker` to update the total user activity points awarded for person information:
-{jinja{ codebox(
- language="xml",
- title="eventListener.xml",
- contents="""
-<eventlistener name=\"execute@wcf\system\worker\\UserActivityPointItemsRebuildDataWorker\">
- <eventclassname>wcf\system\worker\\UserActivityPointItemsRebuildDataWorker</eventclassname>
+```xml title="eventListener.xml"
+<eventlistener name="execute@wcf\system\worker\UserActivityPointItemsRebuildDataWorker">
+ <eventclassname>wcf\system\worker\UserActivityPointItemsRebuildDataWorker</eventclassname>
<eventname>execute</eventname>
<listenerclassname>wcf\system\event\listener\PersonUserActivityPointItemsRebuildDataWorkerListener</listenerclassname>
<environment>admin</environment>
</eventlistener>
-"""
-) }}
+```
{jinja{ codebox(
title="files/lib/system/event/listener/PersonUserActivityPointItemsRebuildDataWorkerListener.class.php",
To support user activity events, an object type for `com.woltlab.wcf.user.recentActivityEvent` has to be registered with a class implementing `wcf\system\user\activity\event\IUserActivityEvent`:
-{jinja{ codebox(
-language="xml",
-title="objectType.xml",
-contents="""
+```xml title="objectType.xml"
<type>
<name>com.woltlab.wcf.people.information</name>
<definitionname>com.woltlab.wcf.user.recentActivityEvent</definitionname>
- <classname>wcf\system\\user\activity\event\PersonInformationUserActivityEvent</classname>
+ <classname>wcf\system\user\activity\event\PersonInformationUserActivityEvent</classname>
</type>
-"""
-) }}
+```
{jinja{ codebox(
title="files/lib/system/user/activity/event/PersonInformationUserActivityEvent.class.php",