آموزش پلاگین

در این بخش، یک پلاگین ساده برای محتوای جوملا توسعه می‌دهیم که ویژگی‌ای مشابه شورت‌کدها (shortcodes) در وردپرس را فراهم می‌کند. با این پلاگین می‌توان در یک مقاله به فیلدی ارجاع داد:

 
On my Joomla instance {sitename} the default editor is {editor}.

این فیلدها به پارامترهای سراسری (تعریف‌شده در فایل configuration.php) محدود خواهند بود و پلاگین مقاله را طوری تغییر می‌دهد که مقداری که این پارامترها تنظیم شده‌اند، نمایش داده شود. به طوری که خروجی چیزی شبیه به این باشد:

 
On my Joomla instance j442 the default editor is tinymce.

علاوه بر این، پلاگین کاربرد موارد زیر را نیز نشان می‌دهد:

- استفاده از ثابت‌های زبان – هم در فایل مانیفست و هم در کد پلاگین

- بازگرداندن مقدار از یک متد پلاگین – از طریق رویداد onContentAfterTitle. پلاگین متن اضافه‌ای پس از عنوان مقاله اضافه می‌کند.

شما می‌توانید این پلاگین را روی نسخه‌های جوملا ۴ و ۵ تست کنید و تفاوت‌ها در نحوه دریافت پارامترها و بازگرداندن نتیجه را ببینید (مطابق توضیحات تغییرات جوملا ۴ و ۵).

این نمودار فایل‌های پلاگینی که باید نوشته شوند را نشان می‌دهد یا می‌توانید فایل زیپ پلاگین را از لینک دانلود دریافت کنید.( https://manual.joomla.org/assets/files/plg_shortcodes-6d54c8b47a9033ca7070c151260ebcc8.zip)

فایل مانیفست (Manifest File)

برای اطلاعات کلی درباره فایل‌های مانیفست، به بخش Manifest Files مراجعه کنید. 

مسیر: plg_shortcodes/shortcodes.xml

 
<?xml version="1.0" encoding="utf-8"?>
<extension method="upgrade" type="plugin" group="content">
    <name>PLG_CONTENT_SHORTCODES</name>
    <version>1.0</version>
    <description>PLG_CONTENT_SHORTCODES_DESCRIPTION</description>
    <author>Me</author>
    <creationDate>Today</creationDate>
    <copyright>(C) 2024 Open Source Matters, Inc.</copyright>
    <license>GNU General Public License version 2 or later</license>
    <namespace path="src">My\Plugin\Content\Shortcodes</namespace>
    <files>
        <folder plugin="shortcodes">services</folder>
        <folder>src</folder>
    </files>
    <languages>
        <language tag="en-GB">language/en-GB/plg_content_shortcodes.ini</language>
        <language tag="en-GB">language/en-GB/plg_content_shortcodes.sys.ini</language>
    </languages>
</extension>

جوملا در مورد فایل‌های مانیفست پلاگین بسیار دقیق است و به راحتی ممکن است اشتباهی رخ دهد که باعث شود پلاگین شما کار نکند. مواردی که باید درست انجام دهید عبارتند از:

نوع/گروه پلاگین 

 
<extension method="upgrade" type="plugin" group="content">
 

در بخش‌های قبلی انواع پلاگین‌ها مانند 'content'، 'system' و... توصیف شده بودند، اما در اینجا نوع(type) "plugin" است چون نوع پلاگین پلاگین است و گروه (group) به نوع پلاگین اشاره دارد.

ثابت‌های زبان 

 
<name>PLG_CONTENT_SHORTCODES</name>
<description>PLG_CONTENT_SHORTCODES_DESCRIPTION</description>

لازم نیست حتماً اینجا از رشته‌های زبان استفاده کنید، اما اگر استفاده می‌کنید باید مقادیر آن‌ها را در فایل language .sys.ini پلاگین خود ارائه دهید. (نام و توضیح در فرم مدیریت پلاگین‌ها نمایش داده می‌شود).

فضای نام (Namespacing) 

 
<namespace path="src">My\Plugin\Content\Shortcodes</namespace>

از نظر فنی لازم نیست دقیقاً ساختار پیشنهادی جوملا یعنی 

`Mycompany\Plugin\<plugin type>\<plugin name>` 

را رعایت کنید، اما باید اطمینان حاصل کنید که پیش‌وند فضای نام (namespace prefix) با موارد زیر مطابقت دارد:

- دستور `use` در فایل services/provider.php 

- بیانیه `namespace` در کلاس اصلی Extension

و همچنین همه کلاس‌های شما زیر پوشه /src باشند که در ویژگی path مشخص شده است.

اگر با مشکلات فضای نام مواجه شدید، بررسی فایل کش شده در مسیر `administrator/cache/autoload_psr4.php` مفید است تا مطمئن شوید پیش‌وند فضای نام پلاگین به مسیر درست اشاره می‌کند. این فایل کش هر بار که پلاگین‌ای نصب می‌کنید بازسازی می‌شود (به شرط فعال بودن پلاگین “Extension - Namespace Updater”). اگر تغییرات مستقیم در کد سایت جوملای خود ایجاد می‌کنید، ممکن است نیاز باشد این فایل کش را حذف کنید تا در مراجعه بعدی مجدداً ساخته شود.

نقطه ورود پلاگین (Plugin entry point) 

 
<files>
    <folder plugin="shortcodes">services</folder>
    <folder>src</folder>
</files>

اطمینان حاصل کنید که محل نقطه ورود پلاگین را با استفاده از `attribute`(ویژگی) plugin="shortcodes" روی پوشه مشخص کرده‌اید. این همچنین به فیلد element در فرم مدیریت پلاگین مرتبط می‌شود.

همچنین نام فایل مانیفست XML شما باید با این مقدار plugin مطابقت داشته باشد (مثلاً باید shortcodes.xml نامگذاری شود). در غیر این صورت جوملا پلاگین را نصب می‌کند اما namespace را درست نمی‌سازد.

فایل‌های زبان 

 
<languages>
    <language tag="en-GB">language/en-GB/plg_content_shortcodes.ini</language>
    <language tag="en-GB">language/en-GB/plg_content_shortcodes.sys.ini</language>
</languages>
 

اطمینان حاصل کنید که فایل‌های زبان پلاگین شما به درستی نامگذاری شده‌اند. در نام فایل باید موارد زیر حتما لحاظ شده باشند:

- نوع پلاگین — مطابق

 
attribute `<extension group="...">`

- عنصر پلاگین — مطابق

 
attribute `<folder plugin="...">`

فایل ارائه‌دهنده سرویس (Service Provider) 

مسیر: `plg_shortcodes/services/provider.php`

 
<?php
use Joomla\CMS\Extension\PluginInterface;
use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
use Joomla\Event\DispatcherInterface;
use My\Plugin\Content\Shortcodes\Extension\Shortcode;

return new class() implements ServiceProviderInterface
{
    public function register(Container $container)
    {
        $container->set(
            PluginInterface::class,
            function (Container $container) {

                $config = (array) PluginHelper::getPlugin('content', 'shortcodes');
                $subject = $container->get(DispatcherInterface::class);
                $app = Factory::getApplication();

                $plugin = new Shortcode($subject, $config);
                $plugin->setApplication($app);

                return $plugin;
            }
        );
    }
};
 

این کد قالب پایه (boilerplate) برای دریافت پلاگین شما از طریق کانتینر تزریق وابستگی (Dependency Injection Container) است. فقط باید سه خط زیر را متناسب با پلاگین خود تغییر دهید:

- `use My\Plugin\Content\Shortcodes\Extension\Shortcode; ` 

  مطمئن شوید این با <namespace> در فایل مانیفست، بیانیه فضای نام (namespace statement) و نام کلاس در فایل Extension شما همخوانی دارد.

- `$config = (array) PluginHelper::getPlugin('content', 'shortcodes');` 

  مطمئن شوید که نوع پلاگین و عنصر (element) پلاگین شما با مانیفست تطابق دارد.

- `$plugin = new Shortcode($subject, $config);` 

  اطمینان حاصل کنید که این با نام کلاس‌ شما در دایرکتوری `src/Extension` مطابقت دارد.

کلاس پلاگین (Extension Class)

کد اصلی پلاگین در فایل زیر قرار دارد و توضیحات داخل کد توضیح می‌دهد که چه کاری انجام می‌دهد.

مسیر: `plg_shortcodes/src/Extension/Shortcode.php`

 
<?php
namespace My\Plugin\Content\Shortcodes\Extension;

// بدون دسترسی مستقیم
defined('_JEXEC') or die;

use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\Event\Event;
use Joomla\Event\SubscriberInterface;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Event\Result\ResultAwareInterface;

class Shortcode extends CMSPlugin implements SubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
                'onContentPrepare' => 'replaceShortcodes',  
                'onContentAfterTitle' => 'addShortcodeSubtitle',  
        ];
    }

    // فراخوانی زمانی که رویداد onContentPrepare اجرا شود
    public function replaceShortcodes(Event $event)
    {
        /*
         * این تابع متن مقاله در حال نمایش را پردازش می‌کند.
         * هر متنی به صورت "{configname}" را با مقدار پارامتر متناظر جایگزین می‌کند.
         * مشابه قابلیت shortcodes در وردپرس است.
         */

        // محدود کردن به سایت (نه API)
        if (!$this->getApplication()->isClient('site')) {
            return;
        }
         
        // برای سازگاری با جوملا 4 و 5
        [$context, $article, $params, $page] = array_values($event->getArguments());
        if ($context !== "com_content.article" && $context !== "com_content.featured") return;
        
        $text = $article->text; 
        $config = Factory::getApplication()->getConfig()->toArray();

        $offset = 0;
        while (($start = strpos($text, "{", $offset)) !== false) {
            if ($end = strpos($text, "}", $start)) {
               $shortcode = substr($text, $start + 1, $end - $start - 1);
               
               $match_found = false;
               foreach ($config as $key => $value) {
                   if ($key === $shortcode) {
                       $text = substr_replace($text, htmlspecialchars($value), $start, $end - $start + 1);
                       $match_found = true;
                       break;
                   }
               } 
                
               if (!$match_found) {
                   $this->loadLanguage();
                   $text = substr_replace($text, Text::_('PLG_CONTENT_SHORTCODES_NO_MATCH'), $start, $end - $start + 1);
               }
                
            } else {
               break;
            }
           
           $offset = $end;
        }

        $article->text = $text;
    }
    
    public function addShortcodeSubtitle(Event $event)
    {
        if (!$this->getApplication()->isClient('site')) {
            return;
        }
        [$context, $article, $params, $page] = array_values($event->getArguments());
        if ($context !== "com_content.article" && $context !== "com_content.featured") return;
        
        $eventType = method_exists($event, 'getContext') ? "concrete event class" : "generic event class";
        
        if ($event instanceof ResultAwareInterface) {
            $event->addResult("{$eventType} via addResult");
        } else {
            $result = $event->getArgument('result') ?? [];
            $result[] = "{$eventType} via setArgument";
            $event->setArgument('result', $result);
        }
    }
}

فایل‌های زبان

ثابت‌های زبان استفاده شده در فایل مانیفست: 

`plg_shortcodes/language/en-GB/plg_content_shortcodes.sys.ini`

 
PLG_CONTENT_SHORTCODES="Shortcodes Plugin"
PLG_CONTENT_SHORTCODES_DESCRIPTION="Replaces article shortcodes (in {} brackets) with field values"

ثابت‌های زبان استفاده شده در کد پلاگین:

`plg_shortcodes/language/en-GB/plg_content_shortcodes.ini`

 
PLG_CONTENT_SHORTCODES_NO_MATCH="Error: no match for shortcode found"

نصب پلاگین

بعد از اینکه فایل‌ها را روی سیستم خود کپی کردید، کل پوشه را فشرده (zip) کرده و پلاگین را نصب کنید. فراموش نکنید پلاگین را فعال کنید!

یک مقاله بنویسید که شامل متنی مانند این باشد:

On my Joomla instance {sitename} the default editor is {editor}.

سپس به یک منوی سایت جوملا بروید که این مقاله را نمایش می‌دهد، چه به صورت مقاله تکی یا مقاله ویژه.

این کد باید هم در جوملا ۴ و هم ۵ کار کند و همچنین بعد از عنوان مقاله اطلاعاتی درباره نوع کلاس رویداد و نحوه بازگرداندن مقدار نمایش دهد.