プラグインは通常、Gravのコア機能に不足があるタスクがある場合に開発されます。
このチュートリアルでは、ボタンをクリックするとランダムなブログ記事を表示するプラグインを作成します。
同様の機能をもったプラグインは、Random という名前で存在しているので、このテストプラグインを Randomizer と呼ぶことにします。
この機能は標準では、すぐに使えませんが、プラグインを使えば簡単に提供できます。GRAV が、この機能を実現するための唯一の方法ではありません。多くの選択肢があります。ここでは、そのうちの1つを紹介します。
簡単そうでしょう?さっそくやってみましょう
このチュートリアルの以前のバージョンでは、プラグインを手動で作成する必要がありました。新しいDevToolsプラグインのおかげで、このプロセス全体を省略することができます。
新しいプラグインを作成する最初のステップは、DevTools Plugin のインストールです。これには2つの方法があります。
コマンドラインで Grav インストールのルートに移動します。
bin/gpm installdevtools
ログイン後、サイドバーから「プラグイン」セクションに移動するだけです。
右上の [+追加] ボタンをクリックします。リストの中から DevTools
を探し、 [インストールボタン] をクリックします。
この次のステップでは、コマンドラインを使用する必要があります。DevToolsには、新しいプラグイン作成をより簡単にする CLI コマンドがいくつか用意されています。
Gravのインストールルートから以下のコマンドを入力します。
bin/plugin devtools new-plugin
実行すると、新しいプラグインを作成するために必要な質問が表示されます。
bin/plugin devtools new-plugin
Enter Plugin Name: Randomizer
Enter Plugin Description: Sends the user to a random page
Enter Developer Name: Acme Corp
Enter Developer Email: contact@acme.co
SUCCESS plugin Randomizer -> Created Successfully
Path: /www/user/plugins/randomizer
Make sure to run `composer update` to initialize the autoloader
この時点で、新しく作成したプラグインフォルダ内のcomposer updateを 実行する必要があります。
DevTools コマンドは、この新しいプラグインがどこに作成されたかを教えてくれます。この作成されたプラグインは完全に機能しますが、望む機能を実行するロジックまで自動的に持っているわけではありませんので、ニーズに合わせて変更する必要があります。
修正と開発が可能な新しいプラグインが出来上がっています。プラグインを構成するものを分解して見てみます。user/plugins/randomizer
フォルダを見ると、以下のようなものがあります。
.
├── CHANGELOG.md
├── LICENSE
├── README.md
├── blueprints.yaml
├── randomizer.php
└── randomizer.yaml
これはサンプル構造ですが、いくつかのものは必須です。
これらの項目は重要であり、これらを含めない限り、プラグインは確実に機能しません。
これらの項目は、GPMでプラグインを公開する場合に必要な項目です。
前の項目で説明したように、プラグインにはいくつかの設定オプションが必要なので、randomizer.yamlファイルは次のようなものにします。
enabled: true
active: true
route: /random
filters:
category: blog
これにより、必要であれば複数のフィルターを持つことができますが、今のところ、タクソノミーカテゴリー:ブログを持つすべてのコンテンツがランダム選択の対象となるように指定しただけです。
すべてのプラグインには、enabled オプションが必要です。サイト全体の設定でこれがfalseの場合、プラグインは Grav によって決して初期化されません。すべてのプラグインはactive オプションも持っています。サイト全体の設定でこれが false の場合、各ページでプラグインを有効にする必要があります。複数のプラグインは、以下で説明するmergeConfig を使ってページのフロントマターで enabled/active をサポートすることにも注意してください。
Grav のデフォルトインストールでは、デフォルトでカテゴリと タグにタクソノミーが定義されています。この設定はuser/config/site.yamlファイルで変更することができます。
Gravの他の設定と同様に、日々の制御のためにこのデフォルトの設定に触れないことをお勧めします。必要なら、/user/config/plugins/randomizer.yaml
と呼ばれるファイルにオーバーライドを作成し、カスタム設定を格納します。このプラグインが提供する randomizer.yaml は、あなたのプラグインのために賢明なデフォルトを設定することを意図しています。
ベースとなるプラグインのクラス構造は、すでに次のようなものになっています。
<?php
namespace Grav\Plugin;
use Composer\Autoload\ClassLoader;
use Grav\Common\Plugin;
use RocketTheme\Toolbox\Event\Event;
/**
* Class RandomizerPlugin
* @package Grav\Plugin
*/
class RandomizerPlugin extends Plugin
{
/**
* Composer autoload.
*
* @return ClassLoader
*/
public function autoload(): ClassLoader
{
return require __DIR__ . '/vendor/autoload.php';
}
}
プラグインでこれらのクラスを使用するため、いくつかの use 文を追加する必要があります。use を追加することで、各クラスの完全な名前空間をインラインで記述する必要がないため、スペースを節約し、コードをより読みやすくします。
use 文を次のように修正します。
use Composer\Autoload\ClassLoader;
use Grav\Common\Plugin;
use Grav\Common\Page\Collection;
use Grav\Common\Uri;
use Grav\Common\Taxonomy;
このクラス構成で重要なのは2つ。
namespace Grav\Plugin
という名前空間が必要です。Grav は高度なイベントシステムを使用しており、最適なパフォーマンスを確保するために、すべてのプラグインは Grav によって検査され、プラグインがどのイベントにサブスクライブしているかが判断されます。
public static function getSubscribedEvents(): array
{
return [
'onPluginsInitialized' => [
['autoload', 100000], // TODO: Remove when plugin requires Grav >=1.7
['onPluginsInitialized', 0]
]
];
}
このプラグインでは、onPluginsInitialized イベントを購読していることを Grav に伝えます。これで、このイベント(プラグインが利用できる最初のイベント)を使って、他のイベントを購読すべきかどうかを判断することができます。
注:最初のオートロードイベントリスナーは、Grav 1.6 でのみ必要です。Grav 1.7 では自動的にこのメソッドが呼び出されます。
次のステップでは、RandomizerPlugin クラスにメソッドを追加して onPluginsInitialized イベントを処理し、ユーザーが randomizer.yaml ファイルで設定したルートに移動しようとしたときのみアクティブになるようにします。現在の 'sample' プラグインのロジックを以下のように置き換えてください。
public function onPluginsInitialized(): void
{
// 管理者用プラグインである場合は実行しない
if ($this->isAdmin()) {
return;
}
/** @var Uri $uri */
$uri = $this->grav['uri'];
$config = $this->config();
$route = $config['route'] ?? null;
if ($route && $route == $uri->path()) {
$this->enable([
'onPageInitialized' => ['onPageInitialized', 0]
]);
}
}
まず、DIコンテナから Uriオブジェクトを取得します。これには、ルート情報を含む、現在のURIに関するすべての情報が含まれています。
config() メソッドはすでにベース Plugin の一部なので、これを使えば設定したルートの設定値を簡単に取得できます。
次に、設定されたルートと現在の URI パスを比較します。もしそれらが等しければ、私たちのプラグインが新しいイベントである onPageInitialized も応答するようにディスパッチャに指示します。
このようなアプローチをとることで、必要のない余計なコードを走らせないようにしています。このような実装が、あなたのサイトを可能な限り高速に動作させます。
このプラグインの最後のステップは、ランダムなページを表示することです。
/**
* Send user to a random page
*/
public function onPageInitialized(): void
{
/** @var Taxonomy $uri */
$taxonomy_map = $this->grav['taxonomy'];
$config = $this->config();
$filters = (array)($config['filters'] ?? []);
$operator = $config['filter_combinator'] ?? 'and';
if (count($filters) > 0) {
$collection = new Collection();
$collection->append($taxonomy_map->findTaxonomy($filters, $operator)->toArray());
if (count($collection) > 0) {
unset($this->grav['page']);
$this->grav['page'] = $collection->random()->current();
}
}
}
DevToolsプラグインで作成されたサンプルプラグインは、onPageContentRaw() と呼ばれるイベントを使用していました。このイベントは私たちの新しいプラグインで使われないので、関数全体を安全に削除することができます。
これで、プラグインは完成です。プラグインクラスの完成形は、以下のようになります。
<?php
namespace Grav\Plugin;
use Composer\Autoload\ClassLoader;
use Grav\Common\Plugin;
use Grav\Common\Page\Collection;
use Grav\Common\Uri;
use Grav\Common\Taxonomy;
/**
* Class RandomizerPlugin
* @package Grav\Plugin
*/
class RandomizerPlugin extends Plugin
{
/**
* @return array
*
* The getSubscribedEvents() gives the core a list of events
* that the plugin wants to listen to. The key of each
* array section is the event that the plugin listens to
* and the value (in the form of an array) contains the
* callable (or function) as well as the priority. The
* higher the number the higher the priority.
*/
public static function getSubscribedEvents(): array
{
return [
'onPluginsInitialized' => [
['autoload', 100000], // TODO: Remove when plugin requires Grav >=1.7
['onPluginsInitialized', 0]
]
];
}
/**
* Composer autoload.
*
* @return ClassLoader
*/
public function autoload(): ClassLoader
{
return require __DIR__ . '/vendor/autoload.php';
}
public function onPluginsInitialized(): void
{
// Don't proceed if we are in the admin plugin
if ($this->isAdmin()) {
return;
}
/** @var Uri $uri */
$uri = $this->grav['uri'];
$config = $this->config();
$route = $config['route'] ?? null;
if ($route && $route == $uri->path()) {
$this->enable([
'onPageInitialized' => ['onPageInitialized', 0]
]);
}
}
/**
* Send user to a random page
*/
public function onPageInitialized(): void
{
/** @var Taxonomy $uri */
$taxonomy_map = $this->grav['taxonomy'];
$config = $this->config();
$filters = (array)($config['filters'] ?? []);
$operator = $config['filter_combinator'] ?? 'and';
if (count($filters) > 0) {
$collection = new Collection();
$collection->append($taxonomy_map->findTaxonomy($filters, $operator)->toArray());
if (count($collection) > 0) {
unset($this->grav['page']);
$this->grav['page'] = $collection->random()->current();
}
}
}
}
あなたがこのページの内容に従っている場合は、あなたのサイトに完全に機能する Randomizer プラグインを有効になっているはずです。ブラウザで http://yoursite.com/random にアクセスするとランダムなページが表示されるはずです。また、オリジナルのランダムプラグインは、getgrav.org サイトのプラグインダウンロードセクションから直接ダウンロードすることができます。
様々なプラグインで使用されている人気のあるテクニックの1つは、プラグインの設定(デフォルトまたはオーバーライドされたユーザー設定のいずれか)とページレベルの設定をマージするという概念です。これは、サイト全体の設定を行い、必要に応じて特定のページのための特定の設定を行うことができることを意味します。これはプラグインに多くのパワーと柔軟性を与えます。
Gravの最近のバージョンでは、この機能を自動的に実行するヘルパーメソッドが追加され、自分でそのロジックをコーディングする必要がなくなりました。SmartyPantsプラグインは、この機能の良い例を提供しています。
public function onPageContentProcessed(Event $event): void
{
$page = $event['page'];
$config = $this->mergeConfig($page);
if ($config->get('process_content')) {
$page->setRawContent(\Michelf\SmartyPants::defaultTransform(
$page->getRawContent(),
$config->get('options')
));
}
}
プラグインは、bin/plugin コマンドラインと統合してタスクを実行する機能も持っています。このような機能を実装したい場合は、プラグイン CLI のドキュメントに従うとよいでしょう。