<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title>October Tricks Latest</title>
    <link>https://octobertricks.com</link>
    <description>Latest Tricks from octobertricks.com</description>
    <atom:link href="" rel="self" type="application/rss+xml"/>
    <item>
      <title>How to redirect backend users after login</title>
      <link>https://octobertricks.com/tricks/how-to-redirect-backend-users-after-login</link>
      <description/>
      <content:encoded><![CDATA[<pre><code>\Event::listen('backend.user.login', function ($user) {
        // This will run after login is successful
        \Redirect::to(Backend::url('your/plugin/controller'))-&gt;send();
});</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>How to integrate Integrate TinyMCE 7</title>
      <link>https://octobertricks.com/tricks/how-to-integrate-integrate-tinymce</link>
      <description>How to integrate TinyMCE in WinterCMS, useful information for creating streamlined user experiences, and examples of using TinyMCE as an inline editor</description>
      <content:encoded><![CDATA[<p>How to integrate <strong>TinyMCE </strong>in WinterCMS, useful information for creating streamlined user experiences, and examples of using TinyMCE as an inline editor</p>]]></content:encoded>
    </item>
    <item>
      <title>Retrieving Plugin Versions in OctoberCMS 3 using VersionManager and PluginVersion</title>
      <link>https://octobertricks.com/tricks/retrieving-plugin-versions-in-octobercms-3-using-versionmanager-and-pluginversion</link>
      <description>OctoberCMS 3 offers two classes to retrieve the version number of a plugin: VersionManager and PluginVersion.
VersionManager
The getLatestVersion() method of \System\Classes\VersionManager retrieves the current version of a plugin from the associated version.yaml file. This file is a fundamental requirement...</description>
      <content:encoded><![CDATA[<p>OctoberCMS 3 offers two classes to retrieve the version number of a plugin: <strong>VersionManager</strong> and <strong>PluginVersion</strong>.</p>
<h2>VersionManager</h2>
<p>The <code>getLatestVersion()</code> method of <code>\System\Classes\VersionManager</code> retrieves the current version of a plugin from the associated <code>version.yaml</code> file. This file is a fundamental requirement and should be included in every plugin since at least OctoberCMS v2. With this class, you can access the latest plugin version without the need for the plugin to be installed and regardless of whether it is activated or not. However, keep in mind that when using the <code>VersionManager</code>, the version specified in the <code>version.yaml</code> file may differ from the installed version stored in the database.</p>
<p><strong>Example</strong></p>
<p>The following code returns the version number of the "RainLab.User" plugin as a string or <code>0</code> if the plugin or the <code>version.yaml</code> file does not exist.</p>
<pre><code class="language-php">$versionManager = \System\Classes\VersionManager::instance();
echo $versionManager-&gt;getLatestVersion('RainLab.User');</code></pre>
<h2>PluginVersion</h2>
<p>The class <code>\System\Models\PluginVersion</code> is, as the namespace suggests, an Eloquent model that maps to the native <code>system_plugin_versions</code> table, thus we can retrieve the latest installed version number from the respective column. This class therefore requires that the plugin is installed, but it also allows for a direct check to see if the plugin is currently activated as well.</p>
<p><strong>Example</strong></p>
<p>The following code demonstrates the use of the <code>PluginVersion</code> class in a typical Eloquent manner. With an additional <code>where</code> clause, like <code>where('is_disabled', 0)</code>, you can further restrict the selection to active plugins too.</p>
<pre><code class="language-php">$pluginVersion = `\System\Models\PluginVersion::where('code', 'RainLab.User')-&gt;first();
echo $pluginVersion ? $pluginVersion-&gt;version : 0;</code></pre>
<h2>Plugin Manager</h2>
<p>By the way, using the <code>\System\Classes\PluginManager</code> class, you can also quickly check whether a plugin exists or not. Similar to <code>VersionManager</code>, this class only verifies if the plugin directory (and necessary files) exists, without checking whether the plugin is installed or activated.</p>
<p><strong>Example</strong></p>
<p>The following code checks whether the <code>RainLab.User</code> plugin exists:</p>
<pre><code class="language-php">echo \System\Classes\PluginManager::instance()-&gt;hasPlugin('RainLab.User');</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Pass values from the parent form to the child form</title>
      <link>https://octobertricks.com/tricks/pass-values-from-the-parent-form-to-the-child-form</link>
      <description>There is a need to pass values from the parent form to the child form using relationship behavior in the Backend of an application.
In the parent controller, the relationExtendManageWidget() function is overridden, and the model used in the widget...</description>
      <content:encoded><![CDATA[<p>There is a need to pass values from the parent form to the child form using relationship behavior in the Backend of an application.</p>
<p>In the parent controller, the <code>relationExtendManageWidget()</code> function is overridden, and the model used in the widget of the child form is accessed using <code>$widget-&gt;config-&gt;model</code>. Then, a dynamic property is added to the model using the <code>addDynamicProperty()</code> function, so that this property is not saved to the database, as it is only used for filtering logic.</p>
<pre><code>public function relationExtendManageWidget($widget, $field, $model) 
{
    if($field == 'actresses' 
        &amp;&amp; property_exists($widget-&gt;config, 'context')
    )
    {
        $widget-&gt;config-&gt;model-&gt;addDynamicProperty('_active_continent_id', $model-&gt;continent_id);
    }
}</code></pre>
<p>To use it, for example, there is a dropdown in the child form to display a list of countries in the selected continent previously selected in the parent form, then we simply do:</p>
<pre><code>country:
    label: 'Country'
    nameFrom: name
    span: full
    type: relation
    scope: '\Foo\Bar\Actress::getFilteredCountryBasedOnContinent'</code></pre>
<p>Then, the function is filled in as follows:</p>
<pre><code>static public function getFilteredCountryBasedOnContinent($query, $model)
{
    $query
        -&gt;where('continent_id', $model-&gt;_active_continent_id);
}</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Resize images in rich text html</title>
      <link>https://octobertricks.com/tricks/resize-images-in-rich-text-html</link>
      <description>Images that are inserted by users into rich text fields are not resized. This twig filter as part of a custom plugin does that and can be inserted before |content or |raw:
It can be used as follows: {{your_field|rich_resize|content}} or...</description>
      <content:encoded><![CDATA[<p>Images that are inserted by users into rich text fields are not resized. This twig filter as part of a custom plugin does that and can be inserted before |content or |raw:</p>
<pre><code class="language-php">&lt;?php namespace Minakari\Customisations;
use \System\Classes\ResizeImages;

class Plugin extends PluginBase
{
    public function boot()
    {
    }

    public function registerMarkupTags(): array
    {
        $filters = [
            'rich_resize' =&gt; [$this, 'richResize']
        ];
        $functions = [];

        return [
            'filters' =&gt; $filters,
            'functions' =&gt; $functions,
        ];
    }

    public function richResize($html)
    {
        // Use DOMDocument to parse the HTML and find all image tags
        $dom = new \DOMDocument();
        @$dom-&gt;loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));

        $images = $dom-&gt;getElementsByTagName('img');

        foreach ($images as $image) {
            $src = $image-&gt;getAttribute('src');

            // Resize the image using the ResizeImages::resize() interface
            $resizedSrc = ResizeImages::resize($src, 1328, null, ['mode' =&gt; 'auto', 'quality' =&gt; '40', 'compress' =&gt; true]);

            // Replace the original src with the resized src
            $image-&gt;setAttribute('src', $resizedSrc);
        }

        // Return the modified HTML
        return $dom-&gt;saveHTML();
    }
}</code></pre>
<p>It can be used as follows: <code>{{your_field|rich_resize|content}}</code> or `{{your_field|rich_resize|raw}}</p>]]></content:encoded>
    </item>
    <item>
      <title>Bind injectRowClass to relation widgets lists</title>
      <link>https://octobertricks.com/tricks/bind-injectrowclass-to-relation-widgets-lists</link>
      <description>This method, relationExtendViewWidget, enhances the visual presentation of relation widgets by binding the injectRowClass event to dynamically apply a CSS class to each row in the widget's list view. Specifically, the provided anonymous function returns the CSS class strike, which...</description>
      <content:encoded><![CDATA[<p>This method, relationExtendViewWidget, enhances the visual presentation of relation widgets by binding the injectRowClass event to dynamically apply a CSS class to each row in the widget's list view. Specifically, the provided anonymous function returns the CSS class strike, which can be customized to suit different styling needs. This approach offers flexibility in styling rows based on specific conditions or criteria, thereby improving the user interface and experience of the relation widgets within the application.</p>
<pre><code>public function relationExtendViewWidget($widget, $field, $model)
{
    $widget-&gt;bindEvent('list.injectRowClass', function ($record) {
        if ($record-&gt;someCondition) {
            return 'strike'; // Apply 'strike' css class if condition is met
        }
    });
}</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>How to override form buttons when using formRenderDesign method</title>
      <link>https://octobertricks.com/tricks/how-to-override-form-buttons-when-using-formrenderdesign-method</link>
      <description>Create a file named _form_buttons.php in your controler and add whatever buttons you like in there. The orginal _buttons.php can be found in modules/backend/behaviors/formcontroller/partials</description>
      <content:encoded><![CDATA[<p>Create a file named _form_buttons.php in your controler and add whatever buttons you like in there. The orginal _buttons.php can be found in modules/backend/behaviors/formcontroller/partials</p>]]></content:encoded>
    </item>
    <item>
      <title>Change Backend Menu items icons</title>
      <link>https://octobertricks.com/tricks/change-backend-menu-items-icons</link>
      <description/>
      <content:encoded><![CDATA[<pre><code class="language-php">Event::listen('backend.menu.extendItems', function ($navigationManager) {
    $navigationManager-&gt;getMainMenuItem('October.Backend', 'Dashboard')-&gt;iconSvg('');
    $navigationManager-&gt;getMainMenuItem('October.Backend', 'Dashboard')-&gt;icon('icon-pie-chart');
});</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Default for Many to Many Relationship Using the Relation Controller</title>
      <link>https://octobertricks.com/tricks/default-for-many-to-many-relationship-using-the-relation-controller</link>
      <description>When using a many to many relation using the relation controller you can set a default value like so—illustrated using a many to many relation ship to users:
Controller
    public function formExtendFields($form)
    {
        if ($this-&gt;formGetContext() === 'create') {
            $model =...</description>
      <content:encoded><![CDATA[<p>When using a many to many relation using the relation controller you can set a default value like so—illustrated using a many to many relation ship to <code>users</code>:</p>
<p><strong>Controller</strong></p>
<pre><code class="language-php">    public function formExtendFields($form)
    {
        if ($this-&gt;formGetContext() === 'create') {
            $model = $this-&gt;formCreateModelObject();
            $sessionKey = $this-&gt;formGetSessionKey()`
            $currentUser = BackendAuth::getUser();

            $model-&gt;users()-&gt;add($currentUser, $sessionKey);
        }
    }</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Write dynamic validation rules when saving a model</title>
      <link>https://octobertricks.com/tricks/write-dynamic-validation-rules-when-saving-a-model</link>
      <description/>
      <content:encoded><![CDATA[<pre><code>    public function beforeValidate()
    {
                $this-&gt;rules['amount_picked'] = 'numeric|min:0|max:' . $this-&gt;amount_required;
    }</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>How to save belongsTo relation in one form without using relation form widget on create</title>
      <link>https://octobertricks.com/tricks/how-to-save-belongsto-relation-in-one-form-without-using-relation-form-widget-on-create</link>
      <description>Define your fields in fields.yaml as</description>
      <content:encoded><![CDATA[<pre><code class="language-php">    public function formExtendModel($model)
    {

         if ($this-&gt;action == 'create') {
             $model-&gt;address = new \Company\Plugin\Models\Address();
         }

         return $model;
    }
</code></pre>
<p>Define your fields in fields.yaml as</p>
<pre><code>fields:
    address[streetname]:
                        label: Name
            type: text
    address[housenumber]:
                        label: House Number
            type: text
   address[zip]:
                        label: Zip
            type: text</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>How to hide all relation toolbar buttons</title>
      <link>https://octobertricks.com/tricks/how-to-hide-all-relation-toolbar-buttons</link>
      <description>To hide all relation buttons, you just need to pass an empty array</description>
      <content:encoded><![CDATA[<p>To hide all relation buttons, you just need to pass an empty array</p>
<pre><code>toolbarButtons: []</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Enable Backend-only Mode</title>
      <link>https://octobertricks.com/tricks/enable-backend-only-mode</link>
      <description>To enable Backend-only Mode, update your environment variables. Set the 'LOAD_MODULES' variable to include only the necessary modules, excluding 'Cms':
LOAD_MODULES="System,Backend,Editor,Media"
Additionally, set the 'BACKEND_URI' variable to an empty string for using the root domain or subdomain:
BACKEND_URI=''</description>
      <content:encoded><![CDATA[<p>To enable Backend-only Mode, update your environment variables. Set the 'LOAD_MODULES' variable to include only the necessary modules, excluding 'Cms':</p>
<p><code>LOAD_MODULES="System,Backend,Editor,Media"</code></p>
<p>Additionally, set the 'BACKEND_URI' variable to an empty string for using the root domain or subdomain:</p>
<p><code>BACKEND_URI=''</code></p>]]></content:encoded>
    </item>
    <item>
      <title>Default value of 'Switch' fieldtype</title>
      <link>https://octobertricks.com/tricks/default-value-of-switch-fieldtype</link>
      <description>To make a 'switch' field checked/switched on by default, you have to use the property 'value' instead of 'default'.</description>
      <content:encoded><![CDATA[<p>To make a 'switch' field checked/switched on by default, you have to use the property 'value' instead of 'default'.</p>
<pre><code>showDate:
    label: Show date
    type: switch
    value: 1</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Get list of email templates</title>
      <link>https://octobertricks.com/tricks/get-list-of-email-templates</link>
      <description>You can use the built in method 
\System\Models\MailTemplate::listAllTemplates()</description>
      <content:encoded><![CDATA[<p>You can use the built in method </p>
<p><code>\System\Models\MailTemplate::listAllTemplates()</code></p>]]></content:encoded>
    </item>
    <item>
      <title>How to pass active locale/lang to mail templates data</title>
      <link>https://octobertricks.com/tricks/how-to-pass-active-localelang-to-mail-templates-data</link>
      <description/>
      <content:encoded><![CDATA[<pre><code>use Event; 
use App; 
use 
System\Classes\MailManager;

public function boot()
{
    Event::listen('mailer.beforeAddContent', function ($mailer, $message, $view, $data, $raw, $plain) {

            $data['_current_locale'] = !empty($data['_current_locale']) ? $data['_current_locale'] : App::getLocale();

            if (MailManager::instance()-&gt;addContentToMailer($message, $view, $data, $plain)) {
                // the caller who fired the event is expecting a FALSE response to halt the event
                return false;
            }

        }, 1);
    }</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Exclude blog posts without featured images in OctoberCMS</title>
      <link>https://octobertricks.com/tricks/select-blog-posts-which-contains-at-least-one-featured-image</link>
      <description>When creating hero sliders or similar components, it’s often helpful to exclude blog posts that don’t have a featured image attached. Fortunately, Laravel makes this easy. Here's a simple query that works in Laravel 6 (the version used in OctoberCMS...</description>
      <content:encoded><![CDATA[<p>When creating hero sliders or similar components, it’s often helpful to exclude blog posts that don’t have a featured image attached. Fortunately, Laravel makes this easy. Here's a simple query that works in Laravel 6 (the version used in OctoberCMS v2):</p>
<pre><code class="language-php">$query = \RainLab\Blog\Models\Post::with(['categories', 'featured_images'])
    -&gt;withCount('featured_images')
    -&gt;where('featured_images_count', '&gt;', 0);

$posts = $query-&gt;listFrontEnd([
    'page'             =&gt; 1,
    'sort'             =&gt; 'published_at desc',
    'perPage'          =&gt; 10,
    'published'        =&gt; true,
});</code></pre>
<h2>Using the Query in Your Template</h2>
<p>The result stored in <code>$posts</code> can be passed to your template layout or CMS page, either in the <code>onInit</code> or <code>onStart</code> function. However, you may notice that the post URLs are missing. This happens because we need to set them manually. Here’s a solution to ensure each post has a URL:</p>
<pre><code class="language-php">##
url = "/test"
description = "Example Template"
==
&lt;?php 
function onStart()
{
    $query = \RainLab\Blog\Models\Post::with(['categories', 'featured_images'])
        -&gt;withCount('featured_images')
        -&gt;where('featured_images_count', '&gt;', 0));

    // Select posts
    $posts = $query-&gt;listFrontEnd([
        'page'             =&gt; 1,
        'sort'             =&gt; 'published_at desc',
        'perPage'          =&gt; 10,
        'search'           =&gt; null,
        'category'         =&gt; null,
        'published'        =&gt; true,
    ]);

    // Get component details
    if (!empty($component = $this-&gt;layout-&gt;getComponent('blogPosts'))) {
        $postPage = $component-&gt;property('postPage');
        $categoryPage = $component-&gt;property('categoryPage');
    }
    $ctrl = $this-&gt;controller;
    $postPage = empty($postPage) ? 'blog/post' : $postPage;
    $categoryPage = empty($categoryPage) ? 'category/post' : $categoryPage;

    // Set on each post and category
    $posts-&gt;each(function($post) use ($ctrl, $postPage, $categoryPage) {
        $post-&gt;setUrl($postPage, $ctrl);
        $post-&gt;categories-&gt;each(fn ($item) =&gt; $item-&gt;setUrl($categoryPage, $ctrl)); 
    });

    // Pass to template
    $this['featuredPosts'] = $posts;
}
?&gt;
==
&lt;!-- Output --&gt;</code></pre>
<h2>Bonus: Extending the Query with BlogHub</h2>
<p>For our upcoming Falcon template, we extended this query to allow the user to set either a <code>featured_image</code> or a custom <code>slider_image</code> meta field. This is achieved using our <a href="https://octobercms.com/plugin/ratmd-bloghub">BlogHub</a> extension for OctoberCMS. To ensure that either a <code>featured_image</code> or a <code>slider_image</code> is available, the query is adjusted as follows:</p>
<pre><code class="language-php">$query = \RainLab\Blog\Models\Post::with(['categories', 'featured_images', 'ratmd_bloghub_meta'])
    -&gt;withCount('featured_images')
    -&gt;where(function ($builder) {
        $builder-&gt;where('featured_images_count', '&gt;', 0);
        $builder-&gt;orWhere(function ($builder) {
            $builder-&gt;whereHas('ratmd_bloghub_meta', function ($builder) {
                $builder-&gt;where('ratmd_bloghub_meta.name', 'slider_image')
                        -&gt;whereNotNull('ratmd_bloghub_meta.value');
            });
        });
    });</code></pre>
<p>To include the <code>slider_image</code> field in your blog posts, install the BlogHub extension and add the following code at the bottom of your <code>theme.yaml</code> file:</p>
<pre><code class="language-yaml">ratmd.bloghub:
    post:
        slider_image:
            tab: Custom Meta
            type: mediafinder
            mode: image
            label: A special image used for sliders only.
            maxItems: 1</code></pre>
<p>Now, you can output the <code>slider_image</code> as follows:</p>
<pre><code class="language-html">&lt;img src="{{ post.bloghub.meta.slider_image | media }}" alt="..." /&gt; </code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Prefill relation widget from main form</title>
      <link>https://octobertricks.com/tricks/prefill-relation-widget-from-main-form</link>
      <description>To prefill a relationform, we can use the relationManageWidget function in our controller. Conveniently the relationmanagerAjaxCall POSTs the current (not yet saved) form data of the calling form. So we can prefill the popup form like this:</description>
      <content:encoded><![CDATA[<p>To prefill a relationform, we can use the relationManageWidget function in our controller. Conveniently the relationmanagerAjaxCall POSTs the current (not yet saved) form data of the calling form. So we can prefill the popup form like this:</p>
<pre><code>    public function relationExtendManageWidget($widget, $field, $model)
        {                               
                        if($field === 'comments'
                                &amp;&amp; property_exists($widget-&gt;config, 'context')
                                &amp;&amp; $widget-&gt;config-&gt;context === 'create'
                        ) {
                                $post=Input::get('post');
                                if ($post){
                                        $widget-&gt;model-&gt;title = 're: '.$post['title'];
                                }
                        }                           
    }</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Reset backend user password</title>
      <link>https://octobertricks.com/tricks/reset-backend-user-password</link>
      <description>Sometimes it's possible that you can forget October CMS website backend user password. You don't need to panic if you or your developer has access to the command line. you can easily change the backend user password in a matter...</description>
      <content:encoded><![CDATA[<p>Sometimes it's possible that you can forget <code>October CMS</code> website <code>backend user</code> password. You don't need to panic if you or your developer has access to the command line. you can easily change the <code>backend user</code> password in a matter of time.</p>
<blockquote>
<p>You can use the <code>php artisan october:passwd</code> command to reset backend user password</p>
</blockquote>
<pre><code>php artisan october:passwd admin NEWPASS</code></pre>
<p>Here this command will set the <code>admin</code> user's password to <code>NEWPASS</code>.</p>
<p>You can replace <code>admin</code> user and <code>NEWPASS</code> with your own details.</p>
<p>Reference:  <a href="https://coderecharge.com/october-cms/backend/october-cms-reset-backend-user-password">Change backend admin password</a></p>]]></content:encoded>
    </item>
    <item>
      <title>How to check the October CMS version</title>
      <link>https://octobertricks.com/tricks/how-to-check-the-october-cms-version</link>
      <description>Sometimes you need to use different logic depending on the October CMS version. Here is a way for you to check the exact version.
A simple way to check if it is v2 or above:
For more precise checking, this...</description>
      <content:encoded><![CDATA[<p>Sometimes you need to use different logic depending on the October CMS version. Here is a way for you to check the exact version.</p>
<p>A simple way to check if it is v2 or above:</p>
<pre><code>if (class_exists('System'))  {
    // Running October CMS 2.0 or above
}
else {
    // Running October CMS 1.0
}</code></pre>
<p>For more precise checking, this will check if it is v2.2 or above:</p>
<pre><code>if (class_exists('System') &amp;&amp; version_compare(\System::VERSION, '2.2') !== -1) {
    // Running October CMS v2.2 or above
}</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>How to extend backend list columns and add custom column</title>
      <link>https://octobertricks.com/tricks/how-to-extend-backend-list-columns-and-add-custom-column</link>
      <description>You can add your custom column to existing backend list by extending controller with extendListColumns  method.

make sure that controller has ListController behaviour implemented 

You can add any type of column partial or relational columns.
Reference : How To Add...</description>
      <content:encoded><![CDATA[<p>You can add your custom column to existing backend list by extending controller with <code>extendListColumns</code>  method.</p>
<blockquote>
<p>make sure that controller has <code>ListController</code> behaviour implemented </p>
</blockquote>
<pre><code>class Plugin extends PluginBase
{
    public function boot() {

        // extending Controller which has ListController Behavior 
        Items::extendListColumns(function($list, $model) {

            // we want only our Item model be extended
            if (!$model instanceof Item) {
                return;
            }

            // adding quantity column or other new column
            $list-&gt;addColumns([
                'quantity' =&gt; [
                    'label' =&gt; 'Quantity',
                    'type' =&gt; 'number',
                    'searchable' =&gt; true
                ]
            ]);

        });
    }</code></pre>
<p>You can add any type of column <code>partial</code> or <code>relational columns</code>.</p>
<p>Reference : <a href="https://tutorialmeta.com/octobercms/how-add-new-column-october-cms-list">How To Add New Column In October Cms List</a></p>
<p>It can be usefull when you need to show extended information with existing backend list or other 3rd party plugins.</p>]]></content:encoded>
    </item>
    <item>
      <title>Render Relation List/Form with trashed datas</title>
      <link>https://octobertricks.com/tricks/render-relation-list-with-trashed-datas</link>
      <description>Sometimes, you have a model with related datas but those datas have softDelete enabled.
And when you try to access the parent model, you may encounter an error due to some partials in your model form or list. 
To avoid...</description>
      <content:encoded><![CDATA[<p>Sometimes, you have a model with related datas but those datas have softDelete enabled.
And when you try to access the parent model, you may encounter an error due to some partials in your model form or list. </p>
<p>To avoid getting this error, you need to configure your relation to get the data with trashed. </p>
<p>Go to your parent model, and change your relation like this : </p>
<pre><code class="language-php">    public $belongsTo = [
        'relationName' =&gt; [ 
                    \Author\Plugin\Models\YourRelationModel::class,
                    'scope'=&gt;'withTrashed'
                ],
    ];</code></pre>
<p>and all works again.</p>]]></content:encoded>
    </item>
    <item>
      <title>Add Counter in plugin.yaml</title>
      <link>https://octobertricks.com/tricks/add-counter-in-pluginyaml</link>
      <description>

In your plugin.yaml, add counter and counterLabel like this: 


then in your model PHP file, add your function which is returning a number like this for example : 


check the result in your backend


</description>
      <content:encoded><![CDATA[<ol>
<li>In your plugin.yaml, add counter and counterLabel like this: </li>
</ol>
<pre><code class="language-yaml">side-menu-item:
  label: yourLabel
  url: your/controller/url
  icon: your-icon
  ...
  counter: \AuthorName\PluginName\Models\YourClass::Yourfunction
  counterLabel: Your Label</code></pre>
<ol start="2">
<li>then in your model PHP file, add your function which is returning a number like this for example : </li>
</ol>
<pre><code class="language-php">&lt;?php namespace  \AuthorName\PluginName\Models;

class YourClass extends Model{

  ...

  public static function Yourfunction(){
    // you can do whatever you need right here, you just need to not forget to return a number.
    return self::count();

  }
}</code></pre>
<ol start="3">
<li>check the result in your backend</li>
</ol>
<p><img src="https://media.discordapp.net/attachments/571377798309216268/904790268505641050/unknown.png" alt="check_img" /></p>]]></content:encoded>
    </item>
    <item>
      <title>Set order of backend menu items</title>
      <link>https://octobertricks.com/tricks/central-control-of-the-backend-menu-items</link>
      <description>Especially with larger projects, it makes sense to sort the backend menu items.
Blinks4451850 and mjauvin have developed a clear variant to control the order:</description>
      <content:encoded><![CDATA[<p>Especially with larger projects, it makes sense to sort the backend menu items.</p>
<p><code>Blinks4451850</code> and <code>mjauvin</code> have developed a clear variant to control the order:</p>
<pre><code>Event::listen('backend.menu.extendItems', function ($manager) {
    $items = $manager-&gt;listMainMenuItems();
    $data = [
        'October.Backend.Media',
        'October.Backend.Dashboard',
        'October.Cms.cms',
        'RainLab.Builder.Builder',
    ];
    $i = 0;
    foreach ($data as $name) {
        if ($item = array_get($items, strtoupper($name), false)) {
            $item-&gt;order = $i;
            $i++;
        }
    }
});</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Display a relation count in a List via columns.yaml</title>
      <link>https://octobertricks.com/tricks/display-relation-count-list-columnsyaml</link>
      <description>Given you have a model that uses a count property on a relationship to get only the related model count:
To display this count value in a List, use the useRelationCount option in your columns.yaml. Using the usual select: count...</description>
      <content:encoded><![CDATA[<p>Given you have a model that uses a <code>count</code> property on a relationship to get only the related model count:</p>
<pre><code class="language-php">    public $hasOne = [
        'comments_count' =&gt; [Comment::class, 'count' =&gt; true],
    ];</code></pre>
<p>To display this count value in a List, use the <code>useRelationCount</code> option in your <code>columns.yaml</code>. Using the usual <code>select: count</code> method would result in a <code>Unknown column 'count' in 'field list'</code> error.</p>
<pre><code class="language-yaml">    comments_count:
        label: Number of related comments
        type: number
        relation: comments_count
        useRelationCount: true             # this is important</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>How to get a list of CMS pages that use a specific component</title>
      <link>https://octobertricks.com/tricks/how-to-get-a-list-of-cms-pages-that-use-a-specific-component</link>
      <description>Sometimes it is necessary to add a plugin entry to a specific CMS page.
An example: 

Testimonials should be placed on different pages. So I have to add every testimonial to a CMS page.
However, not every page (imprint, contact...</description>
      <content:encoded><![CDATA[<p>Sometimes it is necessary to add a plugin entry to a specific CMS page.</p>
<p><strong>An example: </strong></p>
<blockquote>
<p>Testimonials should be placed on different pages. So I have to add every testimonial to a CMS page.</p>
<p>However, not every page (imprint, contact form, etc.) can display testimonials. Therefore, a dropdown with all options would be a bit confusing for the customer.</p>
</blockquote>
<p>In order to only display CMS pages in the  <a href="https://octobercms.com/docs/backend/forms#field-dropdown">backend dropdown</a> that display a testimonial, the <code>withComponent</code> scope can be used.</p>
<p><code>$options = \Cms\Classes\Page::withComponent('showTestimonial')-&gt;all();</code></p>]]></content:encoded>
    </item>
    <item>
      <title>Create new users in unit test</title>
      <link>https://octobertricks.com/tricks/create-new-users-in-unit-test</link>
      <description>If you ever need to create a new user in your plugin unit tests, you first need to ensure early initialization of the Rainlab.User in your Plugin.php file, as below:
Then, in your test class you can create new user:...</description>
      <content:encoded><![CDATA[<p>If you ever need to create a new user in your plugin unit tests, you first need to ensure early initialization of the Rainlab.User in your Plugin.php file, as below:</p>
<pre><code class="language-php">class Plugin extends PluginBase
{
    // make  sure the rainlab.user plugin is loaded already
    public $require = ['RainLab.User'];

    // ... continue with other initialization</code></pre>
<p>Then, in your test class you can create new user:</p>
<pre><code class="language-php">        // create a user
        $this-&gt;user = User::create([
            'name' =&gt; 'Some User',
            'email' =&gt; 'test@test.com',
            'password' =&gt; 'changeme!!!',
            'password_confirmation' =&gt; 'changeme!!!'
        ]);

        // in order to log in as this user, we must be activated
        $this-&gt;user-&gt;is_activated = true;
        $this-&gt;user-&gt;activated_at = now();
        $this-&gt;user-&gt;save();</code></pre>
<p>... and log-in as that user elsewhere in your unit tests:</p>
<pre><code class="language-php">        // register the auth facade
        $alias = AliasLoader::getInstance();
        $alias-&gt;alias('Auth', 'RainLab\User\Facades\Auth');

        App::singleton('user.auth', function() {
            return \RainLab\User\Classes\AuthManager::instance();
        });

        Auth::login($this-&gt;user);
        // we should now be authenticated
        $this-&gt;assertTrue(Auth::check());</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Making the Settings screen logo clickable</title>
      <link>https://octobertricks.com/tricks/making-the-settings-screen-logo-clickable</link>
      <description>So I wanted to link the uploaded backend logo (the one that appears on /backend/system/settings) to my website.
You can do this in 2 ways. First being by overloading the controller middleware:
The second, you could also do this by...</description>
      <content:encoded><![CDATA[<p>So I wanted to link the uploaded backend logo (the one that appears on <strong>/backend/system/settings</strong>) to my website.</p>
<p>You can do this in 2 ways. First being by <a href="https://octobercms.com/docs/backend/controllers-ajax#controller-middleware">overloading the controller middleware</a>:</p>
<pre><code>    Event::listen('backend.page.beforeDisplay', function ($backendController, $action, $params) {
        if ($backendController instanceof \System\Controllers\Settings &amp;&amp; $action === 'index') {
            $backendController-&gt;middleware(function ($request, $response) {
                $basePath = url('//www.yoururl.com');
                $injectedJs = &lt;&lt;&lt; THEINJECTEDJS
&lt;script&gt;
    $(function() {
        $('.layout-cell .oc-logo-transparent').on('click', function(){
             document.location.href = '$basePath';
             return false;
        });
    });
&lt;/script&gt;
THEINJECTEDJS;
                $response-&gt;setContent($response-&gt;getContent() . $injectedJs);
            });
        }
    });</code></pre>
<p>The second, you could also do this by listening to the extendHead view event:</p>
<pre><code>    Event::listen('backend.layout.extendHead', function ($controller, $layout) {
        $basePath = url('//www.yoururl.com');
                return &lt;&lt;&lt; THEINJECTEDJS
&lt;script&gt;
    $(function() {
        $('.layout-cell .oc-logo-transparent').on('click', function(){
             document.location.href = '$basePath';
             return false;
        });
    });
&lt;/script&gt;
THEINJECTEDJS;
                }</code></pre>
<p>Which is similar but does the same without overloading the middleware function.</p>]]></content:encoded>
    </item>
    <item>
      <title>Defining quick actions in the backend main navigation</title>
      <link>https://octobertricks.com/tricks/defining-quick-actions-in-the-main-navigation</link>
      <description>To define quick actions in the main navigation, you need to add this method to the Plugin.php file:
Works with the latest version of OctoberCms installed via composer.</description>
      <content:encoded><![CDATA[<p>To define quick actions in the main navigation, you need to add this method to the Plugin.php file:</p>
<pre><code>public function registerQuickActions()
{
    return [
        'help' =&gt; [
            'label' =&gt; 'Read the documentation',
            'icon' =&gt; 'icon-question-circle',
            'url' =&gt; Backend::url('read-the-docs'),
        ],
        'mail' =&gt; [
            'label' =&gt; 'Send email to developers',
                        // SVG-icon example
            'iconSvg' =&gt; '/plugins/sandbox/quickactions/assets/svg/mail.svg',
            'url' =&gt; Backend::url('mail-to-devs'),
        ],           
    ];
}</code></pre>
<p>Works with the latest version of OctoberCms installed via composer.</p>]]></content:encoded>
    </item>
    <item>
      <title>Define a global variable on the CMS controller</title>
      <link>https://octobertricks.com/tricks/define-global-variable-cms-controller</link>
      <description>To define a variable that is available on your controller everywhere, you can use the following event listener:
You can now access this variable in Twig or any PHP code section that has access to the CMS controller instance:
Page...</description>
      <content:encoded><![CDATA[<p>To define a variable that is available on your controller everywhere, you can use the following event listener:</p>
<pre><code class="language-php">\Event::listen('cms.page.init', function($controller) {
    $controller-&gt;vars['my_special_variable'] = 'some-value';
});</code></pre>
<p>You can now access this variable in Twig or any PHP code section that has access to the CMS controller instance:</p>
<pre><code class="language-twig">{{ my_special_variable }}</code></pre>
<p>Page lifecycle example, works in Components as well:</p>
<pre><code class="language-php">function onStart()
{
    $special = $this-&gt;controller-&gt;vars['my_special_variable'];
}</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Automatically run october:up after running composer update</title>
      <link>https://octobertricks.com/tricks/automatically-run-octoberup-after-running-composer-update</link>
      <description>When using composer with October CMS it might be handy to automatically run the october:up command after updating with composer. 
Find the scripts section in your projects composer.json file and add the php artisan october:up script to the post-update-cmd section....</description>
      <content:encoded><![CDATA[<p>When using composer with October CMS it might be handy to automatically run the <code>october:up</code> command after updating with composer. </p>
<p>Find the <code>scripts</code> section in your projects <code>composer.json</code> file and add the <code>php artisan october:up</code> script to the <code>post-update-cmd</code> section. It might look like this now:</p>
<pre><code>"scripts": {
        "post-create-project-cmd": [
                "php artisan key:generate"
        ],
        "post-update-cmd": [
                "php artisan october:up"
        ]
},</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Make session available in middleware</title>
      <link>https://octobertricks.com/tricks/make-session-available-in-middleware</link>
      <description>To make the session context available in a middleware, you have to push the middleware to the Router instead of the Kernel and add it to the web group.</description>
      <content:encoded><![CDATA[<p>To make the session context available in a middleware, you have to push the middleware to the Router instead of the Kernel and add it to the web group.</p>
<pre><code class="language-php">public function boot(): void
{
    /** @var \Illuminate\Routing\Router $router */
    $router = $this-&gt;app-&gt;make(\Illuminate\Routing\Router::class);
    $router-&gt;pushMiddlewareToGroup('web', YourMiddleware::class);
}</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>How to set default values for backend form fields</title>
      <link>https://octobertricks.com/tricks/how-set-default-values-form-fields</link>
      <description>In your controller, use the formExtendModel method to set the model's properites:</description>
      <content:encoded><![CDATA[<p>In your controller, use the <code>formExtendModel</code> method to set the model's properites:</p>
<pre><code class="language-php">    public function formExtendModel($model)
    {
        if ($this-&gt;formGetContext() === 'create') {
            $model-&gt;your_field = 'Your default value';
        }
    }</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Set default locale for newly registered backend users</title>
      <link>https://octobertricks.com/tricks/set-default-locale-for-newly-registered-backend-users</link>
      <description>In your plugin's boot method:</description>
      <content:encoded><![CDATA[<p>In your plugin's boot method:</p>
<pre><code>        \Backend\Models\User::extend(function ($model) {
            $model-&gt;bindEvent('model.afterCreate', function () use ($model) {
                \Backend\Models\UserPreference::forUser($model)-&gt;set('backend::backend.preferences', ['locale' =&gt; 'es']);
            });
        });</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Extending Backend Settings to add fields (such as maintenance mode, Customize-backend page)</title>
      <link>https://octobertricks.com/tricks/extending-backend-settings-to-add-fields-such-as-maintenance-mode-customize-backend-page</link>
      <description>If you want to extend a Settings of another plugin or backend section to add fields i.e. the ones that don't have an exclusive controller but rather are just a settings page, you need to extend the form widget associated...</description>
      <content:encoded><![CDATA[<p>If you want to extend a Settings of another plugin or backend section to add fields i.e. the ones that don't have an exclusive controller but rather are just a settings page, you need to extend the form widget associated with it. Now at first if you look at System\Controllers\Settings, the class responsible for rendering settings it may feel like a good idea to extend that and called extendFormFields from your Plugin boot but it wouldn't work since the Settings controller is a special controller that doesn't implement form behavior but directly loads a formwidget internally. So to extend it, you have to hook into it's Form's extension methods.</p>
<p>As an example, let us extend the Maintainence Mode page from another plugin. In the Plugin.php boot method, include:</p>
<pre><code>        Event::listen('backend.form.extendFields', function ($widget) {

            if (!$widget-&gt;getController() instanceof \System\Controllers\Settings) {
                return;
            }

            // Only for the MaintenanceSetting model
            if (!$widget-&gt;model instanceof \Cms\Models\MaintenanceSetting) {
                return;
            }

            $widget-&gt;addFields([
                'disable_feature' =&gt; [
                    'label'   =&gt; 'Disable Feature?',
                    'type'    =&gt; 'switch'
                ]
            ]);
        });</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>How to define global functions in October CMS</title>
      <link>https://octobertricks.com/tricks/how-to-define-global-functions-in-october-cms</link>
      <description>I've seen this question asked over and over again, and just found how to do this cleanly and easily with October...

Just add a file called "init.php" within your plugin's root:
init.php:</description>
      <content:encoded><![CDATA[<p>I've seen this question asked over and over again, and just found how to do this cleanly and easily with October...</p>

<p>Just add a file called "init.php" within your plugin's root:</p>
<p>init.php:</p>
<pre><code>&lt;?php

function myGlobalFunction()
{
    return "Hello World!";
}</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Add filtering to a ReorderController</title>
      <link>https://octobertricks.com/tricks/addind-filtering-to-a-reordercontroller</link>
      <description>Add this snippet to your controller's _reorder_toolbar.htm partial:
Add this to your Controller class:</description>
      <content:encoded><![CDATA[<p>Add this snippet to your controller's <code>_reorder_toolbar.htm</code> partial:</p>
<pre><code>    &lt;input name="filter-records" type="text" class="form-control icon search growable"
        data-request="onFilterRecords"
        data-track-input
    /&gt;</code></pre>
<p>Add this to your Controller class:</p>
<pre><code>    public function onFilterRecords()
    {   
        $reorderController = $this-&gt;asExtension('ReorderController');
        $reorderController-&gt;reorder();
        return [
            '#reorderRecords' =&gt; $reorderController-&gt;reorderMakePartial('records', ['records' =&gt; $reorderController-&gt;vars['reorderRecords']]),
        ];
    }

    public function reorderExtendQuery($query)
    {   
        if ($term = Input::get('filter-records')) {
            $query-&gt;where('name', 'like', "%$term%");
        }
    }</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Create a re-usable custom list column type with assets and partials</title>
      <link>https://octobertricks.com/tricks/create-a-re-usable-custom-list-column-type-with-assets-and-partials</link>
      <description/>
      <content:encoded><![CDATA[<p>While the October docs do have information on creating a <a href="https://octobercms.com/docs/backend/lists#custom-column-types">custom list column type</a>, they unfortunately use direct method callbacks, which can make it tricky to use assets for the column type.</p>
<p>By leveraging a List widget event and following the instructions below, you can create a complex custom list column type that supports asset injection into the controller, as well as partial rendering.</p>
<p>For the purposes of this trick, we are creating a <code>graph</code> list column type within the <code>Acme.Demo</code> plugin.</p>
<h3>/plugins/acme/demo/columntypes/Graph.php</h3>
<pre><code>&lt;?php namespace Acme\Demo\ColumnTypes;

use Event;

class Graph
{
    use \System\Traits\ViewMaker;
    use \System\Traits\AssetMaker;

    /**
     * @var \Backend\Classes\Controller Controller instance
     */
    protected $controller;

    /**
     * @var bool Has the column type been rendered?
     */
    protected $rendered = false;

    /**
     * @var bool Has the CSS been injected?
     */
    protected $addedCss = false;

    /**
     * Constructor.
     */
    public function __construct()
    {
        // Inject CSS into controller, only if the column type is actually used
        Event::listen('backend.list.overrideColumnValue', function ($listWidget) {
            if ($this-&gt;rendered &amp;&amp; !$this-&gt;addedCss) {
                $this-&gt;controller = $listWidget-&gt;getController();
                $this-&gt;addCss(
                    '/plugins/acme/demo/columntypes/graph/assets/css/graph.css',
                    'Acme.Demo'
                );

                                // Add any additional CSS/JS assets here as required.

                $this-&gt;addedCss = true;
            }
        });
    }

    /**
     * Renders the "graph" column type.
     * 
     * This is the callback which is registered in `registerListColumnTypes` in the Plugin definition file.
     *
     * @param mixed $value
     * @param \Backend\Classes\ListColumn $column
     * @param \October\Rain\Database\Model $record
     * @return array|string
     */
    public function renderValue($value, $column, $record)
    {
        $this-&gt;rendered = true;

        return $this-&gt;makePartial('graph', [
                            // Add params for partial here
        ]);
    }
}</code></pre>
<h3>/plugins/acme/demo/Plugin.php</h3>
<pre><code class="language-php">
// ...

    public function registerListColumnTypes()
    {
        return [
            'graph' =&gt; [
                new \Acme\Demo\ColumnTypes\Graph,
                'renderValue',
            ],
        ];
    }

// ...</code></pre>
<p>You can now create the following partials and assets:</p>
<ul>
<li><code>/plugins/acme/demo/columntypes/graph/_graph.htm</code> - Contains the HTML content to output for the column.</li>
<li><code>/plugins/acme/demo/columntypes/graph/assets/css/graph.css</code> - Contains the CSS content that will be injected into the controller and added to the <code>&lt;head&gt;</code>.</li>
</ul>
<p>The custom column type will now be available for use in all list widgets under the <code>graph</code> type.</p>
<p>For example:</p>
<pre><code class="language-yaml">columns:
    progress:
            label: Progress
                type: graph</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Get all filtered records by a List Widget</title>
      <link>https://octobertricks.com/tricks/get-all-filtered-records-by-a-list-widget</link>
      <description>If you want to take an action on all currently filtered records from your Controller implementing the ListController behavior, add this method to your controller:</description>
      <content:encoded><![CDATA[<p>If you want to take an action on all currently filtered records from your Controller implementing the ListController behavior, add this method to your controller:</p>
<pre><code>    public function onGetFilteredRecords()
    {
        $this-&gt;makeLists();
        $listWidget = $this-&gt;asExtension('ListController')-&gt;listGetWidget();

        $query = $listWidget-&gt;prepareQuery();
        $records = $query-&gt;get();

        // do something with $records
    }</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Switching the registered user group in a User model based on boolean input</title>
      <link>https://octobertricks.com/tricks/switching-the-registered-user-group-in-a-user-model-based-on-boolean-input</link>
      <description>Given a registered flag that may arrive from an API or any other source, this block can be used to switch the registered flag. Directly calling add or remove causes exceptions so it's essential to check like this:</description>
      <content:encoded><![CDATA[<p>Given a registered flag that may arrive from an API or any other source, this block can be used to switch the registered flag. Directly calling add or remove causes exceptions so it's essential to check like this:</p>
<pre><code class="language-php">$registered = Input::get('is_registered');
$registeredGroup = \RainLab\User\Models\UserGroup::whereName('registered')-&gt;first();
if ($registered) {
    if (!$user-&gt;groups()-&gt;whereName('registered')-&gt;exists()) {
        $user-&gt;groups()-&gt;add($registeredGroup);
        $user-&gt;save();
    }
} else {
    if ($user-&gt;groups()-&gt;whereName('registered')-&gt;exists()) {
        $user-&gt;groups()-&gt;remove($registeredGroup);
        $user-&gt;save();
    }
}</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>OctoberCMS Stack Documentation for Teams</title>
      <link>https://octobertricks.com/tricks/octobercms-stack-documentation-for-teams</link>
      <description>If you need a base on documentation that's already been built, clone this repository and edit accordingly. 
https://github.com/artistro08/artistro08.github.io
Clone: 
Uses docsify.js</description>
      <content:encoded><![CDATA[<p>If you need a base on documentation that's already been built, clone this repository and edit accordingly. </p>
<p><a href="https://github.com/artistro08/artistro08.github.io">https://github.com/artistro08/artistro08.github.io</a></p>
<p>Clone: </p>
<pre><code class="language-bash">git clone https://github.com/artistro08/artistro08.github.io.git</code></pre>
<p>Uses <a href="https://docsify.js.org">docsify.js</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Refresh the backend form of an extended plugin after saving</title>
      <link>https://octobertricks.com/tricks/refresh-the-backend-form-of-an-extended-plugin-after-saving</link>
      <description>Refreshing a backend form on save can be done if you modify the _post_toolbar.htm partial to include refresh:1 as mentioned below. Create a new file called _post_toolbar.htm with the contents below and place it in the partials folder of your...</description>
      <content:encoded><![CDATA[<p>Refreshing a backend form on save can be done if you modify the <code>_post_toolbar.htm</code> partial to include <code>refresh:1</code> as mentioned below. Create a new file called <code>_post_toolbar.htm</code> with the contents below and place it in the <code>partials</code> folder of your own plugin.</p>
<pre><code>&lt;?php 
        $isCreate = $this-&gt;formGetContext() == 'create'; 
        $pageUrl = isset($pageUrl) ? $pageUrl : null; 
?&gt; 
&lt;div class="form-buttons loading-indicator-container"&gt; 

        &lt;!-- Save --&gt; 
        &lt;a 
                href="nojavascript...;" 
                class="btn btn-primary oc-icon-check save" 
                data-request="onSave" 
                data-load-indicator="&lt;?= e(trans('backend::lang.form.saving')) ?&gt;" 
                data-request-before-update="$el.trigger('unchange.oc.changeMonitor')" 
                &lt;?php if (!$isCreate): ?&gt;data-request-data="refresh:1"&lt;?php endif ?&gt; 
                data-hotkey="ctrl+s, cmd+s"&gt; 
                        &lt;?= e(trans('backend::lang.form.save')) ?&gt; 
        &lt;/a&gt; 

        &lt;?php if (!$isCreate): ?&gt; 
                &lt;!-- Save and Close --&gt; 
                &lt;a 
                        href="nojavascript...;" 
                        class="btn btn-primary oc-icon-check save" 
                        data-request-before-update="$el.trigger('unchange.oc.changeMonitor')" 
                        data-request="onSave" 
                        data-load-indicator="&lt;?= e(trans('backend::lang.form.saving')) ?&gt;"&gt; 
                                &lt;?= e(trans('backend::lang.form.save_and_close')) ?&gt; 
                &lt;/a&gt; 
        &lt;?php endif ?&gt; 

        &lt;!-- Preview --&gt; 
        &lt;a 
                href="&lt;?= URL::to($pageUrl) ?&gt;" 
                target="_blank" 
                class="btn btn-primary oc-icon-crosshairs &lt;?php if (!false): ?&gt;hide&lt;?php endif ?&gt;" 
                data-control="preview-button"&gt; 
                        &lt;?= e(trans('backend::lang.form.preview_title')) ?&gt; 
        &lt;/a&gt; 

        &lt;?php if (!$isCreate): ?&gt; 
                &lt;!-- Delete --&gt; 
                &lt;button 
                        type="button" 
                        class="btn btn-default empty oc-icon-trash-o" 
                        data-request="onDelete" 
                        data-request-confirm="&lt;?= e(trans('rainlab.blog::lang.post.delete_confirm')) ?&gt;" 
                        data-control="delete-button"&gt;&lt;/button&gt; 
        &lt;?php endif ?&gt; 
&lt;/div&gt; </code></pre>
<p>Then, in your plugins own Plugin.php file, add the following code in the <code>boot()</code> method:</p>
<pre><code>\Event::listen('backend.form.extendFieldsBefore', function ($widget) {
                if (!($widget-&gt;getController() instanceof \RainLab\Blog\Controllers\Posts &amp;&amp; $widget-&gt;model instanceof \RainLab\Blog\Models\Post)) {
                        return;
                }
                $widget-&gt;fields['toolbar']['path'] = '$/author/plugin/partials/_post_toolbar.htm';
});</code></pre>
<p>After saving your form, the page should refresh and display the right values if you modified something with a <code>beforeSave event</code>.</p>
<p>Credits to @mjauvin and @lucas.sanner54070 for suggesting this in the October CMS forums, with the above example of the Rainlab Blog plugin:</p>]]></content:encoded>
    </item>
    <item>
      <title>Remove another plugin's main menu items</title>
      <link>https://octobertricks.com/tricks/remove-other-plugins-main-menu-items</link>
      <description>Place the following event listener in your Plugin's boot method to remove another plugin's menu items:</description>
      <content:encoded><![CDATA[<p>Place the following event listener in your Plugin's <code>boot</code> method to remove another plugin's menu items:</p>
<pre><code class="language-php">Event::listen('backend.menu.extendItems', function($manager) {
    $manager-&gt;removeMainMenuItem('October.Cms', 'cms');
    $manager-&gt;removeSideMenuItem('October.Cms', 'cms', 'pages');
});</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Include SVGs inline in themes</title>
      <link>https://octobertricks.com/tricks/include-svgs-inline-in-themes</link>
      <description>See https://wintertricks.com/tricks/include-svgs-inline-themes</description>
      <content:encoded><![CDATA[<p>See <a href="https://wintertricks.com/tricks/include-svgs-inline-themes">https://wintertricks.com/tricks/include-svgs-inline-themes</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Clean HTML Pasted into Froala</title>
      <link>https://octobertricks.com/tricks/clean-html-pasted-into-froala</link>
      <description>Then include via:</description>
      <content:encoded><![CDATA[<pre><code class="language-js">/**
 * Froala - Clean HTML Plugin.
 */
+function ($) {
    $.FroalaEditor.PLUGINS.cleanHtml = function (editor) {
        function _init() {
            editor.events.on('paste.beforeCleanup', function (clipboardHtml) {
                return _convertHtmlToPlainText(clipboardHtml);
            });
        }
        function _convertHtmlToPlainText(clipboardHtml) {
            return '&lt;p&gt;' + clipboardHtml.replace(/&lt;br&gt;/gi, "\n").replace(/&lt;(?:.|\s)*?&gt;/g, '') + '&lt;/p&gt;';
        }
        return {
            _init: _init
        };
    };
}(jQuery);</code></pre>
<p>Then include via:</p>
<pre><code class="language-php">/**
 * Extend Rich Editor.
 */
\Backend\FormWidgets\RichEditor::extend(function ($widget) {
    $widget-&gt;addJs('/plugins/author/name/assets/js/froala.clean-html.js', 'Author.Name');
});</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Add links to Rich Editor search link section</title>
      <link>https://octobertricks.com/tricks/add-links-to-rich-editor-search-link-section</link>
      <description>If you want to add links to the rich editor "choose link" section 

The links will appear in this dropdown 

In your plugin boot method add those two events.
In your model prepare the generate url logic.</description>
      <content:encoded><![CDATA[<p>If you want to add links to the rich editor "choose link" section </p>
<p><img src="https://i.ibb.co/wpDVgY8/1.png" alt="" /></p>
<p>The links will appear in this dropdown </p>
<p><img src="https://i.ibb.co/KGWkKvd/2-pagelink.png" alt="" /></p>
<p>In your plugin <code>boot</code> method add those two events.</p>
<pre><code>Event::listen('backend.richeditor.listTypes', function () {
    return [
        'your_type' =&gt; 'Title',
    ];
});

Event::listen('backend.richeditor.getTypeInfo', function ($type) {
    if ($type === 'your_type') {
        return Model::getRichEditorTypeInfo($type);
    }   
});</code></pre>
<p>In your model prepare the generate url logic.</p>
<pre><code>public static function getRichEditorTypeInfo($type)
{
    if ($type == 'your_type') {
        $yourTypes = self::all();
        $selectOptions = [];  //array to populate with urls

        foreach ($yourTypes as $type) {
            $selectOptions['your url'] = [
                'title' =&gt; 'Your title',
                // 'items'=&gt; additional items added as subsection
            ];
        }

        return $selectOptions;
    }

    return [];
}</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Display post author on your blog post page using RainLab.Blog plugin</title>
      <link>https://octobertricks.com/tricks/display-post-author-on-your-blog-post-page-using-rainlabblog-plugin</link>
      <description>How to display post author on your blog post page

At some point you probably needed to create some kind of widget with post author data like it's displayed on other blogging platforms such as Medium or as usually seen...</description>
      <content:encoded><![CDATA[<h3>How to display post author on your blog post page</h3>
<p>
At some point you probably needed to create some kind of widget with post author data like it's displayed on other blogging platforms such as Medium or as usually seen on many Wordpress blogs.
</p>
<p>
Dive in to learn how to exactly get user data from post and display them on your CMS page
</p>

<img src="">
<p>Let's assume that you have some experience working with OctoberCMS and you already have CMS page with blog post component in place.
</p>
<p>
If you haven't worked with RainLab.Blog plugin before, please go ahead and read the <a href="https://octobercms.com/plugin/rainlab-blog" target="_blank">official documentation</a>.
</p>
<h4>
Post page
</h4>
<p>
We are using bootstrap as css framework which won't be a problem teaching you how to display user data but your design might be different so keep that in mind.
</p>
<p>Basic display of post data</p>
<pre><code>&lt;section id="single-post"&gt;
    &lt;div class="container"&gt;
        &lt;div class="single-row row"&gt;
            &lt;div class="single-col-1 col-xl-7 col-lg-7 col-md-8 col-sm-12 col-10"&gt;
                &lt;!-- POST TITLE --&gt;
                &lt;h1 class="post-title"&gt;
                    {{ post.title }}
                &lt;/h1&gt;
                &lt;hr class="post-title-separator"&gt;
                &lt;!-- POST PUBLISH DATE --&gt;
                &lt;p class="post-date"&gt;{{ post.published_at | strftime('%d.%m.%Y')}}&lt;/p&gt;
            &lt;/div&gt;
            &lt;!-- POST CONTENT --&gt;
            &lt;div class="single-col-2 col-xl-7 col-lg-8 col-md-10 col-sm-10 col-10"&gt;
                {{ post.content_html|raw }}
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/section&gt;</code></pre>
<p>
As you can see from the code above it's simple and we get to show basic post data such as title, published at date, and post content. If you are having issues with date format try installing twig extension plugin.
</p>
<p>
Now, let's say you want to display name, and avatar of the post author. If you tried working with OctoberCMS and Blog plugin it's really simple. All you need to do is access user property inside post model.
</p>
<pre><code>&lt;section id="single-post"&gt;
    &lt;div class="container"&gt;
        &lt;div class="single-row row"&gt;
            &lt;div class="single-col-1 col-xl-7 col-lg-7 col-md-8 col-sm-12 col-10"&gt;
                &lt;!-- POST TITLE --&gt;
                &lt;h1 class="post-title"&gt;
                    {{ post.title }}
                &lt;/h1&gt;
                &lt;hr class="post-title-separator"&gt;

                &lt;!-- AUTHOR DATA --&gt;
                 &lt;img style="border-radius: 40px;display: block; margin-left: auto; margin-right: auto; margin-bottom: 10px;" src="{{ post.user.avatar.path }}" height="80px;"/&gt;
                &lt;p class="post-date"&gt;By: 
                   style="color: #ef0d33"&gt;
                        {{ post.user.first_name }} {{ post.user.last_name }}
                    &lt;/a&gt;
                &lt;/p&gt;

                &lt;!-- POST PUBLISH DATE --&gt;
                &lt;p class="post-date"&gt;{{ post.published_at | strftime('%d.%m.%Y')}}&lt;/p&gt;
            &lt;/div&gt;
            &lt;!-- POST CONTENT --&gt;
            &lt;div class="single-col-2 col-xl-7 col-lg-8 col-md-10 col-sm-10 col-10"&gt;
                {{ post.content_html|raw }}
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/section&gt;</code></pre>
<p>
If you are curious what is inside User model you can use code section on CMS page to find out. It's best to use onEnd function as that's when page and components are loaded fully. For example:
</p>
<pre><code>function onEnd(){
    dd($this-&gt;post-&gt;user-&gt;attributes); // This will give you user data 
}</code></pre>
<p>
    Hope this helps you understand how RainLab.Blog Post component works
    </p>]]></content:encoded>
    </item>
    <item>
      <title>Use an AJAX request handler on a backend settings form</title>
      <link>https://octobertricks.com/tricks/use-ajax-request-handler-backend-settings-form</link>
      <description>A backend settings form usually only has a form model, but no separate controller available. If you want to register a custom AJAX request handler you have to add it to the \System\Controllers\Settings controller. October re-uses this controller for all...</description>
      <content:encoded><![CDATA[<p>A backend settings form usually only has a form model, but no separate controller available. If you want to register a custom AJAX request handler you have to add it to the <code>\System\Controllers\Settings</code> controller. October re-uses this controller for all backend settings pages. </p>
<p>You can use the <code>extend()</code> method to add a custom handler:</p>
<pre><code class="language-php">    // Plugin.php
    public function boot()
    {
        \System\Controllers\Settings::extend(function($controller) {
            $controller-&gt;addDynamicMethod('onMyCustomHandler', function() {
                return 'handler called!';
            });
        });
    }</code></pre>
<p>You can now call this handler from any custom partial in your backend settings form:</p>
<pre><code class="language-html">&lt;button class="btn btn-default"
        data-handler="onMyCustomHandler"&gt;
    Trigger AJAX request
&lt;/button&gt;</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>How to translate Static Page menu items</title>
      <link>https://octobertricks.com/tricks/how-to-translate-static-page-menu-items</link>
      <description>Update:  RainLab.Pages v1.3.6 along with Rainlab.Translate v1.7.3 now support translation natively.
The menus created using the RainLab.Pages plugin do not support translation. In order to overcome this limitation, I propose this simple solution:
When creating your menu items, use a...</description>
      <content:encoded><![CDATA[<p><strong><em>Update:  RainLab.Pages v1.3.6 along with Rainlab.Translate v1.7.3 now support translation natively.</em></strong></p>
<p>The menus created using the <code>RainLab.Pages</code> plugin do not support translation. In order to overcome this limitation, I propose this simple solution:</p>
<p>When creating your menu items, use a localization string as the title (e.g. <code>author.plugin::lang.menu.menuName</code>)</p>
<p>Then when rendering the menu in your partial, just use the <code>|trans</code> filter to localize the menu item:</p>
<pre><code>&lt;ul&gt;
    {% for item in items if not item.viewBag.isHidden %}
        &lt;li&gt;{{ item.title | trans }}&lt;/li&gt;
    {% endfor %}
&lt;/ul&gt;</code></pre>
<p>Of course, you'll need to create an entry in your plugin's lang folder for those localization strings.</p>]]></content:encoded>
    </item>
    <item>
      <title>Updating Report Widget partials with AJAX</title>
      <link>https://octobertricks.com/tricks/updating-report-widget-partials-with-ajax</link>
      <description>October provides a robust and feature rich dashboard system that allows users to add any number of widgets. These widgets are useful for displaying high level metrics, such as page views, access logs, etc. 
You may find the need to...</description>
      <content:encoded><![CDATA[<p>October provides a robust and feature rich dashboard system that allows users to add any number of widgets. These widgets are useful for displaying high level metrics, such as page views, access logs, etc. </p>
<p>You may find the need to update this content dynamically, based upon some action the user could make within the report widget. October's AJAX framework makes this relatively easy, so long as you know what to return from your AJAX handler. </p>
<p>This trick will provide an example of how to update your report widget partial using October's AJAX framework.</p>
<blockquote>
<p>Note: This trick assumes you have already created your report widget class and have a partial that needs to be updated. If you need help creating a report widget, please see the documentation <a href="https://octobercms.com/docs/backend/widgets#report-widgets">Report Widgets</a>. </p>
</blockquote>
<ol>
<li>Add a element to your partial to make the AJAX request. Here is an example:
<pre><code>&lt;button
data-request="onUpdateWidget"&gt;
Update
&lt;/button&gt;</code></pre></li>
<li>Add a new method to your report widget class <code>public function onUpdateWidget()</code>. For example:
<pre><code>public function onUpdateWidget()
{
return [
    '#'.$this-&gt;alias =&gt; $this-&gt;render()
    ];
}</code></pre></li>
</ol>
<blockquote>
<p>The secret sauce here is the widget's <code>alias</code> property, which determines which widget is actually being updated. Your widget should already have a <code>render()</code> method which returns the contents of the widget partial. </p>
</blockquote>
<p>Now, when you click the button in your report widget, the AJAX framework will make a request and call the handler <code>onUpdateWidget</code>. In this example, we have re-rendered the widget itself so any changes to data will be displayed. </p>
<p>We are free to return any content we wish, even other partials, or static content. The possibilities are limitless!</p>]]></content:encoded>
    </item>
  </channel>
  <channel>
    <title>October Tricks Popular</title>
    <link>https://octobertricks.com</link>
    <description>Popular Tricks from octobertricks.com</description>
    <atom:link href="" rel="self" type="application/rss+xml"/>
    <item>
      <title>Display current year in Twig</title>
      <link>https://octobertricks.com/tricks/display-current-year-in-twig</link>
      <description>Showing the current year in Twig is easier than you'd think. Here's how to display the current year inside of your Twig templates.
You'll find this code snippet very useful when displaying your copyright in the footer of the website....</description>
      <content:encoded><![CDATA[<p>Showing the current year in Twig is easier than you'd think. Here's how to display the current year inside of your Twig templates.</p>
<pre><code class="language-twig">{{ 'now' | date('Y') }}</code></pre>
<p>You'll find this code snippet very useful when displaying your copyright in the footer of the website. (e.g. <strong>MyWebsite © 2019</strong>)</p>]]></content:encoded>
    </item>
    <item>
      <title>Update backend list records in a popup</title>
      <link>https://octobertricks.com/tricks/update-records-from-list-view-in-a-popup</link>
      <description>Have you ever needed or wanted to update a record from the list view by opening a popup, rather than navigating to the update page? This trick will help you do just that!


Update the recordOnClick property of your config_list.yaml...</description>
      <content:encoded><![CDATA[<p>Have you ever needed or wanted to update a record from the list view by opening a popup, rather than navigating to the update page? This trick will help you do just that!</p>
<ol>
<li>Update the <code>recordOnClick</code> property of your <code>config_list.yaml</code> inside your controller's folder:</li>
</ol>
<pre><code># Link URL for each record
recordOnClick: "$.popup({ handler: 'onUpdateForm', extraData: { record_id: ':id' } })"</code></pre>
<ol start="2">
<li>Register the <code>onUpdateForm</code> handler in your controller class:</li>
</ol>
<pre><code>public function onUpdateForm()
    {     
        $this-&gt;asExtension('FormController')-&gt;update(post('record_id'));
        $this-&gt;vars['recordId'] = post('record_id');
        return $this-&gt;makePartial('update_form');
    }</code></pre>
<ol start="3">
<li>Create the <code>_update_form.htm</code> partial inside your controller's views directory (i.e. /plugins/author/controllers/controllerName):</li>
</ol>
<pre><code>&lt;?= Form::open(['id' =&gt; 'updateForm']) ?&gt;
    &lt;input type="hidden" name="record_id" value="&lt;?= $recordId ?&gt;" /&gt;
    &lt;div class="modal-header"&gt;
        &lt;button type="button" class="close" data-dismiss="popup"&gt;×&lt;/button&gt;
        &lt;h4 class="modal-title"&gt;&lt;?= e($this-&gt;pageTitle) ?&gt;&lt;/h4&gt;
    &lt;/div&gt;

    &lt;?php if (!$this-&gt;fatalError): ?&gt;

        &lt;div class="modal-body"&gt;
            &lt;?= $this-&gt;formRender() ?&gt;
        &lt;/div&gt;
        &lt;div class="modal-footer"&gt;
            &lt;button
                type="submit"
                data-request="onUpdate"
                onclick="$(this).data('request-data', {
                    redirect: 0
                })"
                data-hotkey="ctrl+s, cmd+s"
                data-popup-load-indicator
                class="btn btn-primary"&gt;
                &lt;u&gt;S&lt;/u&gt;ave
            &lt;/button&gt;

            &lt;button
                type="button"
                class="btn btn-default"
                data-dismiss="popup"&gt;
                &lt;?= e(trans('backend::lang.form.cancel')) ?&gt;
            &lt;/button&gt;
        &lt;/div&gt;

    &lt;?php else: ?&gt;

        &lt;div class="modal-body"&gt;
            &lt;p class="flash-message static error"&gt;&lt;?= e(trans($this-&gt;fatalError)) ?&gt;&lt;/p&gt;
        &lt;/div&gt;
        &lt;div class="modal-footer"&gt;
            &lt;button
                type="button"
                class="btn btn-default"
                data-dismiss="popup"&gt;
                &lt;?= e(trans('backend::lang.form.close')) ?&gt;
            &lt;/button&gt;
        &lt;/div&gt;

    &lt;?php endif ?&gt;

    &lt;script&gt;
        setTimeout(
            function(){ $('#updateForm input.form-control:first').focus() },
            310
        )
    &lt;/script&gt;

&lt;?= Form::close() ?&gt;</code></pre>
<ol start="4">
<li>Register the <code>onUpdate</code> handler in the controller class:</li>
</ol>
<pre><code>public function onUpdate()
    {
        $this-&gt;asExtension('FormController')-&gt;update_onSave(post('record_id'));
        return $this-&gt;listRefresh();
    }</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Override Translations with a Plugin</title>
      <link>https://octobertricks.com/tricks/override-translations-with-a-plugin</link>
      <description>October allows users to override translations on a per-site basis very easily, through the use of a /lang directory in the project's root. But what happens when these changes need to be bundled with a plugin, so they don't need...</description>
      <content:encoded><![CDATA[<p>October allows users to override translations on a per-site basis very easily, <a href="https://octobercms.com/docs/plugin/localization#overriding">through the use of a <code>/lang</code> directory in the project's root</a>. But what happens when these changes need to be bundled with a plugin, so they don't need to be applied manually per installation?</p>
<p><a href="https://octobercms.com/docs/api/translator/beforeresolve">Luckily, there is a very useful <code>translator.beforeResolve</code> event that allows translation results to be modified before they are returned back to the application.</a></p>
<p>With some slight enhancements, you are able to override any translation string present in your October app with a single event listener in your plugin's <code>boot()</code> method:</p>
<pre><code>use Event;
use Lang;

public function boot()
{
        Event::listen('translator.beforeResolve', function ($key, $replace, $locale) {
                $plugin = 'author.plugin'; // Replace this string with the path of the plugin this is being executed from

                // Check the translation doesn't originate from this plugin
                if (substr($key, 0, strlen($plugin)) != $plugin) {
                        // Contruct a possible translation path
                        $path = $plugin . '::lang.' . str_replace('::', '.', $key);

                        // Retrieve its results
                        $result = Lang::get($path);

                        // If an overriding translation is found, return it
                        if ($result != $path) {
                                return $result;
                        }
                }
        });
}</code></pre>
<p>Now, you can modify any translation in your plugin's <code>lang.php</code> files, like so:</p>
<pre><code>&lt;?php return [
    'acme' =&gt; [
        'blog' =&gt; [
            'lang' =&gt; [
                'plugin' =&gt; [
                    'name' =&gt; 'My Blog', // acme.blog::lang.plugin.name is overriden with 'My Blog'
                ],
            ],
        ],
    ],
    'backend' =&gt; [
        'lang' =&gt; [
            'user' =&gt; [
                'menu_label' =&gt; 'Users', // backend::lang.user.menu_label is overriden with 'Users'
            ],
        ],
    ],
];</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Creating Custom Backend Skins</title>
      <link>https://octobertricks.com/tricks/creating-custom-backend-skins</link>
      <description>This trick will help you get started with customizing October's backend UI. There are some important considerations to be made here:

Storm UI is based on Bootstrap 3
Decoupling Storm UI is a tedious process
This limits what is possible...</description>
      <content:encoded><![CDATA[<p>This trick will help you get started with customizing October's backend UI. There are some important considerations to be made here:</p>
<ol>
<li>Storm UI is based on Bootstrap 3</li>
<li>Decoupling Storm UI is a tedious process</li>
<li>This limits what is possible depending on your knowledge, time, and requirements</li>
</ol>
<blockquote>
<p>Please note this trick is intended to get you started, and does not cover making modifications to the UI. </p>
</blockquote>
<p><strong>Instructions</strong></p>
<ol>
<li>Create a new plugin <code>php artisan create:plugin Author.CustomSkin</code></li>
<li>Create a new folder in your plugin's directory called <code>skin</code></li>
<li>Create a new class in your plugin's <code>skin</code> directory called <code>CustomSkin.php</code>:</li>
</ol>
<pre><code>&lt;?php namespace Author\Plugin\Skin;

use Backend\Skins\Standard as BackendSkin;

/**
 * Modified backend skin information file.
 *
 * This is modified to include an additional path to override the default layouts.
 *
 */

class CustomSkin extends BackendSkin
{
    /**
     * {@inheritDoc}
     */
    public function getLayoutPaths()
    {
        return [
            plugins_path('/author/plugin/skin/layouts'),
            $this-&gt;skinPath . '/layouts'
        ];
    }
}</code></pre>
<ol start="4">
<li>Copy the <code>layouts</code> directory from the backend module to your plugin's <code>skin</code> directory</li>
<li>
<p>Update the <code>backendSkin</code> property in <code>config/cms.php</code> to use your new skin class: </p>
<pre><code>/*
|--------------------------------------------------------------------------
| Back-end Skin
|--------------------------------------------------------------------------
|
| Specifies the back-end skin to use.
|
*/

'backendSkin' =&gt; 'Author\CustomSkin\Skin\CustomSkin',</code></pre>
</li>
</ol>
<p>When you are finished, you should have a new plugin with a directory structure as below:</p>
<pre><code>plugins/
  author/                  &lt;=== Author name
    customskin/            &lt;=== Plugin name
      skin/
        layouts/
        CustomSkin.php     &lt;=== Custom skin class
      ...
      Plugin.php           &lt;=== Plugin registration file</code></pre>
<p>Upvote this trick or follow me on Twitter <a href="https://www.twitter.com/thegreatbarker">@thegreatbarker</a> if you would like me to publish a blog or video with more information!</p>
<p><strong>Credits</strong></p>
<p>Many thanks to @LukeTowers for helping me get started and better understanding how October's Backend works!</p>]]></content:encoded>
    </item>
    <item>
      <title>Define permissions for columns and fields in the backend</title>
      <link>https://octobertricks.com/tricks/permissions-for-columns-fields-in-backend</link>
      <description>This feature is available in Core starting from Build 460:  https://github.com/octobercms/october/pull/4520
Create a trait that extends the controller and form fields.
traits/ColumnFieldPermissions.php
Example of usage
Then we can use it in columns or fields like</description>
      <content:encoded><![CDATA[<p><strong>This feature is available in Core starting from Build 460:  <a href="https://github.com/octobercms/october/pull/4520">https://github.com/octobercms/october/pull/4520</a></strong></p>
<p>Create a trait that extends the controller and form fields.</p>
<h3>traits/ColumnFieldPermissions.php</h3>
<pre><code class="language-php">trait ColumnFieldPermissions
{
    public function formExtendFields($form, $fields)
    {
        foreach ($fields as $name =&gt; $field) {
            $permissionValue = array_get($field-&gt;config, 'permission');
            if ($permissionValue &amp;&amp; !$this-&gt;user-&gt;hasAccess($permissionValue)) {
                if (array_get($field-&gt;config, 'permissionReadOnly')) {
                    $field-&gt;readOnly = true;
                    $field-&gt;disabled = true;
                } else {
                    $form-&gt;removeField($name);
                }
            }
        }
    }

    public function listExtendColumns($list)
    {
        foreach ($list-&gt;columns as $name =&gt; $column) {
            $permissionValue = array_get($column, 'permission');
            if ($permissionValue &amp;&amp; !$this-&gt;user-&gt;hasAccess($permissionValue)) {
                $list-&gt;removeColumn($name);
            }
        }
    }
}</code></pre>
<h3>Example of usage</h3>
<pre><code class="language-php">use Samuell\Plugin\Traits\ColumnFieldPermissions;

class YourController extends Controller
{
    use ColumnFieldPermissions;

    ....
}</code></pre>
<p>Then we can use it in columns or fields like</p>
<pre><code class="language-yaml">name:
    permission: my.custom.permission</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Create dynamic ajax popup in the frontend</title>
      <link>https://octobertricks.com/tricks/create-dynamic-ajax-popup-in-front-end</link>
      <description>Creating a modal popup is very easy with Bootstrap. As best practises, you should use on sites about 1-2 modal windows at most inside the body tag. But what to do if you need more modal popups and those should...</description>
      <content:encoded><![CDATA[<p>Creating a modal popup is very easy with Bootstrap. As best practises, you should use on sites about 1-2 modal windows at most inside the body tag. But what to do if you need more modal popups and those should be dynamically in the best case?</p>
<p>In this tutorial, we show you how you to implement dynamic modal windows with Ajax in October CMS.
Before you can create the modal popup using the Bootstrap Framework, the Bootstrap and jQuery library need to included those in your layout htm file.</p>
<pre><code>&lt;script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"&gt;&lt;/script&gt;
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"&gt;&lt;/script&gt;
&lt;script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"&gt;&lt;/script&gt;
{% framework extras %}
{% scripts %}</code></pre>
<ol>
<li>Create a new component, for example, we name it:  AjaxPopup:</li>
</ol>
<pre><code>php artisan create:component Algoriq.Backpack AjaxPopup</code></pre>
<ol start="2">
<li>
<p>Then we write our function to call our popup window partial:</p>
<pre><code>public function onLoadPopupForm()
{
    return [
        'popup' =&gt; $this-&gt;renderPartial('@popup.htm')
    ];
}</code></pre>
</li>
<li>
<p>Bootstrap Modal Button.
The following example creates a button. This button (openBtn) triggers the ajax process to show the modal  popup window, we will write it in the default.htm component template.</p>
</li>
</ol>
<pre><code>&lt;a href="nojavascript...;" class="btn btn-primary" data-show-popup&gt;Show popup&lt;/a&gt;</code></pre>
<ol start="4">
<li>Bootstrap Modal Popup.
As next step we will create a new modal popup window template and call it popup.htm in same directory where the default.htm is and put the following code inside this file:</li>
</ol>
<pre><code>&lt;div class="modal fade" id="ajaxPopupForm" tabindex="-1" role="dialog" aria-labelledby="ajaxPopupFormLabel" aria-hidden="true"&gt;
    &lt;div class="modal-dialog" role="document"&gt;
        &lt;div class="modal-content"&gt;
            &lt;div class="modal-header"&gt;
                &lt;h5 class="modal-title" id="ajaxPopupFormLabel"&gt;Ajax Popup&lt;/h5&gt;
                &lt;button
                    type="button"
                    class="close"
                    data-dismiss="modal"
                    data-disable-on-ajax-start
                    data-enable-on-ajax-always
                    aria-label="Close"&gt;
                    &lt;span aria-hidden="true"&gt;×&lt;/span&gt;
                &lt;/button&gt;
            &lt;/div&gt;
            &lt;div class="modal-body"&gt;
                ...
            &lt;/div&gt;
            &lt;div class="modal-footer"&gt;
                &lt;button
                    type="button"
                    class="btn btn-secondary"
                    data-dismiss="modal"
                    data-disable-on-ajax-start
                    data-enable-on-ajax-always&gt;
                    Close
                &lt;/button&gt;
                &lt;button
                    type="submit"
                    class="btn btn-primary"
                    data-disable-on-ajax-start
                    data-enable-on-ajax-always&gt;
                    Save changes
                &lt;/button&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;</code></pre>
<ol start="5">
<li>After we have created a button and our modal template, we need to create an ajax handler to utilize our dynamic modal popups and a script where we can initialise this handler.
So in the next step, we create two javascript asset files the first one we name it, for example, ajaxUtils.js and put the following code inside this file:</li>
</ol>
<pre><code>$(function() {
    "use strict";

    var ajaxUtils = function() {
        this.registerHandlers()
    };

    ajaxUtils.prototype.registerHandlers = function() {
        var requestSenderSelector = 'form, a[data-request], input[data-request], select[data-request]';
        $(document).on('ajaxPromise', requestSenderSelector, $.proxy(this.onFormAjaxInit));
        $(document).on('ajaxFail', requestSenderSelector, $.proxy(this.onFormAjaxFail));
        $(document).on('ajaxDone', requestSenderSelector, $.proxy(this.onFormAjaxSuccess));
        $(document).on('shown.bs.modal', 'div.modal', $.proxy(this.onModalDisplayed, this));
        $(document).on('hidden.bs.modal', 'div.modal', $.proxy(this.onModalHidden, this));
    };

    ajaxUtils.prototype.onFormAjaxInit = function(e) {
        var $form = $(e.currentTarget).closest('form');

        if ($(e.target).attr('data-no-ajax-disable-effects') !== undefined) {
            return
        }

        $form.find('[data-disable-on-ajax-start]').prop('disabled', true).attr('disabled', 'disabled')
    };

    ajaxUtils.prototype.onFormAjaxFail = function(e) {
        var $form = $(e.currentTarget).closest('form');

        $form.find('[data-enable-on-ajax-fail], [data-enable-on-ajax-always]').prop('disabled', false).removeAttr('disabled')
    };

    ajaxUtils.prototype.onFormAjaxSuccess = function(e) {
        var $form = $(e.currentTarget).closest('form');

        $form.find('[data-enable-on-ajax-success], [data-enable-on-ajax-always]').prop('disabled', false).removeAttr('disabled')
    };

    ajaxUtils.prototype.onModalDisplayed = function(e) {
        var $defaultFocus = $('[data-default-focus]', e.currentTarget);

        $defaultFocus.focus()
    };

    ajaxUtils.prototype.onModalHidden = function(e) {
        $(e.currentTarget).remove()
    };

    new ajaxUtils()

});</code></pre>
<ol start="6">
<li>Our second asset file with the name ajaxPopup.js should contain the following code:</li>
</ol>
<pre><code>$(function() {
    var PopupBuilder = function() {

        function init() {
            bindEventHandlers()
        }

        function bindEventHandlers() {
            $(document).on('click', 'a[data-show-popup]', onLoadAjaxPopup);
        }

        function onLoadAjaxPopup(e) {
            showAjaxPopup(e)
        }

        function showAjaxPopup(e) {

            $.oc.stripeLoadIndicator.show();

            $(e.currentTarget).request('onLoadPopupForm', {
                data: {},
                success: function(data) {
                    $(data.popup).modal({
                        backdrop: 'static',
                        keyboard: true
                    });
                }
            }).always(function() {
                $.oc.stripeLoadIndicator.hide();
            });

            e.preventDefault();

            return false
        }

        init()
    };

    new PopupBuilder()
});</code></pre>
<p>Now you can place those files in your plugin assets folder for example (“assets/js/”) and initialize those assets scripts inside your plugin the following way:</p>
<pre><code>    public function onRun()
    {
        $this-&gt;addJs('/plugins/algoriq/backpack/assets/js/ajaxUtils.js');
        $this-&gt;addJs('/plugins/algoriq/backpack/assets/js/ajaxPopup.js');
    }</code></pre>
<p>Thank you for your attention I hope you enjoyed this tutorial. </p>
<p>However, if you have any suggestions or you probably see some room for improvements, then I would kindly ask you to drop me a line and I will get in touch with you as soon as possible!</p>]]></content:encoded>
    </item>
    <item>
      <title>RainLab.Pages: Custom page field cheatsheet</title>
      <link>https://octobertricks.com/tricks/custom-page-field-cheatsheet</link>
      <description>This is a short cheatsheet for Custom Page Fields:
String
Use in twig:
Textarea
Use in twig:
Checkbox
Use in twig:
Mediafinder
Use in twig:
Dropdown
Use in twig:
Repeater
Use in twig:</description>
      <content:encoded><![CDATA[<p>This is a short cheatsheet for Custom Page Fields:</p>
<h3>String</h3>
<pre><code class="language-html">{variable name="variableName" tab="tabName" label="fieldLabel" type="text"}{/variable}</code></pre>
<p>Use in twig:</p>
<pre><code class="language-twig">{{ variableName }}</code></pre>
<h3>Textarea</h3>
<pre><code class="language-html">{variable name="variableName" label="fieldLabel" tab="tabName" type="textarea"}{/variable}</code></pre>
<p>Use in twig:</p>
<pre><code class="language-twig">{{ variableName }}</code></pre>
<h3>Checkbox</h3>
<pre><code class="language-html">{variable name="variableName" tab="tabName" label="fieldLabel" type="checkbox"}{/variable}</code></pre>
<p>Use in twig:</p>
<pre><code class="language-twig">{% if variableName %}</code></pre>
<h3>Mediafinder</h3>
<pre><code class="language-html">{variable name="variableName" tab="tabName" label="fieldLabel" type="mediafinder"}{/variable}</code></pre>
<p>Use in twig:</p>
<pre><code class="language-twig">{{ variableName | media }}</code></pre>
<h3>Dropdown</h3>
<pre><code class="language-html">{variable name="variableName" tab="tabName" label="fieldLabel"
options="Option1|Option2|Option3" type="dropdown"}{/variable}

or

{variable name="variableName" tab="tabName" label="fieldLabel"
options="one:Option1|two:Option2|three:Option3" type="dropdown"}{/variable}
</code></pre>
<p>Use in twig:</p>
<pre><code class="language-twig">{% if variableName == 2 %} {# This means Option2 is selected. #}
or 
{% if variableName == two %} {# This means Option2 is selected (with keys). #}</code></pre>
<h3>Repeater</h3>
<pre><code class="language-html">{repeater name="repeaterName" prompt="Add an item." tab="tabName"}
    [...]
{/repeater}</code></pre>
<p>Use in twig:</p>
<pre><code class="language-twig">{% for repeaterItem in repeaterName %}
    [...]
{% endfor %}</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Add a relation manager widget to a form</title>
      <link>https://octobertricks.com/tricks/add-relation-manager-widget-form</link>
      <description>Given are the following models (adapt the class names and namespaces to your usecase):

Post: This is the base model, a simple blog post. We want to add the relation manager to this model's form.
Comment: This is the related...</description>
      <content:encoded><![CDATA[<p>Given are the following models (adapt the class names and namespaces to your usecase):</p>
<ul>
<li>Post: This is the base model, a simple blog post. We want to add the relation manager to this model's form.</li>
<li>Comment: This is the related model. A blog post has many comments.</li>
</ul>
<pre><code class="language-php">&lt;?php
namespace Acme\Blog\Models;

class Post extends Model
{
    // The relation manager works for any relation type, use whatever you need.
    public $hasMany = ['comments' =&gt; \Acme\Blog\Models\Comment::class];
}</code></pre>
<h2>Implementing and configuring the relation controller</h2>
<p>In your <code>PostsController</code> add the following lines:</p>
<pre><code class="language-php">&lt;?php
namespace Acme\Blog\Controllers;

class Posts extends Controller
{
    public $implement = [
        'Backend.Behaviors.FormController',
        'Backend.Behaviors.RelationController',         // Add this!
    ];

    public $formConfig = 'config_form.yaml';
    public $relationConfig = 'config_relation.yaml';    // Add this!
}</code></pre>
<p>Next, create the <code>config_relation.yaml</code> file in <code>plugins/acme/blog/controllers/posts/config_relation.yaml</code>.</p>
<p>Paste the contents below (in case of a <code>hasMany</code> relation) into the yaml file.
You can find more examples for different relationship types (<code>hasOne</code>, <code>belongsToMany</code>, etc) <a href="https://octobercms.com/docs/backend/relations#relationship-types" target="_blank">
in the official docs</a>.</p>
<pre><code class="language-yaml">comments:
    label: Comment    
    deferredBinding: true
    view:
        list: $/acme/blog/models/comment/columns.yaml
        toolbarButtons: create|delete
    manage:
        form: $/acme/blog/models/comment/fields.yaml
        recordsPerPage: 10</code></pre>
<h2>Displaying the relation manager</h2>
<p>Create a new file in <code>plugins/acme/blog/controllers/posts/_comments.htm</code>. Paste the following contents:</p>
<pre><code class="language-php">&lt;?= $this-&gt;relationRender('comments'); ?&gt;</code></pre>
<p>The <code>comments</code> key corresponds to the base key in your <code>config_relation.yaml</code>.</p>
<p>Now you can include this partial in your model's form definition to display the relation manager.</p>
<pre><code class="language-yaml">
# in plugins/acme/blog/models/post/fields.yaml
comments:
    type: partial
    path: comments # includes _comments.htm from the current controller's path.</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Disable Backend User Groups</title>
      <link>https://octobertricks.com/tricks/disable-backend-user-groups</link>
      <description>Disabling user group UI items is a great way of decluttering your backend for projects that don't use the features.
Firstly, this code is required in your plugin's Plugin.php:
Make sure to replace acme/blog with the name of your plugin....</description>
      <content:encoded><![CDATA[<p>Disabling user group UI items is a great way of decluttering your backend for projects that don't use the features.</p>
<p>Firstly, this code is required in your plugin's Plugin.php:</p>
<pre><code>use Backend\Controllers\Users as BackendUserController;
// ...
    public function boot()
    {
            BackendUserController::extend(function ($controller) {
                    $controller-&gt;listConfig = $controller-&gt;makeConfig($controller-&gt;listConfig);
                    $controller-&gt;listConfig-&gt;toolbar = array_merge($controller-&gt;listConfig-&gt;toolbar, ['buttons' =&gt; '$/acme/blog/partials/toolbar.users.htm']);
            });

            BackendUserController::extendListColumns(function ($list, $model) {
                    $list-&gt;removeColumn('groups');
            });

            BackendUserController::extendFormFields(function($form, $model, $context) {
                    $form-&gt;removeField('groups');
            });
    }</code></pre>
<p>Make sure to replace <code>acme/blog</code> with the name of your plugin.</p>
<p>Finally, create the file <code>partials/toolbar.users.htm</code> in your plugin's root directory, with the following code:</p>
<pre><code>&lt;div data-control="toolbar"&gt;
    &lt;a href="&lt;?= Backend::url('backend/users/create') ?&gt;" class="btn btn-primary oc-icon-plus"&gt;
        &lt;?= e(trans('backend::lang.user.new')) ?&gt;
    &lt;/a&gt;
    &lt;?php if ($this-&gt;user-&gt;isSuperUser()): ?&gt;
        &lt;a href="&lt;?= Backend::url('backend/userroles') ?&gt;" class="btn btn-default oc-icon-address-card"&gt;
            &lt;?= e(trans('backend::lang.user.role.list_title')) ?&gt;
        &lt;/a&gt;
    &lt;?php endif ?&gt;
&lt;/div&gt;</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Use media manager for blog post featured image</title>
      <link>https://octobertricks.com/tricks/use-media-manager-for-blog-post-featured-image</link>
      <description>By default, blog posts enable you to use a featured image, but only if you upload your image directly. If you're looking to use the Media Manager for your featured images, all it requires is making a small plugin.
Here,...</description>
      <content:encoded><![CDATA[<p>By default, blog posts enable you to use a featured image, but only if you upload your image directly. If you're looking to use the Media Manager for your featured images, all it requires is making a small plugin.</p>
<pre><code class="language-php">&lt;?php
namespace Acme\BlogBanner;
use System\Classes\PluginBase;
use Event;
/**
 * Class Plugin
 *
 * @package Acme\BlogBanner
 */
class Plugin extends PluginBase
{
    public $require = ['RainLab.Blog'];
    /**
     * @inheritdoc
     */
    public function pluginDetails(): array
    {
        return [
            'name'        =&gt; 'Blog Banner',
            'description' =&gt; 'A RainLab.Blog extension adding banner image via Media Manager to posts.',
            'author'      =&gt; 'Acme',
            'icon'        =&gt; 'icon-file-image-o',
        ];
    }
    public function register()
    {
        Event::listen('backend.form.extendFields', function (\Backend\Widgets\Form $formWidget) {
            if (!$formWidget-&gt;getController() instanceof \RainLab\Blog\Controllers\Posts) {
                return;
            }
            if (!$formWidget-&gt;model instanceof \RainLab\Blog\Models\Post) {
                return;
            }
            $formWidget-&gt;addSecondaryTabFields([
                'metadata[banner_image]' =&gt; [
                    'tab' =&gt; 'rainlab.blog::lang.post.tab_manage',
                    'label'   =&gt; 'Banner Image',
                    'type' =&gt; 'mediafinder',
                    'mode' =&gt; 'image'
                ],
            ]);
            $formWidget-&gt;removeField('featured_images');
        });
    }
}</code></pre>
<p>Here, we call it <code>banner_image</code> instead of <code>featured_image</code> to avoid any conflicts, but that's all you need to enable the Media Manger for blog posts.</p>
<p>To use the image in the CMS pages, just use:</p>
<pre><code class="language-twig">&lt;img src="{{ post.metadata.banner_image|media }}"&gt;</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Render an e-mail template in the browser</title>
      <link>https://octobertricks.com/tricks/render-an-e-mail-template-in-the-browser</link>
      <description>To preview an e-mail template directly in the browser, add a temporary route to your plugin's routes.php file:
Now visit http://yoursite.test/mail to preview the mail in your browser. Don't forget to remove this route once you are done!</description>
      <content:encoded><![CDATA[<p>To preview an e-mail template directly in the browser, add a temporary route to your plugin's <code>routes.php</code> file:</p>
<pre><code class="language-php">// plugins/yourvendor/yourplugin/routes.php

use System\Classes\MailManager;
use System\Models\MailLayout;
use System\Models\MailTemplate;

Route::get('/mail', function () {
    $data = [
        'your-dummy' =&gt; 'data',
    ];

    $layout = new MailLayout;
    $layout-&gt;fillFromCode('default'); // Change this to use another layout.

    $template = new MailTemplate;
    $template-&gt;layout = $layout;
    $template-&gt;fillFromContent(File::get(base_path('plugins/path/to/your/views/template.htm')));

    return MailManager::instance()-&gt;renderTemplate($template, $data);
});</code></pre>
<p>Now visit <code>http://yoursite.test/mail</code> to preview the mail in your browser. Don't forget to remove this route once you are done!</p>]]></content:encoded>
    </item>
    <item>
      <title>Customize the pagination markup</title>
      <link>https://octobertricks.com/tricks/customize-pagination-markup</link>
      <description>Given you have a Paginator instance stored in a $results variable:
You can output the default pagination markup using the | raw filter:
If you need to customize the markup of the pagination you'll have to generate it yourself:</description>
      <content:encoded><![CDATA[<p>Given you have a <code>Paginator</code> instance stored in a <code>$results</code> variable:</p>
<pre><code class="language-php">$this['results'] = YourModel::paginate(10);</code></pre>
<p>You can output the default pagination markup using the <code>| raw</code> filter:</p>
<pre><code class="language-twig">{{ results | raw }}</code></pre>
<p>If you need to customize the markup of the pagination you'll have to generate it yourself:</p>
<pre><code class="language-twig">{% if results.hasPages %}
    &lt;ul class="pagination"&gt;
        &lt;li&gt;
            {% if results.currentPage &gt; 1 %}
                &lt;a href="{{ results.previousPageUrl }}" rel="prev"&gt;«&lt;/a&gt;
            {% else %}
                &lt;span class="disabled"&gt;«&lt;/span&gt;
            {% endif %}
        &lt;/li&gt;

        {% for page in range(1, results.lastPage) %}
            &lt;li&gt;
                &lt;a href="{{ results.url(page) }}"&gt;{{ page }}&lt;/a&gt;
            &lt;/li&gt;
        {% endfor %}

        &lt;li&gt;
            {% if results.hasMorePages %}
                &lt;a href="{{ results.nextPageUrl }}" rel="next"&gt;»&lt;/a&gt;
            {% else %}
                &lt;span class="disabled"&gt;»&lt;/span&gt;
            {% endif %}
        &lt;/li&gt;
    &lt;/ul&gt;
{% endif %}</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Customise AJAX Loading Stripe</title>
      <link>https://octobertricks.com/tricks/customise-ajax-loading-stripe</link>
      <description>October's AJAX framework implements a blue stripe at the top of your site, showing the progress of requests.
Frequently, this blue clashes with your site's color scheme, and thus is problematic. Thankfully, there is a simple CSS fix:
You are...</description>
      <content:encoded><![CDATA[<p>October's AJAX framework implements a blue stripe at the top of your site, showing the progress of requests.</p>
<p>Frequently, this blue clashes with your site's color scheme, and thus is problematic. Thankfully, there is a simple CSS fix:</p>
<pre><code>.stripe-loading-indicator .stripe,
.stripe-loading-indicator .stripe-loaded {
    background: red !important;        
}</code></pre>
<p>You are also able to change the height of the stripe as well, if you wish:</p>
<pre><code>height: 8px !important;</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Add models to a RainLab.Sitemap or RainLab.Pages menu</title>
      <link>https://octobertricks.com/tricks/add-models-rainlabsitemap-or-rainlabpages-menu</link>
      <description>To add all entries of a specific model to a RainLab.Sitemap or RainLab.Pages menu do the following:
In your Plugin.php add the following three event listeners. Replace the your-items key with a more descriptive string.
Then add the resolveMenuItem method...</description>
      <content:encoded><![CDATA[<p>To add all entries of a specific model to a <code>RainLab.Sitemap</code> or <code>RainLab.Pages</code> menu do the following:</p>
<p>In your <code>Plugin.php</code> add the following three event listeners. Replace the <code>your-items</code> key with a more descriptive string.</p>
<pre><code class="language-php">public function boot()
{
    \Event::listen('pages.menuitem.listTypes', function () {
        return [
            'your-items' =&gt; 'Name of the items',
        ];
    });

    \Event::listen('pages.menuitem.getTypeInfo', function ($type) {
        if ($type === 'your-items') {
            $theme = \Cms\Classes\Theme::getActiveTheme();
            $pages = \Cms\Classes\Page::listInTheme($theme, true);
            return [
                'dynamicItems' =&gt; true,
                'cmsPages' =&gt; $pages,
            ];
        }
    });

    \Event::listen('pages.menuitem.resolveItem', function ($type, $item, $url, $theme) {
        if ($type === 'your-items') {
            return YourModel::resolveMenuItem($item, $url, $theme);
        }
    });
}</code></pre>
<p>Then add the <code>resolveMenuItem</code> method to your Model. The method has to return an array of all the items you want to add. The example code below fetches all models from the database and generates the link using a specific cms page.</p>
<pre><code class="language-php">public static function resolveMenuItem($item, $url, $theme)
{
    $pageName = $item-&gt;cmsPage;
    $cmsPage = \Cms\Classes\Page::loadCached($theme, $pageName);
    $items   = self
        ::orderBy('created_at', 'DESC')
        -&gt;get()
        -&gt;map(function (self $item) use ($cmsPage, $url, $pageName) {
            $pageUrl = $cmsPage-&gt;url($pageName, ['slug' =&gt; $item-&gt;slug]);

            return [
                'title'    =&gt; $item-&gt;name,
                'url'      =&gt; $pageUrl,
                'mtime'    =&gt; $item-&gt;updated_at,
                'isActive' =&gt; $pageUrl === $url,
            ];
        })
        -&gt;toArray();

    return [
        'items' =&gt; $items,
    ];
}</code></pre>
<p>You will now find your new menu items type in the respective editors of <code>RainLab.Sitemap</code> and <code>RainLab.Pages</code>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Access images from a media folder in the frontend</title>
      <link>https://octobertricks.com/tricks/access-images-media-folder-frontend</link>
      <description>Method1: Use the storage_path helper and the File::files method to list the images in a path.
Method2: Use the Storage::files method to list the images in a path.
Note: Method1 returns an array of Symfony\Component\Finder\SplFileInfo objects which give much more...</description>
      <content:encoded><![CDATA[<p>Method1: Use the <code>storage_path</code> helper and the <code>File::files</code> method to list the images in a path.</p>
<pre><code class="language-php">==
function onInit()
{
   $dir = storage_path('app/media/your-folder');
   $this['files'] = File::files($dir);
}
==
&lt;ul&gt;
    {% for file in files %}
       &lt;li&gt;{{ file }}&lt;/li&gt;
    {% endfor %}
&lt;/ul&gt;</code></pre>
<p>Method2: Use the <code>Storage::files</code> method to list the images in a path.</p>
<pre><code class="language-php">==
function onInit()
{
   $dir = 'media/your-folder';
   $this['files'] = Storage::files($dir);
}
==
&lt;ul&gt;
    {% for file in files %}
       &lt;li&gt;{{ file }}&lt;/li&gt;
    {% endfor %}
&lt;/ul&gt;
</code></pre>
<p>Note: Method1 returns an array of <code>Symfony\Component\Finder\SplFileInfo</code> objects which give much more information about the files (size, perms, owner, etc).</p>]]></content:encoded>
    </item>
    <item>
      <title>Access URL parameters in a cms page or partial</title>
      <link>https://octobertricks.com/tricks/access-url-parameters-cms-page-or-partial</link>
      <description/>
      <content:encoded><![CDATA[<p>There are multiple ways to access URL parameters in a cms page or partial. This trick shows you how you can access the different parts of an example URL <code>http://example.com/detail/a-custom-model-slug?page=1</code>.</p>
<pre><code class="language-php">
url = "/detail/:slug"
==
function onStart()
{
  // The following URL is given
  // http://example.com/detail/a-custom-model-slug?page=1

  $this['pageNum'] = request()-&gt;get('page');
  // or
  // $this['pageNum'] = \Request::get('page');

  $this['slug'] = $this-&gt;param('slug');
}
==
Slug is {{ slug }}, page is {{ pageNum }}.</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Using OctoberCMS without the CMS Module</title>
      <link>https://octobertricks.com/tricks/using-octobercms-without-the-cms-module</link>
      <description>If you are familiar with October's architecture, you know that the application comes with 3 "modules": Backend, System, and CMS. What each of these provides is fairly easy to understand based on the name alone: the Backend module handles the...</description>
      <content:encoded><![CDATA[<p>If you are familiar with October's architecture, you know that the application comes with 3 "modules": Backend, System, and CMS. What each of these provides is fairly easy to understand based on the name alone: the Backend module handles the admin area, the System module provides essential functionality to the other modules, and the CMS module handles the frontend, public facing website.</p>
<p>What if you are only interested in using the Backend of OctoberCMS, without the CMS module or a theme? This trick will help you remove the CMS module from your application.</p>
<ol>
<li>Update <code>config/cms.php</code>:</li>
<li>Remove the <code>activeTheme</code> value</li>
<li>Remove <code>Cms</code> from the <code>loadModules</code> array</li>
<li>Optionally, you may remove the 'backendUri' value if you want your application accessible from the root domain. i.e. <a href="https://www.myapp.com">https://www.myapp.com</a> vs <a href="https://www.myapp.com/backend">https://www.myapp.com/backend</a></li>
</ol>
<p>And that's all there is to it! You now have a fully functional backend application using OctoberCMS!</p>
<blockquote>
<p>If you are using composer, you can also remove the cms package from your composer.json. Please note this can lead to problems if any of your plugins register components, or references classes found in the CMS module, such as the Page class. Proceed with caution!</p>
</blockquote>]]></content:encoded>
    </item>
    <item>
      <title>How to set default values for backend form fields</title>
      <link>https://octobertricks.com/tricks/how-set-default-values-form-fields</link>
      <description>In your controller, use the formExtendModel method to set the model's properites:</description>
      <content:encoded><![CDATA[<p>In your controller, use the <code>formExtendModel</code> method to set the model's properites:</p>
<pre><code class="language-php">    public function formExtendModel($model)
    {
        if ($this-&gt;formGetContext() === 'create') {
            $model-&gt;your_field = 'Your default value';
        }
    }</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Use the original filename as thumbnail name</title>
      <link>https://octobertricks.com/tricks/use-original-filename-thumbnail-name</link>
      <description>If you want to replace the generated thumb_6_800_0_0_0_auto.jpg filenames with more SEO-friendly variants like the-original-file-name_6_800_0_0_0_auto.jpg then follow the steps below:
Add the following class to your plugin:
Now simply use this model instead of System\Models\File when you define attachMany or...</description>
      <content:encoded><![CDATA[<p>If you want to replace the generated <code>thumb_6_800_0_0_0_auto.jpg</code> filenames with more SEO-friendly variants like <code>the-original-file-name_6_800_0_0_0_auto.jpg</code> then follow the steps below:</p>
<p>Add the following class to your plugin:</p>
<pre><code>&lt;?php namespace YourVendor\YourPlugin\Models;

/**
 * Custom thumbnail name attachment.
 *
 * @see https://octobertricks.com/tricks/use-original-filename-thumbnail-name
 */
class File extends \System\Models\File
{
    /**
     * Generates a thumbnail filename using the original filename.
     * @return string
     */
    public function getThumbFilename($width, $height, $options)
    {
        $original = parent::getThumbFilename($width, $height, $options);

        $newName = str_slug(pathinfo($this-&gt;file_name, PATHINFO_FILENAME));

        return str_replace('thumb_', $newName . '_', $original);
    }

    /**
     * Generates a disk name from the supplied file name. 
     */
    protected function getDiskName()
    {
        $ext  = strtolower($this-&gt;getExtension());
        $name = str_slug(pathinfo($this-&gt;file_name, PATHINFO_FILENAME));

        // A filename has to be at least 9 characters long.
        if (strlen($name) &lt; 9) {
            $name .= str_random(9 - strlen($name));
        }

        return implode('.', array_filter([$name, $ext]));
    }
}</code></pre>
<p>Now simply use this model instead of <code>System\Models\File</code> when you define <code>attachMany</code> or <code>attachOne</code> relationship.</p>
<pre><code>&lt;?php namespace YourVendor\YourPlugin\Models;

class Event extends Model
{
    public $attachOne = [
        'image' =&gt; \YourVendor\YourPlugin\Models\File::class,
    ];
}</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Register custom side navigation for your plugin</title>
      <link>https://octobertricks.com/tricks/register-custom-side-navigation-for-your-plugin</link>
      <description>The NavigationManager (available through the BackendMenu facade) has the ability to register a special menu called contextSideNav. This allows you to create custom side menus for your plugins, such as the one used in the System Settings page. This trick...</description>
      <content:encoded><![CDATA[<p>The <code>NavigationManager</code> (available through the <code>BackendMenu</code> facade) has the ability to register a special menu called <code>contextSideNav</code>. This allows you to create custom side menus for your plugins, such as the one used in the System Settings page. This trick will help you re-create the setting style sidenav for your plugin.</p>
<h2>Part 1 - Create sidenav partials</h2>
<p>Create a new folder in your plugin directory called <code>partials</code></p>
<p>Create a new file in the <code>partials</code> directory called <code>_sidenav.htm</code> with the contents below:</p>
<pre><code>&lt;!-- Main sidenav menu wrapper --&gt;
&lt;div style="background: steelblue;" class="layout-cell sidenav-tree" 
data-control="sidenav-tree" data-search-input="#settings-search-input"&gt;
 &lt;div class="layout"&gt;
     &lt;div class="layout-row min-size"&gt;
         &lt;?= $this-&gt;makePartial('$/author/plugin/partials/_sidenav_search_toolbar.htm') ?&gt;
     &lt;/div&gt;
     &lt;div class="layout-row"&gt;
         &lt;div class="layout-cell"&gt;
             &lt;div class="layout-relative"&gt;
                 &lt;div class="layout-absolute"&gt;
                     &lt;div class="control-scrollbar" data-control="scrollbar"&gt;
                         &lt;?= $this-&gt;makePartial('$/author/plugin/partials/_sidenav_menu.htm') ?&gt;
                     &lt;/div&gt;
                 &lt;/div&gt;
             &lt;/div&gt;
         &lt;/div&gt;
     &lt;/div&gt;
 &lt;/div&gt;
&lt;/div&gt;</code></pre>
<p>Create a new file in the <code>partials</code> directory called <code>_sidenav_search_toolbar.htm</code> with the contents below:</p>
<pre><code>&lt;!-- Search form on top of sidenav --&gt;
&lt;div class="layout control-toolbar"&gt;
    &lt;div class="layout-cell"&gt;
        &lt;div class="relative toolbar-item loading-indicator-container size-input-text"&gt;
            &lt;input placeholder="&lt;?= e(trans('system::lang.settings.search')) ?&gt;" type="text" name="search" value="" 
                class="form-control icon search"
                id="settings-search-input"
                autocomplete="off"
                data-track-input
                data-load-indicator
                data-load-indicator-opaque
            /&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;</code></pre>
<p>Create a new file in the <code>partials</code> directory called <code>_sidenav_menu.htm</code> with the contents below:</p>
<pre><code class="language-php">&lt;!-- Sidebar menu --&gt;
&lt;?php
$sideMenuItems = BackendMenu::listSideMenuItems();
if ($sideMenuItems):
    $collapsedGroups = explode('|',
isset($_COOKIE['sidenav_treegroupStatus']) ? $_COOKIE['sidenav_treegroupStatus'] : null);
$categories = [];
foreach ($sideMenuItems as $sideItemCode =&gt; $item){
    if(!property_exists($item, 'group'))
        $item-&gt;group = 'default';
    if(!property_exists($item, 'keywords'))
        $item-&gt;keywords = '';
    if(!property_exists($item, 'description'))
        $item-&gt;description = '';
    $categories[$item-&gt;group][$sideItemCode] = $item;
}
?&gt;        
&lt;ul class="top-level"&gt;
&lt;?php foreach ($categories as $category =&gt; $items):
        $collapsed = in_array($category, $collapsedGroups);
?&gt;
    &lt;li data-group-code="&lt;?= e($category) ?&gt;"
        &lt;?= $collapsed ? 'data-status="collapsed"' : null ?&gt;
    &gt;
        &lt;div class="group"&gt;
            &lt;h3&gt;&lt;?= e(trans($category)) ?&gt;&lt;/h3&gt;
        &lt;/div&gt;
        &lt;ul&gt;
        &lt;?php foreach ($items as $item): ?&gt;
            &lt;li class="&lt;?= BackendMenu::isSideMenuItemActive($item) ? 'active' : null ?&gt;"
                data-keywords="&lt;?= e(trans($item-&gt;keywords)) ?&gt;"&gt;
                &lt;a href="&lt;?= $item-&gt;url ?&gt;"&gt;
                    &lt;i class="sidebar-menu-item &lt;?= $item-&gt;icon ?&gt;"&gt;&lt;/i&gt;
                    &lt;span class="header"&gt;&lt;?= e(trans($item-&gt;label)) ?&gt;&lt;/span&gt;
                    &lt;span class="description"&gt;&lt;?= e(trans($item-&gt;description)) ?&gt;&lt;/span&gt;
                &lt;/a&gt;
            &lt;/li&gt;
        &lt;?php endforeach ?&gt;
        &lt;/ul&gt;
    &lt;/li&gt;
&lt;?php endforeach ?&gt;
&lt;/ul&gt;
&lt;?php endif; ?&gt;</code></pre>
<h2>Part 2 - Registering the contextSidenavPartial</h2>
<p>Add this code to your <code>Plugin.php</code> file:</p>
<pre><code class="language-php">use BackendMenu;

public function register()
{
    BackendMenu::registerContextSidenavPartial('Author.PluginName', 'owner', '$/author/plugin/partials/_sidenav.htm');        
}</code></pre>
<p>That's all there is to it. Note we have re-created the settings style menu here, but you would be free to use any style you wish.</p>]]></content:encoded>
    </item>
    <item>
      <title>Create Cms Page from PHP code</title>
      <link>https://octobertricks.com/tricks/create-cms-page-with-translation-from-php-code</link>
      <description>Use this code to programatically create a CMS Page with URL/Title translations:
(Note: to be used with Rainlab.Translate plugin)
Use this code to programatically create a CMS Page and attach a component:</description>
      <content:encoded><![CDATA[<p>Use this code to programatically create a CMS Page with URL/Title translations:</p>
<pre><code>    $page = new \Cms\Classes\Page([
        'fileName' =&gt; 'test-page',
        'title' =&gt; 'My Page Title',
        'url' =&gt; '/test-page',
        'layout' =&gt; 'default',
    ]);

    $page-&gt;attributes['viewBag'] = [
            'localeUrl' =&gt; [
                    'fr' =&gt; '/french-URL',
                    'de' =&gt; '/deutch-URL',
            ],
            'localeTitle' =&gt; [
                    'fr' =&gt; 'French Title',
                    'de' =&gt; 'Deutch Title',
            ],
    ];

    $page-&gt;save();</code></pre>
<p>(Note: to be used with <code>Rainlab.Translate</code> plugin)</p>
<p>Use this code to programatically create a CMS Page and attach a component:</p>
<pre><code>    $page = new \Cms\Classes\Page([
        'fileName' =&gt; 'test-page',
        'title' =&gt; 'My Page Title',
        'url' =&gt; '/test-page',
        'layout' =&gt; 'default',
    ]);

    $page-&gt;attributes['myComponent'] = [];

    $page-&gt;save();</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Allow additional filetypes for uploads</title>
      <link>https://octobertricks.com/tricks/allow-additional-filetypes-uploads</link>
      <description>Image uploads
October uses a config array to check for allowed image extensions. This list is
defined in \October\Rain\Filesystem\Definitions::imageExtensions().
To add your own extensions to the list you have to copy the default values to file_definitions.image_extensions in your config/cms.php file....</description>
      <content:encoded><![CDATA[<h2>Image uploads</h2>
<p>October uses a config array to check for allowed image extensions. This list is
defined in <code>\October\Rain\Filesystem\Definitions::imageExtensions()</code>.</p>
<p>To add your own extensions to the list you have to copy the default values to <code>file_definitions.image_extensions</code> in your <code>config/cms.php</code> file.</p>
<p>Note: If you use a upload widget in the <code>file</code> mode make sure to add your extension to the <code>default_extensions</code> key as described in the next section.</p>
<pre><code class="language-php">    // add in config/cms.php
    // ...
    'file_definitions' =&gt; [
        'image_extensions' =&gt; [
            // your new custom extensions
            'svg',
            // defaults
            'jpg',
            'jpeg',
            'bmp',
            'png',
            'webp',
            'gif',
        ]
    ]</code></pre>
<h2>General file uploads</h2>
<p>October uses a config array to check for allowed upload extensions. This list is
defined in <code>\October\Rain\Filesystem\Definitions::defaultExtensions()</code>.</p>
<p>To add your own extensions to the list you have to copy the default values to <code>file_definitions.default_extensions</code> in your <code>config/cms.php</code> file.</p>
<p>If you use a upload widget in the <code>image</code> mode make sure to add your extension to the <code>image_extensions</code> key as described in the section above.</p>
<pre><code class="language-php">    // add in config/cms.php
    // ...
    'file_definitions' =&gt; [
        'default_extensions' =&gt; [
            // your new custom extensions
            'json',
            // defaults
            'jpg',
            'jpeg',
            'bmp',
            'png',
            'webp',
            'gif',
            'svg',
            'js',
            'map',
            'ico',
            'css',
            'less',
            'scss',
            'ics',
            'odt',
            'doc',
            'docx',
            'ppt',
            'pptx',
            'pdf',
            'swf',
            'txt',
            'xml',
            'ods',
            'xls',
            'xlsx',
            'eot',
            'woff',
            'woff2',
            'ttf',
            'flv',
            'wmv',
            'mp3',
            'ogg',
            'wav',
            'avi',
            'mov',
            'mp4',
            'mpeg',
            'webm',
            'mkv',
            'rar',
            'xml',
            'zip',
        ]
    ]</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Display model data on a cms page</title>
      <link>https://octobertricks.com/tricks/display-model-data-cms-page</link>
      <description>There are many ways to display a model's data on a cms page. This trick describes two:
Via page execution lifecycle
Via a custom component
Register your custom component in your Plugin.php.
Create the blogDetail component as components/BlogDetail.php
Finally, place...</description>
      <content:encoded><![CDATA[<p>There are many ways to display a model's data on a cms page. This trick describes two:</p>
<h3>Via page execution lifecycle</h3>
<pre><code class="language-twig">url = "/blog/:slug"
==
use Acme\Blog\Models\Post;

function onStart()
{
  $this['post'] = Post::where('slug', $this-&gt;param('slug'))-&gt;first();
}
==
&lt;h2&gt;{{ post.title }}&lt;/h2&gt;

&lt;div&gt;{{ post.content }}&lt;/div&gt;
</code></pre>
<h3>Via a custom component</h3>
<p>Register your custom component in your Plugin.php.</p>
<pre><code class="language-php">// Plugin.php
public function registerComponents()
{
    return [
        Acme\Blog\Components\BlogDetail::class =&gt; 'blogDetail',
    ];
}</code></pre>
<p>Create the <code>blogDetail</code> component as <code>components/BlogDetail.php</code></p>
<pre><code class="language-php">namespace Acme\Blog\Components;

use Cms\Classes\ComponentBase;

class BlogDetail extends ComponentBase
{
    public $blog;

    public function defineProperties()
    {
        return [
            'slug' =&gt; [
                'type'  =&gt; 'string',
                'title' =&gt; 'Slug',
            ]
        ];
    }

    public function onRun()
    {
        $this-&gt;blog = $this-&gt;page['blog'] = Post::where('slug', $this-&gt;property('slug'))-&gt;first();
    }
}</code></pre>
<p>Finally, place the component on your CMS page.</p>
<pre><code class="language-twig">url = "/blog/:slug"

[blogDetail]
slug = "{{ :slug }}"
==

&lt;h2&gt;{{ blogDetail.post.title }}&lt;/h2&gt;

&lt;div&gt;{{ blogDetail.post.content }}&lt;/div&gt;

{#  Since we set $this-&gt;page['blog'] the post is also available
    via the {{ post }} variable directly.

    @see https://octobertricks.com/tricks/access-component-properties-page-or-partial
#}
</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Add a custom button to a relation manager</title>
      <link>https://octobertricks.com/tricks/add-a-custom-button-to-a-relation-manager</link>
      <description>Sometimes you may want to add a custom button to a relation widget to execute a custom action or extend the function of the default buttons. You can easily do this by specifying a custom key in the toolbarButtons option...</description>
      <content:encoded><![CDATA[<p>Sometimes you may want to add a custom button to a relation widget to execute a custom action or extend the function of the default buttons. You can easily do this by specifying a custom key in the <code>toolbarButtons</code> option of your <code>config_relation.yaml</code>:</p>
<pre><code class="language-yaml"># ===================================
#  Relation Behavior Config
# ===================================

items:
    label: Invoice Line Item
    view:
        list: $/acme/pay/models/invoiceitem/columns.yaml
        toolbarButtons: create|delete|custom # Add this
    manage:
        form: $/acme/pay/models/invoiceitem/fields.yaml
        recordsPerPage: 10</code></pre>
<p>Next, create a new file <code>_relation_button_custom.htm</code> (the last part corresponds to the item in your configuration file) in your controller's partial directory (e. g. <code>/plugins/acme/controllers/invoices/</code>) with the following contents:</p>
<pre><code>&lt;button
        class="btn btn-sm btn-secondary"
        data-request="onDoSomething"
        data-stripe-load-indicator&gt;
    Custom
&lt;/button&gt;</code></pre>
<p>In this case, the button will just call the handler <code>onDoSomething</code> of your controller. But you can also go more advanced and pass the selected (checked) items or any custom variables to the controller. You can even open a custom modal and render complex controls. A lot of the markup can be reused from the <a href="https://github.com/octobercms/october/tree/master/modules/backend/behaviors/relationcontroller/partials">existing button partials</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Update a single field from a FormController AJAX method</title>
      <link>https://octobertricks.com/tricks/update-single-field-in-formcontroller-using-ajax</link>
      <description>When using an AJAX handler in your FormController, you can update a single field in your form using this:
If you need to replace the field container, set useContainer =&gt; false. If you need to keep the container, set useContainer...</description>
      <content:encoded><![CDATA[<p>When using an AJAX handler in your FormController, you can update a single field in your form using this:</p>
<pre><code>public function onYourAjaxHandler($recordID)
{
   $model = MyModel::findOrFail($recordID);
   $model-&gt;fieldToUpdate = "new value";
   $this-&gt;initForm($model);

   $fieldMarkup = $this-&gt;formGetWidget()-&gt;renderField('fieldToUpdate', ['useContainer' =&gt; true]);

   return [
      '#field-id' =&gt; $fieldMarkup
   ];
}</code></pre>
<p>If you need to <em>replace</em> the field container, set <code>useContainer =&gt; false</code>. If you need to <em>keep</em> the container, set <code>useContainer =&gt; true</code>.</p>
<p>Since v452 of OctoberCMS, it is now possible to use the formRenderField() method directly as the "options" argument has been added to it:</p>
<pre><code>   $this-&gt;formRenderField('fieldToUpdate', ['useContainer'=&gt;false]);</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Override a controller's view file locally in your plugin</title>
      <link>https://octobertricks.com/tricks/override-a-controllers-view-file-locally-in-your-plugin</link>
      <description>Let's say you want to override a controller's view file (e.g. the Rainlab.Blog Posts controller):

copy the original view file into your plugin partials directory, under the posts folder.
modify the copied file to your liking
add the following code...</description>
      <content:encoded><![CDATA[<p>Let's say you want to override a controller's <em>view</em> file (e.g. the <code>Rainlab.Blog</code> Posts controller):</p>
<ul>
<li>copy the original view file into your plugin <code>partials</code> directory, under the <code>posts</code> folder.</li>
<li>modify the copied file to your liking</li>
<li>add the following code to the boot method of your Plugin registration file:</li>
</ul>
<pre><code class="language-php">use Rainlab\Blog\Controllers\Posts;

public function boot()
{
    Posts::extend(function($controller) {
        list($author, $plugin) = explode('\\', strtolower(get_class()));
        $partials_path = sprintf('$/%s/%s/partials/posts', $author, $plugin);
        $controller-&gt;addViewPath($partials_path);
    });
}</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Hide/show relation manager buttons</title>
      <link>https://octobertricks.com/tricks/hideshow-relation-manager-buttons</link>
      <description>Would you prefer to hide the various buttons for your relation manager views? For example, unlink/delete buttons are visible, but disabled, unless you select a record. 
If you want to override this behavior, create a partials with the name _relation_button_action.htm...</description>
      <content:encoded><![CDATA[<p>Would you prefer to hide the various buttons for your relation manager views? For example, unlink/delete buttons are visible, but disabled, unless you select a record. </p>
<p>If you want to override this behavior, create a partials with the name <code>_relation_button_action.htm</code> inside your controllers folder (i.e. Author\Plugin\Controllers\Controller), where <code>_action</code> equals the button you want to override. For example, if you wanted to override the <code>delete</code> button you would create <code>authour/plugin/controllers/controller/_relation_button_delete.htm</code>. The code for the partial can be copied from <code>modules/backend/behaviors/relationcontroller/_button_action.htm</code> or completely customized at this point.</p>
<p>The key lines determining the buttons behavior are:</p>
<pre><code>disabled="disabled"
data-trigger-action="enable"
data-trigger="#&lt;?= $this-&gt;relationGetId('view') ?&gt; .control-list input[type=checkbox]"
data-trigger-condition="checked"</code></pre>
<p>We will go over each of these lines below:</p>
<ol>
<li><code>disabled="disabled"</code> This should be self explanatory, but this line disables the button. We will remove this line because we want our button enabled, but hidden when a record(s) is selected.</li>
<li><code>data-trigger-action="enable"</code> This line tells the framework what to do with this element. In this case, it will enable the field. We want to change this line to <code>data-trigger-action="show"</code>.</li>
<li><code>data-trigger="#&lt;?= $this-&gt;relationGetId('view') ?&gt; .control-list input[type=checkbox]"</code> This line targets the checkboxes in the list view. Do not modify this line.</li>
<li><code>data-trigger-condition="checked"</code> This line tells the framework what condition to look for. Do not change this line.</li>
</ol>
<p>Your final button partial should look something like this:</p>
<pre><code>&lt;button
        class="btn btn-sm btn-secondary oc-icon-random"
        onclick="$(this).data('request-data', {
            checked: $('#&lt;?= $this-&gt;relationGetId('view') ?&gt; .control-list').listWidget('getChecked')
        })"
        data-handler="onRelationButtonMove"
        data-control="popup"
        data-size="large"
        data-request-success="$.oc.relationBehavior.changed('&lt;?= e($this-&gt;vars['relationField']) ?&gt;', 'moved')"
        data-trigger-action="show"
        data-trigger="#&lt;?= $this-&gt;relationGetId('view') ?&gt; .control-list input[type=checkbox]"
        data-trigger-condition="checked"
        data-stripe-load-indicator&gt;
        Move user(s)
&lt;/button&gt;</code></pre>
<p><strong>Note:</strong>  This functionality is not explicity documented. However, you should be able to infer this from looking at the Backend Form Trigger Event Docs.</p>]]></content:encoded>
    </item>
    <item>
      <title>Deploy with backend brand settings</title>
      <link>https://octobertricks.com/tricks/deploy-with-backend-brand-settings</link>
      <description>This trick will allow you to deploy your site with backend brand settings already configured (and its pretty easy too)!
When deploying your site, the backend brand will be set to October defaults which requires a login to the backend...</description>
      <content:encoded><![CDATA[<p>This trick will allow you to deploy your site with backend brand settings already configured (and its pretty easy too)!</p>
<p>When deploying your site, the backend brand will be set to October defaults which requires a login to the backend to update things like the logo, tag line and colors.</p>
<ol>
<li>Create a new file in your app's config directory: <code>config/brand.php</code></li>
<li>Paste the block of code below into your <code>brand.php</code> file: </li>
</ol>
<pre><code>&lt;?php

return [

    /*
    |--------------------------------------------------------------------------
    | Specify the default backend brand settings
    |--------------------------------------------------------------------------
    |
    | These parameter values can be overridden by the backend Brand settings
    |
    */

    'logoPath' =&gt; '$/author/plugin/assets/images/logo.png',
    'faviconPath' =&gt; '$/author/plugin/assets/images/favicon.ico',
    'appName' =&gt; 'APP NAME',
    'tagline' =&gt; 'APP TAGLINE',
    'primaryColor' =&gt; "#b4b4b4",
    'secondaryColor' =&gt; "#ffcc00",
    'accentColor' =&gt; "#B4B4B4",
    'menuMode' =&gt; 'inline', // options: inline, inline_no_icons, tile, collapse
    'customLessPath' =&gt; '$/author/plugin/assets/styles/backend.less',
];</code></pre>
<ol start="3">
<li>Update the values relative to your application. Note the image paths must be relative to your filesystem and not a URL.</li>
</ol>
<p>I want to thank <a href="https://github.com/luketowers">@LukeTowers</a> for pointing this functionality out to me.</p>]]></content:encoded>
    </item>
    <item>
      <title>How to add a canonical link to your layout in twig</title>
      <link>https://octobertricks.com/tricks/add-a-canonical-link-to-your-layout-in-twig</link>
      <description>Add this to the  section of your layout:
or</description>
      <content:encoded><![CDATA[<p>Add this to the  section of your layout:</p>
<pre><code>&lt;link rel="canonical" href="{{ url_current() | lower }}" /&gt;</code></pre>
<p>or</p>
<pre><code>&lt;link rel="canonical" href="{{ this.page.id | page }}" /&gt;</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Use an AJAX request handler on a backend settings form</title>
      <link>https://octobertricks.com/tricks/use-ajax-request-handler-backend-settings-form</link>
      <description>A backend settings form usually only has a form model, but no separate controller available. If you want to register a custom AJAX request handler you have to add it to the \System\Controllers\Settings controller. October re-uses this controller for all...</description>
      <content:encoded><![CDATA[<p>A backend settings form usually only has a form model, but no separate controller available. If you want to register a custom AJAX request handler you have to add it to the <code>\System\Controllers\Settings</code> controller. October re-uses this controller for all backend settings pages. </p>
<p>You can use the <code>extend()</code> method to add a custom handler:</p>
<pre><code class="language-php">    // Plugin.php
    public function boot()
    {
        \System\Controllers\Settings::extend(function($controller) {
            $controller-&gt;addDynamicMethod('onMyCustomHandler', function() {
                return 'handler called!';
            });
        });
    }</code></pre>
<p>You can now call this handler from any custom partial in your backend settings form:</p>
<pre><code class="language-html">&lt;button class="btn btn-default"
        data-handler="onMyCustomHandler"&gt;
    Trigger AJAX request
&lt;/button&gt;</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Filter `jsonable` fields using Eloquent</title>
      <link>https://octobertricks.com/tricks/filter-jsonable-fields-using-eloquent</link>
      <description>Fields that are declared as jsonable are stored as JSON string in a single database column.
If you declare this column as JSON type in your database you can use Laravel's JSON where clauses to query the structured data.
You...</description>
      <content:encoded><![CDATA[<p>Fields that are declared as <code>jsonable</code> are stored as JSON string in a single database column.</p>
<p>If you declare this column as <code>JSON</code> type in your database you can use Laravel's <a href="https://laravel.com/docs/5.5/queries#json-where-clauses">JSON where clauses</a> to query the structured data.</p>
<p>You need to be using a database that supports JSON columns (MySQL 5.7+ or MariaDB 10.2+).</p>
<pre><code class="language-php">// In your migration
Schema::create('your_table', function (Blueprint $table) {
    $table-&gt;increments('id');
    $table-&gt;json('jsonable_field'); // Declare as JSON
    // ...
});</code></pre>
<p>Basic queries are supported on Laravel 5.5.</p>
<pre><code class="language-php">$users = DB::table('users')
           -&gt;where('preferences-&gt;dining-&gt;meal', 'salad')
           -&gt;get();</code></pre>
<p>If you need advanced JSON features you have to fall back to raw queries.</p>
<pre><code class="language-php">// Filter data like {"subkey": [10]}
$users = DB::table('users')
           -&gt;whereRaw('JSON_EXTRACT(array_of_values, ?) &gt;= ?', ['$."subkey"[0]'])
           -&gt;get();

// Order by JSON value like {"value_name": "abc"}
$users = DB::table('users')
           -&gt;orderByRaw('JSON_EXTRACT(field_name, ?) ASC', ['$."value_name"'])
           -&gt;get();</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Generate a page URL in a specific locale</title>
      <link>https://octobertricks.com/tricks/generate-page-url-specific-locale</link>
      <description>Use the rewriteTranslatablePageUrl method to get a page URL in a specific locale. </description>
      <content:encoded><![CDATA[<p>Use the <code>rewriteTranslatablePageUrl</code> method to get a page URL in a specific locale. </p>
<pre><code class="language-php">$locale = 'de';
$pageName = 'target-cms-page';
// If your model slug is translatable use
// $params = ['slug' =&gt; $model-&gt;locale($locale)-&gt;slug];
$params = ['slug' =&gt; 'your-model-slug'];

$theme = Theme::getActiveThemeCode();
$cmsPage = Page::loadCached($theme, $pageName);

$cmsPage-&gt;rewriteTranslatablePageUrl($locale);

$router = new \October\Rain\Router\Router;
$localeUrl = $router-&gt;urlFromPattern($cmsPage-&gt;url, $params);
// If you need the locale prefix use 
// $localeUrl = $router-&gt;urlFromPattern(sprintf("/%s%s", $locale, $page-&gt;url), $params);

echo url($localeUrl);</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Compare dates in Twig</title>
      <link>https://octobertricks.com/tricks/compare-dates-twig</link>
      <description>In Twig you can use "now" | date to get the current date. Format "now" and your date as unix-timestamp. You can then rely on number comparision to compare dates this way:
A nicer solution to this problem is to...</description>
      <content:encoded><![CDATA[<p>In Twig you can use <code>"now" | date</code> to get the current date. Format "now" and your date as unix-timestamp. You can then rely on number comparision to compare dates this way:</p>
<pre><code class="language-twig">{% if record.end_date|date('U') &gt; 'now'|date('U') %}</code></pre>
<p>A nicer solution to this problem is to add a <code>getIsPastAttribute</code> method to your model and do the comparision there. This way you can use <code>record.is_past</code> in twig.</p>
<pre><code class="language-php">
class Record extends Model
{
    public function getIsPastAttribute()
    {
        return $this-&gt;end_date-&gt;lt(now());
    }
}</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Set the default value of a datepicker form widget to the current time</title>
      <link>https://octobertricks.com/tricks/set-default-value-datepicker-form-widget-current-time</link>
      <description>If you've got a datepicker form widget and want to preset it to the current date and time simply pass now as value to the default property.</description>
      <content:encoded><![CDATA[<p>If you've got a <code>datepicker</code> form widget and want to preset it to the current date and time simply pass <code>now</code> as value to the <code>default</code> property.</p>
<pre><code class="language-yaml">    published_at:
        label: 'Published at'
        mode: datetime
        type: datepicker
        default: now</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Use a rich editor form widget as the Rainlab.Blog post editor</title>
      <link>https://octobertricks.com/tricks/force-richeditor-in-rainlabblog-plugin-post-editor</link>
      <description>Use the following Event listener to force the RainLab.Blog plugin to always use a richeditor form widget.</description>
      <content:encoded><![CDATA[<p>Use the following Event listener to force the RainLab.Blog plugin to always use a <code>richeditor</code> form widget.</p>
<pre><code class="language-php">Event::listen('backend.form.extendFieldsBefore', function($widget) {
    // Extend only the Blog\Posts controller &amp; Extend only Blog\Post model
    if (!($widget-&gt;getController() instanceof \RainLab\Blog\Controllers\Posts
        &amp;&amp; $widget-&gt;model instanceof \RainLab\Blog\Models\Post)
    ){
        return;
    }

    $widget-&gt;secondaryTabs['fields']['content']['type'] = 'richeditor';
});</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Dynamic robots.txt</title>
      <link>https://octobertricks.com/tricks/dynamic-robotstxt</link>
      <description>This will allow to create dynamic robot.txt file with TWIG.
This is our robotstxt CMS page with twig variables:</description>
      <content:encoded><![CDATA[<p>This will allow to create dynamic robot.txt file with TWIG.</p>
<p>This is our robotstxt CMS page with twig variables:</p>
<pre><code>title = "robots"
url = "/robots"
is_hidden = 0
==
&lt;?php
function onStart()
{
    $this-&gt;setResponseHeader('Content-Type', 'text/plain');
}
==
Modified: 9-27-2019
User-agent: *
Allow: /
Disallow: /api/*
Disallow: /payment/*

{% set baseUrl = url('/') %}
Disallow: {{ 'myCustomPage'|page(false)|replace({ (baseUrl): '' }) }}

Sitemap: {{ url('/') }}/sitemap.xml</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Make plugin translation keys available as theme messages for RainLab.Translate</title>
      <link>https://octobertricks.com/tricks/make-plugin-translation-keys-available-as-theme-messages-for-rainlabtranslate</link>
      <description>See https://wintertricks.com/tricks/make-plugin-translation-keys-available-theme-messages-wintertranslate</description>
      <content:encoded><![CDATA[<p>See <a href="https://wintertricks.com/tricks/make-plugin-translation-keys-available-theme-messages-wintertranslate">https://wintertricks.com/tricks/make-plugin-translation-keys-available-theme-messages-wintertranslate</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Updating Report Widget partials with AJAX</title>
      <link>https://octobertricks.com/tricks/updating-report-widget-partials-with-ajax</link>
      <description>October provides a robust and feature rich dashboard system that allows users to add any number of widgets. These widgets are useful for displaying high level metrics, such as page views, access logs, etc. 
You may find the need to...</description>
      <content:encoded><![CDATA[<p>October provides a robust and feature rich dashboard system that allows users to add any number of widgets. These widgets are useful for displaying high level metrics, such as page views, access logs, etc. </p>
<p>You may find the need to update this content dynamically, based upon some action the user could make within the report widget. October's AJAX framework makes this relatively easy, so long as you know what to return from your AJAX handler. </p>
<p>This trick will provide an example of how to update your report widget partial using October's AJAX framework.</p>
<blockquote>
<p>Note: This trick assumes you have already created your report widget class and have a partial that needs to be updated. If you need help creating a report widget, please see the documentation <a href="https://octobercms.com/docs/backend/widgets#report-widgets">Report Widgets</a>. </p>
</blockquote>
<ol>
<li>Add a element to your partial to make the AJAX request. Here is an example:
<pre><code>&lt;button
data-request="onUpdateWidget"&gt;
Update
&lt;/button&gt;</code></pre></li>
<li>Add a new method to your report widget class <code>public function onUpdateWidget()</code>. For example:
<pre><code>public function onUpdateWidget()
{
return [
    '#'.$this-&gt;alias =&gt; $this-&gt;render()
    ];
}</code></pre></li>
</ol>
<blockquote>
<p>The secret sauce here is the widget's <code>alias</code> property, which determines which widget is actually being updated. Your widget should already have a <code>render()</code> method which returns the contents of the widget partial. </p>
</blockquote>
<p>Now, when you click the button in your report widget, the AJAX framework will make a request and call the handler <code>onUpdateWidget</code>. In this example, we have re-rendered the widget itself so any changes to data will be displayed. </p>
<p>We are free to return any content we wish, even other partials, or static content. The possibilities are limitless!</p>]]></content:encoded>
    </item>
    <item>
      <title>Clean HTML Pasted into Froala</title>
      <link>https://octobertricks.com/tricks/clean-html-pasted-into-froala</link>
      <description>Then include via:</description>
      <content:encoded><![CDATA[<pre><code class="language-js">/**
 * Froala - Clean HTML Plugin.
 */
+function ($) {
    $.FroalaEditor.PLUGINS.cleanHtml = function (editor) {
        function _init() {
            editor.events.on('paste.beforeCleanup', function (clipboardHtml) {
                return _convertHtmlToPlainText(clipboardHtml);
            });
        }
        function _convertHtmlToPlainText(clipboardHtml) {
            return '&lt;p&gt;' + clipboardHtml.replace(/&lt;br&gt;/gi, "\n").replace(/&lt;(?:.|\s)*?&gt;/g, '') + '&lt;/p&gt;';
        }
        return {
            _init: _init
        };
    };
}(jQuery);</code></pre>
<p>Then include via:</p>
<pre><code class="language-php">/**
 * Extend Rich Editor.
 */
\Backend\FormWidgets\RichEditor::extend(function ($widget) {
    $widget-&gt;addJs('/plugins/author/name/assets/js/froala.clean-html.js', 'Author.Name');
});</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Access current Eloquent model in a backend form</title>
      <link>https://octobertricks.com/tricks/get-attributes-and-functions-loaded-model-backend-form</link>
      <description>Sometimes you need to access attributes or methods of the current model in a backend form (let's say in a custom partial). You can access the model via the vars property:
Of course you have also access to all the...</description>
      <content:encoded><![CDATA[<p>Sometimes you need to access attributes or methods of the current model in a backend form (let's say in a custom partial). You can access the model via the <code>vars</code> property:</p>
<pre><code class="language-php">$this-&gt;vars['formModel'];</code></pre>
<p>Of course you have also access to all the model's properties and methods:</p>
<pre><code class="language-php">$this-&gt;vars['formModel']-&gt;id;
$this-&gt;vars['formModel']-&gt;title;
$this-&gt;vars['formModel']-&gt;customMethod();</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Return a file download from an AJAX handler</title>
      <link>https://octobertricks.com/tricks/return-a-file-download-from-an-ajax-handler</link>
      <description>Currently it is not possible to return a download response from an AJAX handler. You have to use a dedicated route or page that returns the response instead.
You can redirect to this page from any AJAX handler and the...</description>
      <content:encoded><![CDATA[<p>Currently it is not possible to return a download response from an AJAX handler. You have to use a dedicated route or page that returns the response instead.</p>
<pre><code class="language-php">title = "Download"
url = "/trigger-download"
is_hidden = 0
==
function onStart()
{
    $pathToFile = storage_path('your-file.pdf');
    $fileName = 'download.pdf';
    $headers = [
        'Content-Type' =&gt; 'application/pdf'
    ];

    return Response::download($pathToFile, $fileName, $headers);
}
==</code></pre>
<p>You can redirect to this page from any AJAX handler and the browser will start a file download.</p>
<pre><code class="language-php">
function onDownloadHandler()
{
    return Redirect::to('trigger-download');
}</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Add a backend page to view your plugin settings</title>
      <link>https://octobertricks.com/tricks/add-backend-page-to-view-update-your-plugin-settings</link>
      <description>Plugin's settings registration:
Plugin's navigation registration:
Controller definition:</description>
      <content:encoded><![CDATA[<p>Plugin's settings registration:</p>
<pre><code class="language-php">    public function registerSettings()
    {   
        return [
            'settings' =&gt; [
                'label'       =&gt; 'Test Settings',
                'description' =&gt; 'Test settings descr',
                'class'       =&gt; 'AuthorName\PluginName\Models\Settings',
              ],
        ];
    }</code></pre>
<p>Plugin's navigation registration:</p>
<pre><code class="language-php">    public function registerNavigation()
    {   
        return [
            'main-menu' =&gt; [
                'label'       =&gt; 'Test Menu',
                'url'         =&gt; Backend::url('AuthorName/PluginName/test'),

                'sideMenu' =&gt; [
                    'side-menu-item' =&gt; [
                        'label' =&gt; 'Settings',
                        'url' =&gt; Backend::url('AuthorName/PluginName/settings'),
                    ],
                ],
            ],
        ];
    }</code></pre>
<p>Controller definition:</p>
<pre><code class="language-php">&lt;?php namespace AuthorName\PluginName\Controllers;

use BackendMenu;
use Redirect;
use Request;        

class Settings extends \System\Controllers\Settings
{                       
    protected $author;
    protected $plugin;
    protected $code = 'settings'; // see registerSettings()
    protected $mainMenuId = 'main-menu'; // see registerNavigation()
    protected $sideMenuId = 'side-menu-item'; // see registerNavigation()

    public function __construct()
    {   
        parent::__construct();
        $this-&gt;viewPath = base_path().'/modules/system/controllers/settings';

        // Extract Author and Plugin name from current class path
        list($this-&gt;author, $this-&gt;plugin) = explode('\\', get_class());

        BackendMenu::setContext(sprintf('%s.%s', $this-&gt;author, $this-&gt;plugin), $this-&gt;mainMenuId, $this-&gt;sideMenuId);
    }

    public function index()
    {   
        $url = sprintf('%s/update/%s/%s/%s', Request::url(), $this-&gt;author, $this-&gt;plugin, $this-&gt;code);

        return Redirect::to($url);
    }
}</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Bidirectional Belongs To Many Relationship</title>
      <link>https://octobertricks.com/tricks/bidirectional-belongs-to-many-relationship</link>
      <description>Usage from Plugin.php boot method:</description>
      <content:encoded><![CDATA[<pre><code class="language-php">&lt;?php

namespace ThePottingShed\Relationships\Classes;

/**
 * Bidirectional Belongs To Many Relationship.
 */
class BidirectionalBelongsToManyRelationship
{
    /**
     * Attach.
     *
     * @param  October\Rain\Database\Model $model
     * @param  integer $insertedData
     * @param  string  $relationName
     * @param  string  $keyName
     * @param  string  $otherKeyName
     *
     * @return void
     */
    public static function attach($model, $insertedData, $relationName, $keyName, $otherKeyName)
    {
        if (!empty($insertedData)) {
            $record      = $insertedData[0];
            $key         = $record[$keyName];
            $otherKey    = $record[$otherKeyName];
            $otherRecord = $model::find($otherKey);
            $otherRecord-&gt;{$relationName}()-&gt;syncWithoutDetaching($key);
        }
    }

    /**
     * Detach.
     *
     * @param  October\Rain\Database\Model $model
     * @param  integer $attachedIdList
     * @param  string $relationName
     *
     * @return void
     */
    public static function detach($model, $attachedIdList, $relationName)
    {
        if (!empty($attachedIdList)) {
            $key = $model-&gt;id;
            foreach ($attachedIdList as $otherKey) {
                $otherRecord = $model::find($otherKey);
                $otherKeys   = collect($otherRecord-&gt;{$relationName}-&gt;lists('id'))-&gt;reject(function ($otherKey) use ($key) {
                    return $otherKey === $key;
                });
                $otherRecord-&gt;{$relationName}()-&gt;sync($otherKeys);
            }
        }
    }
}</code></pre>
<p>Usage from <strong>Plugin.php</strong> <code>boot</code> method:</p>
<pre><code class="language-php">/**
 * Boot.
 *
 * @return void
 */
public function boot()
{
    \RainLab\Blog\Models\Post::extend(function ($model) {
        $model-&gt;belongsToMany += [
            'related_blog_posts' =&gt; [
                'RainLab\Blog\Models\Post',
                'table'    =&gt; 'tps_blog_posts_blog_posts',
                'key'      =&gt; 'bp_id',
                'otherKey' =&gt; 'rbp_id',
                'order'    =&gt; 'title',
                'scope'    =&gt; 'isPublished',
            ],
        ];
        $model-&gt;bindEvent('model.relation.afterAttach', function ($relationName, $attachedIdList, $insertData) use ($model) {
            if ($relationName === 'related_blog_posts') {
                BidirectionalBelongsToManyRelationship::attach($model, $insertData, $relationName, $keyName = 'bp_id', $otherKeyName = 'rbp_id');
            }
        });
        $model-&gt;bindEvent('model.relation.afterDetach', function ($relationName, $attachedIdList) use ($model) {
            if ($relationName === 'related_blog_posts') {
                BidirectionalBelongsToManyRelationship::detach($model, $attachedIdList, $relationName);
            }
        });
    });
}</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Using UUID for Models</title>
      <link>https://octobertricks.com/tricks/using-uuid-for-models</link>
      <description>Using UUIDs in your database tables is easier than it seems. Here are the steps you should take to ensure that October CMS works properly with UUID columns.
Migrations
The schema builder comes with a handy uuid table column that...</description>
      <content:encoded><![CDATA[<p>Using UUIDs in your database tables is easier than it seems. Here are the steps you should take to ensure that October CMS works properly with UUID columns.</p>
<h2>Migrations</h2>
<p>The schema builder comes with a handy <code>uuid</code> table column that we can use to place our UUIDs. You'll also need to append <code>primary()</code> to ensure that the UUID becomes the primary key.</p>
<pre><code class="language-php">// updates/create_table.php
Schema::create('my_database_table', function (Blueprint $table) {
    $table-&gt;uuid('id')-&gt;primary();
});</code></pre>
<h2>Models</h2>
<p>In your models, set the <code>$incrementing</code> variable to <code>false</code> to ensure that the Model does not increment the value of the UUID.</p>
<p>Finally, automatically generating a UUID will require the <code>Ramsey\Uuid\Uuid</code>. We'll be using this library because it already comes installed with Laravel, so there's no need to install any other UUID generator. Next, add the <code>beforeCreate()</code> event method into your Model. The code to generate the UUID is:</p>
<pre><code class="language-php">use Ramsey\Uuid\Uuid;

class Test extends Model
{
    public $incrementing = false;

    public function beforeCreate()
    {
        $this-&gt;id = Uuid::uuid4()-&gt;toString();
    }
}</code></pre>
<p>You can learn more about the UUID library on <a href="https://github.com/ramsey/uuid">GitHub</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Display a relation count in a List via columns.yaml</title>
      <link>https://octobertricks.com/tricks/display-relation-count-list-columnsyaml</link>
      <description>Given you have a model that uses a count property on a relationship to get only the related model count:
To display this count value in a List, use the useRelationCount option in your columns.yaml. Using the usual select: count...</description>
      <content:encoded><![CDATA[<p>Given you have a model that uses a <code>count</code> property on a relationship to get only the related model count:</p>
<pre><code class="language-php">    public $hasOne = [
        'comments_count' =&gt; [Comment::class, 'count' =&gt; true],
    ];</code></pre>
<p>To display this count value in a List, use the <code>useRelationCount</code> option in your <code>columns.yaml</code>. Using the usual <code>select: count</code> method would result in a <code>Unknown column 'count' in 'field list'</code> error.</p>
<pre><code class="language-yaml">    comments_count:
        label: Number of related comments
        type: number
        relation: comments_count
        useRelationCount: true             # this is important</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Add a category filter to a backend list</title>
      <link>https://octobertricks.com/tricks/add-category-filter-backend-list</link>
      <description>In your plugin directory create the following file:
Paste your filter configuration in it:
Enable the filter by adding the following line to your config_list.yaml.</description>
      <content:encoded><![CDATA[<p>In your plugin directory create the following file:</p>
<pre><code>controllers/yourcontroller/config_filter.yaml</code></pre>
<p>Paste your filter configuration in it:</p>
<pre><code class="language-yaml">scopes:
    category:
        label: Category
        modelClass: Acme\Blog\Models\Category
        conditions: category_id in (:filtered)
        nameFrom: name</code></pre>
<p>Enable the filter by adding the following line to your <code>config_list.yaml</code>.</p>
<pre><code class="language-yaml">filter: config_filter.yaml</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Include jQuery in your project</title>
      <link>https://octobertricks.com/tricks/include-jquery-your-project</link>
      <description>You can include the same jQuery version October ships in your theme by using the @jquery alias.
By passing it as an array to the | theme filter you'll get a new filename as soon as the content of the...</description>
      <content:encoded><![CDATA[<p>You can include the same jQuery version October ships in your theme by using the <code>@jquery</code> alias.</p>
<pre><code class="language-twig">&lt;script src="{{ ['@jquery'] | theme }}"&gt;&lt;/script&gt;</code></pre>
<p>By passing it as an array to the <code>| theme</code> filter you'll get a new filename as soon as the content of the jQuery file changes. This makes sure that users will download the new version and not use a cached one.</p>
<p>You can also add additional files to the array to combine all of them into a single output file.</p>
<pre><code class="language-twig">&lt;script src="{{ ['@jquery', 'assets/another.js'] | theme }}"&gt;&lt;/script&gt;</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Add group filter and custom options to a backend list</title>
      <link>https://octobertricks.com/tricks/add-group-filter-and-custom-options-to-a-backend-list</link>
      <description>Given this table:
| title  | genre     |
| -------| --------- |
| Book 1 | Academia  |
| Book 2 | Biography |
| Book 3 | Children  |
| Book 4 | Fiction   |
| Book 5 |...</description>
      <content:encoded><![CDATA[<p>Given this table:</p>
<pre><code>| title  | genre     |
| -------| --------- |
| Book 1 | Academia  |
| Book 2 | Biography |
| Book 3 | Children  |
| Book 4 | Fiction   |
| Book 5 | Biography |</code></pre>
<p>In your plugin  directory create the following file:</p>
<pre><code>controllers/yourcontroller/config_filter.yaml</code></pre>
<p>inside <code>config_filter.yaml</code></p>
<pre><code>scopes:
    genre:
        label: Filter Genres
        modelClass: Path\To\Models\Model
        type: group
        conditions: genre in (:filtered)
        options: listGenres</code></pre>
<p>on your model create a method <code>listGenres</code></p>
<pre><code>    public function listGenres()
    {
        // you can use distinct or groupBy
        return Model::groupBy-&gt;('genre')-&gt;pluck('genre', 'genre')-&gt;toArray();
    }</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Re-use and migrate WordPress password hashes in October</title>
      <link>https://octobertricks.com/tricks/re-use-and-migrate-wordpress-password-hashes-in-october</link>
      <description>This trick describes how you can migrate existing WordPress users to October. It allows a user to log in to the October backend with the same password that was used on WordPress. It will migrate the password to a proper...</description>
      <content:encoded><![CDATA[<p>This trick describes how you can migrate existing WordPress users to October. It allows a user to log in to the October backend with the same password that was used on WordPress. It will migrate the password to a proper bcrypt hash during the first login.</p>
<h2>Step 1: Import user data</h2>
<p>Migrate all WordPress password hashes (<code>ẁp_users.user_pass</code>) into the <code>backend_users</code> table. I won't describe in detail how you do this (for example by using <a href="https://github.com/corcel/corcel">Corcel</a>). Just make sure that the <code>wp_users.user_pass</code> column ends up in a new <code>backend_users.wp_password_hash</code> column that you have added manually (or via a proper plugin migration).</p>
<p>The <code>backend_users</code> table should look like this (some columns omitted):</p>
<table>

<tr>
<th>id</th>
<th>login</th>
<th>password</th>
<th>wp_password_hash</th>
</tr>

<tbody>
<tr>
<td>1</td>
<td>admin</td>
<td>null or random string</td>
<td>$1$fDzVfXkk$XY7EKilSen7g8xtVFwyjD.</td>
</tr>
<tr>
<td>2</td>
<td>otheruser</td>
<td>null or random string</td>
<td>$1$Z9NUyZha$OO3qctee2.bZqfnEK3g5J1</td>
</tr>
</tbody>
</table>
<h2>Step 2: Install mikemclin/laravel-wp-password</h2>
<p>To check a plain text password against a stored WordPress password hash, we can use the <a href="https://github.com/mikemclin/laravel-wp-password/tree/master"><code>mikemclin/laravel-wp-password</code></a> composer package. </p>
<p>Install it by running <code>composer require "mikemclin/laravel-wp-password" "~2.0.1"</code>.</p>
<p>Make sure to run this command from your October root directory, not a plugin's subdirectory. Otherwise you will end up with mixed versions of various <code>Illuminate/*</code> packages.</p>
<p>If you need to add the dependency to a specific plugin make sure it's included in the plugin's <code>composer.json</code> but always run <code>composer install</code> in the root directory.</p>
<h2>Step 3: Extend the AuthManager</h2>
<p>To extend the default <code>AuthManager</code> class that October uses during the login process, add the following code to a Plugin's <code>Plugin.php</code> file:</p>
<pre><code class="language-php">use YourVendor\YourPlugin\Classes\AuthManager;

class Plugin extends PluginBase
{
    public function register()
    {
        App::singleton('backend.auth', function () {
            // This overrides the default AuthManager instance with our own.
            return AuthManager::instance();
        });
    }
}</code></pre>
<h2>Step 4: Override AuthManager methods</h2>
<p>There are multiple ways to hook into October's <code>AuthManager</code>. For this use-case, it is enough to override the <code>findUserByCredentials</code> method in our custom <code>AuthManager</code> class. </p>
<p>Create the following class and save it to <code>plugins/your-vendor/your-plugin/classes/AuthManager.php</code></p>
<pre><code class="language-php">&lt;?php

namespace YourVendor\YourPlugin\Classes;

use Backend\Classes\AuthManager as BackendAuthManager;
use MikeMcLin\WpPassword\Facades\WpPassword;
use October\Rain\Auth\AuthException;

class AuthManager extends BackendAuthManager
{
    public function findUserByCredentials(array $credentials = [])
    {
        $originalException = null;
        try {
            // Try to log in using the base class' logic. If no exception is thrown,
            // the login worked with the provided credentials.
            // In these case there's nothing for us to do.
            return parent::findUserByCredentials($credentials);
        } catch (AuthException $e) {
            // Capture the thrown exception. We will re-throw it if we are unable
            // to re-hash the user's password.
            $originalException = $e;
        }

        // Find the user by the provided login attribute. 
        // Re-throw the original exception if no user is found.
        $user = $this-&gt;findUserByLogin($credentials['login']);
        if ( ! $user) {
            throw $originalException;
        }

        // Check if the user model contains an old wp_password_hash.
        // If not, we have nothing to check against and the login should 
        // fail with the original exception.
        if ( ! $oldHash = $user-&gt;wp_password_hash) {
            throw $originalException;
        }

        // Check if the provided password matches the stored WordPress hash
        // using WpPassword's check method.
        // If it does not match, abort by re-throwing the original exception.
        if ( ! WpPassword::check($credentials['password'], $user-&gt;wp_password_hash)) {
            throw $originalException;
        }

        // We have found a user where the WordPress hash matched. Let's re-hash the password
        // to bcrypt by setting it on the model (as password and confirmation). 
        // Also remove the old WordPress hash to make sure it is gone for good.
        $user-&gt;password = $credentials['password'];
        $user-&gt;password_confirmation = $credentials['password'];
        $user-&gt;wp_password_hash = '';
        $user-&gt;save();

        // Return the updated user model. This makes sure the usual 
        // login logic is executed.
        return $user;
    }
}</code></pre>
<h2>Step 5: Test the new AuthManager logic</h2>
<p>To test the new AuthManager logic, empty the <code>password</code> column of a user in the <code>backends_user</code> table. Add a WordPress password hash to the <code>wp_password_hash</code> column. You can generate a hash for a specific password using a <a href="http://www.passwordtool.hu/wordpress-password-hash-generator-v3-v4">WordPress Password Hash Generator</a>.</p>
<p>If you log in now, you should notice no changes to the usual login routine. If you check your database after the login the <code>wp_password_hash</code> column should be empty and the <code>password</code> column should contain a valid bcrypt hash. </p>
<p>Make sure to test that subsequent logins with the new hash work as expected.</p>]]></content:encoded>
    </item>
    <item>
      <title>Resize images in rich text html</title>
      <link>https://octobertricks.com/tricks/resize-images-in-rich-text-html</link>
      <description>Images that are inserted by users into rich text fields are not resized. This twig filter as part of a custom plugin does that and can be inserted before |content or |raw:
It can be used as follows: {{your_field|rich_resize|content}} or...</description>
      <content:encoded><![CDATA[<p>Images that are inserted by users into rich text fields are not resized. This twig filter as part of a custom plugin does that and can be inserted before |content or |raw:</p>
<pre><code class="language-php">&lt;?php namespace Minakari\Customisations;
use \System\Classes\ResizeImages;

class Plugin extends PluginBase
{
    public function boot()
    {
    }

    public function registerMarkupTags(): array
    {
        $filters = [
            'rich_resize' =&gt; [$this, 'richResize']
        ];
        $functions = [];

        return [
            'filters' =&gt; $filters,
            'functions' =&gt; $functions,
        ];
    }

    public function richResize($html)
    {
        // Use DOMDocument to parse the HTML and find all image tags
        $dom = new \DOMDocument();
        @$dom-&gt;loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));

        $images = $dom-&gt;getElementsByTagName('img');

        foreach ($images as $image) {
            $src = $image-&gt;getAttribute('src');

            // Resize the image using the ResizeImages::resize() interface
            $resizedSrc = ResizeImages::resize($src, 1328, null, ['mode' =&gt; 'auto', 'quality' =&gt; '40', 'compress' =&gt; true]);

            // Replace the original src with the resized src
            $image-&gt;setAttribute('src', $resizedSrc);
        }

        // Return the modified HTML
        return $dom-&gt;saveHTML();
    }
}</code></pre>
<p>It can be used as follows: <code>{{your_field|rich_resize|content}}</code> or `{{your_field|rich_resize|raw}}</p>]]></content:encoded>
    </item>
  </channel>
  <channel>
    <title>October Trick of the day</title>
    <link>https://octobertricks.com</link>
    <description>octobertrickscom Trick of the day</description>
    <atom:link href="" rel="self" type="application/rss+xml"/>
    <item>
      <title>Make session available in middleware</title>
      <link>https://octobertricks.com/tricks/make-session-available-in-middleware</link>
      <description>To make the session context available in a middleware, you have to push the middleware to the Router instead of the Kernel and add it to the web group.</description>
      <content:encoded><![CDATA[<p>To make the session context available in a middleware, you have to push the middleware to the Router instead of the Kernel and add it to the web group.</p>
<pre><code class="language-php">public function boot(): void
{
    /** @var \Illuminate\Routing\Router $router */
    $router = $this-&gt;app-&gt;make(\Illuminate\Routing\Router::class);
    $router-&gt;pushMiddlewareToGroup('web', YourMiddleware::class);
}</code></pre>]]></content:encoded>
    </item>
  </channel>
</rss>
