diff --git a/docs/devs/lets-build-an-add-on.md b/docs/devs/lets-build-an-add-on.md index 1e2af14..d48bc6e 100644 --- a/docs/devs/lets-build-an-add-on.md +++ b/docs/devs/lets-build-an-add-on.md @@ -370,16 +370,16 @@ Finally, click save to save your template modification. If all has gone well, wh We have our column, we have a UI to pass an input to that column, now we have to handle saving data to that column. We will do this by extending the Forum controller and extending a special method which is called when a node and its data are saved. First, let's create a "Class extension" which can be found under the "Development" entry in the Admin CP. Click "Add class extension". -Here we need to specify a "Base class name" which is the name of the class we are extending, which in this case will be `XF\Admin\Controller\Forum`. And we need to specify a "Extension class name" which is the class which will extend the base class. Enter this as `Demo\Portal\XF\Admin\Controller\Forum`. We should create that class before clicking Save. +Here we need to specify a "Base class name" which is the name of the class we are extending, which in this case will be `XF\Admin\Controller\ForumController`. And we need to specify an "Extension class name" which is the class which will extend the base class. Enter this as `Demo\Portal\XF\Admin\Controller\ForumController`. We should create that class before clicking Save. -Create a new file in `src/addons/Demo/Portal/XF/Admin/Controller` named `Forum.php`. This might seem like quite a long path, but we recommend a path like this for extended classes. It enables you to more easily identify the files that represent extended classes by virtue of the fact that they are in a directory of the same name as the extended "add-on" ID (in this case `XF`). It also makes it clear exactly which class has been extended as the directory structure follows the same path as the default class. The contents of the file should, for now, look like this: +Create a new file in `src/addons/Demo/Portal/XF/Admin/Controller` named `ForumController.php`. This might seem like quite a long path, but we recommend a path like this for extended classes. It enables you to more easily identify the files that represent extended classes by virtue of the fact that they are in a directory of the same name as the extended "add-on" ID (in this case `XF`). It also makes it clear exactly which class has been extended as the directory structure follows the same path as the default class. The contents of the file should, for now, look like this: -```php title="src/addons/Demo/Portal/XF/Admin/Controller/Forum.php" +```php title="src/addons/Demo/Portal/XF/Admin/Controller/ForumController.php" demo_portal_auto_feature) { $creator->setFeatureThread(true); @@ -487,7 +487,7 @@ if ($forum->demo_portal_auto_feature) We can now add the `_save()` method to the extended creator class: -```php title="src/addons/Demo/Portal/XF/Service/Thread/Creator.php" +```php title="src/addons/Demo/Portal/XF/Service/Thread/CreatorService.php" protected function _save() { $thread = parent::_save(); @@ -498,7 +498,7 @@ protected function _save() To make sure this thread gets featured, in between the `$thread` line and the `return` line we just need to add: -```php title="src/addons/Demo/Portal/XF/Service/Thread/Creator.php" +```php title="src/addons/Demo/Portal/XF/Service/Thread/CreatorService.php" if ($this->featureThread && $thread->discussion_state == 'visible') { /** @var \Demo\Portal\Entity\FeaturedThread $featuredThread */ @@ -599,8 +599,9 @@ This doesn't return the results of this query. This returns the finder object it Let's now use that in our `actionIndex()` method inside our portal controller. Change the existing `$viewParams = [];` line to the following: ```php title="src/addons/Demo/Portal/Pub/Controller/Portal.php" -/** @var \Demo\Portal\Repository\FeaturedThread $repo */ -$repo = $this->repository('Demo\Portal:FeaturedThread'); +use Demo\Portal\Repository\FeaturedThread; + +$repo = $this->repository(FeaturedThread::class); $finder = $repo->findFeaturedThreadsForPortalView(); @@ -705,7 +706,7 @@ public static function homePageUrl(&$homePageUrl, \XF\Mvc\Router $router) } ``` -Finally, we should consider changing the index page route to our portal page. Go to Admin CP and under Setup click Options followed by "Basic board information". Change the "Index page route" option to `portal/`. +Finally, we should consider changing the index page route to our portal page. Go to Admin CP and under Setup click Options followed by "Basic options". Change the "Index page route" option to `portal/`. While you're in the Admin CP, let's see what happens now when you click on the Board title in the header. This should take you to your index page. All being well, that index page should now be your portal! In addition to that, the Home tab should be visible, and selected. @@ -758,7 +759,7 @@ namespace Demo\Portal\XF\Entity; class Thread extends XFCP_Thread { - public function canFeatureUnfeature() + public function canFeatureUnfeature(&$error = null): bool { return true; } @@ -769,16 +770,16 @@ Ok, so, we haven't exactly done much here of value, yet. All the `canFeatureUnfe To test this works so far, open one of the threads you previously featured, and select "Edit thread" from the tools menu. We should see the "Set thread status" checkbox row has the "Featured" checkbox we added, and it should be checked, indicating that this thread is indeed featured. -We can now move on to changing the thread editor service to look for this value and feature or unfeature accordingly. We are going to need two new class extensions for this. Go back to the "Add class extensions" page. The first one will have a base class of `XF\Pub\Controller\Thread` and extension class of `Demo\Portal\XF\Pub\Controller\Thread`. The second one will have a base class of `XF\Service\Thread\Editor` and an extension class of `Demo\Portal\XF\Service\Thread\Editor`. +We can now move on to changing the thread editor service to look for this value and feature or unfeature accordingly. We are going to need two new class extensions for this. Go back to the "Add class extensions" page. The first one will have a base class of `XF\Pub\Controller\ThreadController` and extension class of `Demo\Portal\XF\Pub\Controller\ThreadController`. The second one will have a base class of `XF\Service\Thread\EditorService` and an extension class of `Demo\Portal\XF\Service\Thread\EditorService`. The editor service is actually going to be very similar to the extended creator service we created earlier, so create that in the relevant location. Here is all of the code for the extended class: -```php title="src/addons/Demo/Portal/XF/Service/Thread/Editor.php" +```php title="src/addons/Demo/Portal/XF/Service/Thread/EditorService.php" canFeatureUnfeature(); @@ -854,8 +855,8 @@ We need to extend another method in the thread controller to handle a situation We just need to add the following code below the `setupThreadEdit()` method we added above: -```php title="src/addons/Demo/Portal/XF/Pub/Controller/Thread.php" -public function finalizeThreadReply(\XF\Service\Thread\Replier $replier) +```php title="src/addons/Demo/Portal/XF/Pub/Controller/ThreadController.php" +public function finalizeThreadReply(\XF\Service\Thread\ReplierService $replier) { parent::finalizeThreadReply($replier); @@ -876,7 +877,7 @@ Note that we haven't actually returned anything in this method because it isn't For the final step in manually featuring/unfeaturing a thread, we need to go back to the forum controller and slightly change our existing code so that if featuring isn't automatic, we can handle it manually, instead. This should be fairly straight forward. Head into your extended forum controller, and replace this: -```php title="src/addons/Demo/Portal/XF/Pub/Controller/Thread.php" +```php title="src/addons/Demo/Portal/XF/Pub/Controller/ForumController.php" if ($forum->demo_portal_auto_feature) { $creator->setFeatureThread(true); @@ -885,7 +886,7 @@ if ($forum->demo_portal_auto_feature) With this: -```php title="src/addons/Demo/Portal/XF/Pub/Controller/Thread.php" +```php title="src/addons/Demo/Portal/XF/Pub/Controller/ForumController.php" if ($forum->demo_portal_auto_feature) { $creator->setFeatureThread(true); @@ -1058,20 +1059,21 @@ You may have spotted earlier in the demo_portal_view template that each post we 'attachments': $post.attach_count ? $post.Attachments : [], ``` -Right now, this is going to generate an additional query for each post. So, we should instead try to do a single query for all of the posts we are displaying and add them to the posts in advance. It probably sounds more complicated than it is. Just add the below code beneath the `->slice(0, $perPage, true);` line. +Right now, this is going to generate an additional query for each post. So, we should instead try to do a single query for all of the posts we are displaying and add them to the posts in advance. It probably sounds more complicated than it is. Just add the below code beneath the `->sliceToPage($page, $perPage);` line. ```php title="src/addons/Demo/Portal/Pub/Controller/Portal.php" +use XF\Repository\AttachmentRepository; + $threads = $featuredThreads->pluckNamed('Thread'); $posts = $threads->pluckNamed('FirstPost', 'first_post_id'); -/** @var \XF\Repository\Attachment $attachRepo */ -$attachRepo = $this->repository('XF:Attachment'); +$attachRepo = $this->repository(AttachmentRepository::class); $attachRepo->addAttachmentsToContent($posts, 'post'); ``` We use the `pluckNamed()` method first to get a collection of threads, then again to get a collection of the posts (keyed by the post ID) from the threads. Once we have the posts, we can just pass them into a special method in the attachment repo, which performs a single query and "hydrates" the Attachments relation for each post. -The final permission related thing to finish up is to create a new permission to control who can feature / unfeature threads manually. To do this, in the Admin CP under "Development" click "Permission definitions" and click "Add permission". The "Permission group" will be "forum", "Permission ID" will be `demoPortalFeature`, "Title" should be `Can feature / unfeature threads`, set "Interface group" to `Forum moderator permissions` and after choosing an appropriate display order and ensuring your add-on is selected, click "Save". +The final permission related thing to finish up is to create a new permission to control who can feature / unfeature threads manually. To do this, in the Admin CP under "Development" click "Permission definitions" and click "Add permission". The "Permission group" will be `forum`, "Permission ID" will be `demoPortalFeature`, "Title" should be `Can feature / unfeature threads`, set "Interface group" to `Forum moderator permissions` and after choosing an appropriate display order and ensuring your add-on is selected, click "Save". To actually use this permission, we need to go back to our extended thread entity to modify the `canFeatureUnfeature()` method. Replace `return true;` with: @@ -1087,7 +1089,7 @@ We currently display only 5 featured threads per page, but it would be nice to h In the Admin CP under Setup then Options click the "Add option group" button. We'll just call the "Group ID" `demoPortal` and give it a title of "Demo - Portal options". Give it an appropriate ̀"Description" and "Display order" and click "Save". -Now click "Add option". Set the "Option ID" to `demoPortalFeaturedPerPage`, "Title" to `Featured threads per page`, edit format to `Spin box`, "Data type" to `Positive integer` and "Default value" to `10`. Click "Save". +Now click "Add option". Set the "Option ID" to `demoPortalFeaturedPerPage`, "Title" to `Featured threads per page`, edit format to `Number box`, "Data type" to `Positive integer` and "Default value" to `10`. Click "Save". To implement that, go back to the portal controller and change: diff --git a/static/files/Demo-Portal-1.0.0 Alpha.zip b/static/files/Demo-Portal-1.0.0 Alpha.zip index a4da03d..3c71f6b 100644 Binary files a/static/files/Demo-Portal-1.0.0 Alpha.zip and b/static/files/Demo-Portal-1.0.0 Alpha.zip differ