پلاگین کنسول–Hello World

مقدمه

برنامه‌های کنسول (Console Applications) از جوملا 4 معرفی شدند و روشی استراتژیک برای نوشتن برنامه‌های خط فرمان (CLI) در جوملا هستند. این برنامه‌ها اپلیکیشن‌های PHP هستند که از فریم‌ورک جوملا استفاده می‌کنند و از خط فرمان سروری که جوملا روی آن نصب است اجرا می‌شوند. بنابراین می‌توانید این برنامه‌ها را به صورت‌های زیر اجرا کنید:

- از طریق ترمینال روی خود سرور 

- از طریق کرون جاب (cron job) روی سرور 

- از طریق ترمینال ریموت (مثلاً با PuTTY)

جوملا خود چندین برنامه خط فرمان آماده دارد؛ پس می‌توانید در ترمینال به پوشه جوملای خود بروید و مثلا این دستور را اجرا کنید:

php cli/joomla.php user:list

که لیست کاربران سایت را نشان می‌دهد. (ممکن است نیاز باشد متغیر php خود را به مسیر صحیح php.exe تنظیم کنید.)

برای دیدن لیست برنامه‌های موجود دستور زیر را بزنید:

php cli/joomla.php

شما نیز می‌توانید برنامه خط فرمان خود را بنویسید و برنامه‌های موجود روی این مجموعه را گسترش دهید. برای این کار پلاگین کنسول می‌نویسید. در این بخش نحوه نوشتن یک برنامه ساده «hello world» آموزش داده شده، به طوری که بتوانید این دستور را اجرا کنید:

php cli/joomla.php hello:world

و متنی با عنوان «Hello World» در خروجی نمایش داده شود.

چه کاری باید انجام دهید؟

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

- یک کلاس (مثلا `ConsolePlugin`) که به جنبه‌های مکانیزم پلاگین جوملا رسیدگی می‌کند 

- یک کلاس (مثلا `Command`) که کد واقعی دستور را اجرا می‌کند

نحوه ارتباط این دو کلاس با کد جوملا به شکل نمودار توالی (Sequence Diagram) زیر است: 

نمودار نحوه ثبت  رویداد و اضافه  کردن فرمان به برنامه در پلاگین های جوملا

(در این نمودار نشان می‌دهد چگونه پلاگین، رویداد را ثبت کرده و فرمان را به برنامه اضافه می‌کند)

در این مثال، دو کلاس به شکل زیر نامیده می‌شوند:

- `HelloworldConsolePlugin` – برای رسیدگی به جنبه‌های پلاگین 

- `RunHelloCommand` – که متن «Hello World» را چاپ می‌کند و اطلاعات مربوط به فرمان را دارد.

کد پلاگین کنسول (Console Plugin)

تابع `getSubscribedEvents` که رویدادهای مورد نظر پلاگین را ثبت می‌کند:

 
public static function getSubscribedEvents(): array
{
    return [
        \Joomla\Application\ApplicationEvents::BEFORE_EXECUTE => 'registerCommands',
    ];
}

تابع `registerCommands` که فرمان را به اپلیکیشن جوملا اضافه می‌کند:

 
public function registerCommands(): void
{
    $app = Factory::getApplication();
    $app->addCommand(new RunHelloCommand());
}

متد `configure()` در کلاس فرمان (Command)

این متد مسئول تعریف توضیحات و راهنمای دستور است که در خط فرمان نمایش داده می‌شود:

 
protected function configure(): void
{
    $this->setDescription('This command prints hello world');
    $this->setHelp(
        <<<EOF
The <info>%command.name%</info> command prints hello world. To use enter:
<info>php %command.full_name%</info>
EOF
    );
}

نکات مهم درباره `configure()`

- با `setDescription` توضیح کوتاهی از عملکرد دستور تعریف می‌کنید که وقتی کاربر لیست دستورات را اجرا می‌کند نمایش داده شود:

php cli/joomla.php

- با `setHelp` متن راهنما را می‌دهید که وقتی کاربر به صورت زیر دستور را اجرا می‌کند نمایش داده می‌شود:

php cli/joomla.php hello:world -h

متغیرهای `%command.name%` و `%command.full_name%` در متن قابل استفاده هستند و نام دستور هم با تعریف زیر مشخص می‌گردد:

protected static $defaultName = 'hello:world';

این همچنین هر زمان که کاربر وارد شود نمایش داده می‌شود

php cli/joomla.php

اجرای دستور: متد `doExecute()`

در نهایت، وقتی دستور `RunHelloCommand` اجرا می‌شود، متد زیر فراخوانی می‌شود که خروجی «Hello World» را روی ترمینال چاپ می‌کند:

 
protected function doExecute(InputInterface $input, OutputInterface $output): int
{
    $symfonyStyle = new SymfonyStyle($input, $output);
    $symfonyStyle->text('Hello World');
    return 0;
}

در این کد:

- جوملا بسته `SymfonyStyle` را برای مدیریت ورودی و خروجی (I/O) به ترمینال بکار می‌گیرد که متد‌های راحت و متنوعی برای کار با ترمینال فراهم می‌کند.

- خروجی `"Hello World"` توسط تابع `text()` چاپ می‌شود.

- این تابع عدد خروجی (exit code) 0 را برمی‌گرداند که به معنای اجرای موفقیت‌آمیز دستور است. این کد توسط برنامه PHP جوملا دریافت شده و باعث تعیین وضعیت پایان اجرای برنامه می‌شود.

کد کامل پلاگین

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

فرض کنید فایل‌های پلاگین را در پوشه‌ای به نام `plg_helloworld_cli` قرار دهید.

نکته درباره هماهنگی کدها و زبان

- برای ساخت پلاگین بهتر است بین فایل‌های کد خود بعضی استانداردها را رعایت کنید 

- استفاده از فایل‌های زبان (Language Files) توصیه می‌شود که آن را مستقل از زبان کند 

- اما برای سادگی، مثال "Hello World" فقط از زبان انگلیسی پشتیبانی می‌کند.

فایل مانیفست پلاگین

`plg_helloworld_cli/helloworld.xml`

 
<?xml version="1.0" encoding="utf-8"?>
<extension type="plugin" group="console" method="upgrade">
    <name>Helloworld Console Application</name>
    <version>1.0.0</version>
    <creationDate>today</creationDate>
    <author>Me</author>
    <description>A basic Hello World console application</description>
    <namespace path="src">My\Plugin\Console\Helloworld</namespace>
    <files>
        <folder plugin="helloworld">services</folder>
        <folder>src</folder>
    </files>
</extension>

فایل Service Provider

در مسیر: 

`plg_helloworld_cli/services/provider.php`

این فایل تقریباً یک کد الگوی معمول است که تنها باید موارد مربوط به پلاگین خود را تنظیم کنید و همچنین آبجکت Application را به عنوان وابستگی دریافت می‌کند تا در پلاگین استفاده شود:

 
<?php
defined('_JEXEC') or die;

use Joomla\CMS\Extension\PluginInterface;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
use Joomla\Event\DispatcherInterface;
use Joomla\CMS\Factory;
use My\Plugin\Console\Helloworld\Extension\HelloworldConsolePlugin;

return new class implements ServiceProviderInterface
{
    /**
     * Registers the service provider with a DI container.
     *
     * @param   Container  $container  The DI container.
     *
     * @return  void
     *
     * @since   4.2.0
     */
    public function register(Container $container)
    {
        $container->set(
            PluginInterface::class,
            function (Container $container) {
                $dispatcher = $container->get(DispatcherInterface::class);
                $plugin     = new HelloworldConsolePlugin(
                    $dispatcher,
                    (array) PluginHelper::getPlugin('console', 'helloworld')
                );
                $plugin->setApplication(Factory::getApplication());

                return $plugin;
            }
        );
    }
};

 

فایل پلاگین کنسول

فایل زیر مسئول تعامل با فریمورک پلاگین جوملا است: 

`plg_helloworld_cli/src/Extension/HelloworldConsolePlugin.php`

 
<?php
namespace My\Plugin\Console\Helloworld\Extension;

\defined('_JEXEC') or die;

use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\Event\SubscriberInterface;
use Joomla\Application\ApplicationEvents;
use My\Plugin\Console\Helloworld\CliCommand\RunHelloCommand;

class HelloworldConsolePlugin extends CMSPlugin implements SubscriberInterface
{   
    // ثبت رویدادهایی که به آن‌ها گوش داده می‌شود
    public static function getSubscribedEvents(): array
    {
        return [
            \Joomla\Application\ApplicationEvents::BEFORE_EXECUTE => 'registerCommands',
        ];
    }

    // تابعی که فرمان‌ها را در اپ جوملا ثبت می‌کند
    public function registerCommands(): void
    {
        $app = $this->getApplication();
        $app->addCommand(new RunHelloCommand());
    }
}
 

فایل کلاس فرمان (Command)

این فایل مسئول اجرای دستور `hello:world` است: 

`plg_helloworld_cli/src/CliCommand/RunHelloCommand.php`

 
<?php
namespace My\Plugin\Console\Helloworld\CliCommand;

defined('_JEXEC') or die;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Joomla\Console\Command\AbstractCommand;

class RunHelloCommand extends AbstractCommand
{
    /**
     * نام پیش‌فرض دستور
     *
     * @var    string
     * @since  4.0.0
     */
    protected static $defaultName = 'hello:world';

    /**
     * تنظیمات دستور: توضیحات و راهنما
     *
     * @return  void
     * @since   4.0.0
     */
    protected function configure(): void
    {
        $this->setDescription('This command prints hello world');
        $this->setHelp(
            <<<EOF
The <info>%command.name%</info> command prints hello world. To use enter:
<info>php %command.full_name%</info>
EOF
        );
    }

    /**
     * اجرای دستور
     *
     * @param   InputInterface   $input   ورودی دستور
     * @param   OutputInterface  $output  خروجی دستور
     *
     * @return  integer  کد خروجی (0 به معنای موفقیت)
     * @since   4.0.0
     */
    protected function doExecute(InputInterface $input, OutputInterface $output): int
    {
        $symfonyStyle = new SymfonyStyle($input, $output);

        $symfonyStyle->text("Hello World");

        return 0;
    }
}

نصب پلاگین و استفاده

1. پوشه پلاگین `plg_helloworld_cli` را زیپ کنید و به روش معمول پلاگین‌ها را نصب کنید.

2. پس از نصب، حتما پلاگین را در بخش مدیریت جوملا فعال کنید.

3. در ترمینال (ssh یا command prompt) به شاخه اصلی نصب جوملا بروید و دستور زیر را اجرا کنید تا لیست دستورات موجود را ببینید:

php cli/joomla.php

در این لیست باید دستور `hello:world` را هم مشاهده کنید.

4. برای اجرای دستور کافیست بزنید:

php cli/joomla.php hello:world

در خروجی عبارت `"Hello World"` نمایش داده خواهد شد.

5. برای دیدن راهنمای دستور می‌توانید اجرا کنید:

php cli/joomla.php hello:world -h

نکته

ممکن است لازم باشد متغیر php را طوری تنظیم کنید که به فایل مناسب `php.exe` اشاره کند.