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.
-```php
+{jinja{ codebox(
+ language="php",
+ title="files/lib/system/comment/manager/ExampleCommentManager.class.php",
+ contents="""
<?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:
-```php
+
+{jinja{ codebox(
+ language="php",
+ title="files/lib/system/user/activity/event/ExampleUserActivityEvent.class.php",
+ contents="""
<?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.
-```php
+{jinja{ codebox(
+ language="php",
+ title="files/lib/data/example/LikeableExampleProvider.class.php",
+ contents="""
<?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.
-```php
+{jinja{ codebox(
+ language="php",
+ title="files/lib/data/package/plugin/ExamplePackageInstallationPlugin.class.php",
+ contents="""
<?php
class ExamplePackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin implements IIdempotentPackageInstallationPlugin {
public static function getSyncDependencies() {
return [];
}
}
-```
+"""
+) }}
## Media Providers
### Example Implementation
-#### mediaProvider.xml
-
-```xml
-<?xml version="1.0" encoding="UTF-8"?>
-<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/tornado/mediaProvider.xsd">
- <import>
- <provider name="example">
- <title>Example Provider</title>
- <regex><![CDATA[https?://example.com/watch?v=(?P<ID>[a-zA-Z0-9])]]></regex>
- <className><![CDATA[wcf\system\bbcode\media\provider\ExampleBBCodeMediaProvider]]></className>
- </provider>
- </import>
-</data>
-```
+{jinja{ codebox(
+ language="xml",
+ title="mediaProvider.xml",
+ filepath="migration/wsc-30/mediaProvider.xml"
+) }}
#### PHP Callback
### Recent Activity
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:
-
-```xml
+
+{jinja{ codebox(
+language="xml",
+title="objectType.xml",
+contents="""
<type>
- <name>com.woltlab.example.likeableObject.recentActivityEvent</name>
- <definitionname>com.woltlab.wcf.user.recentActivityEvent</definitionname>
- <classname>wcf\system\user\activity\event\LikeableObjectUserActivityEvent</classname>
- <supportsReactions>1</supportsReactions>
+ <name>com.woltlab.example.likeableObject.recentActivityEvent</name>
+ <definitionname>com.woltlab.wcf.user.recentActivityEvent</definitionname>
+ <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.
### Comments
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:
-```xml
+
+{jinja{ codebox(
+language="xml",
+title="objectType.xml",
+contents="""
<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>
- <category>com.woltlab.example</category>
- <supportsReactions>1</supportsReactions>
+ <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>
+ <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:
-```php
+{jinja{ codebox(
+language="php",
+title="files/lib/system/user/content/provider/CommentUserContentProvider.class.php",
+contents="""
<?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
Example:
-```php
+{jinja{ codebox(
+ language="php",
+ title="files/lib/data/foo/Foo.class.php",
+ contents="""
class Foo extends DatabaseObject implements IPopoverObject {
- public function getPopoverLinkClass() {
- return 'fooLink';
- }
+ public function getPopoverLinkClass() {
+ return 'fooLink';
+ }
}
+"""
+)}}
+{jinja{ codebox(
+ language="php",
+ title="files/lib/data/foo/FooAction.class.php",
+ contents="""
class FooAction extends AbstractDatabaseObjectAction implements IPopoverAction {
- public function validateGetPopover() {
- // …
- }
-
- public function getPopover() {
- return [
- 'template' => '…',
- ];
- }
+ public function validateGetPopover() {
+ // …
+ }
+
+ public function getPopover() {
+ return [
+ 'template' => '…',
+ ];
+ }
}
-```
+"""
+)}}
```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:
-```xml
+{jinja{ codebox(
+ language="xml",
+ title="objectType.xml",
+ contents="""
<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>
+ <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>
</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.
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/tornado/mediaProvider.xsd">
+ <import>
+ <provider name="example">
+ <title>Example Provider</title>
+ <regex>https?://example.com/watch?v=(?P<ID>[a-zA-Z0-9])</regex>
+ <className>wcf\system\bbcode\media\provider\ExampleBBCodeMediaProvider</className>
+ </provider>
+ </import>
+</data>
\ No newline at end of file