Grav オリジナルプラグインの作成

Gravではマルチサイト構成が可能です。

必要なファイル(setup.php)の設置と、ディレクトリの設定をおこなってしまえば後は単純なコピー作業でサイトを追加できます。

毎回コマンドラインから作業してもいいのですが、管理画面から追加、削除などできれば楽でいいですね( ゚∀゚)

ということで個人的に楽をするためにそれっぽいプラグインを作成してみます。

まずはプラグイン作成の下準備としてDevToolsプラグインをGravにインストールします。

DevToolsはコマンドラインからプラグインやテーマのひな型が作成できます。


サーバー上でgravのインストールディレクトリに移動し以下のコマンドを実行

> bin/plugin devtools newplugin

いくつか入力を促されるので必要な情報を入力

> bin/plugin devtools newplugin
Enter Plugin Name: multiplesitetool
Enter Plugin Description: The configuration tool for multiple-site.                        
Enter Developer Name: Utano Mayonaka            
Enter GitHub ID (can be blank): 
Enter Developer Email: [email protected]

SUCCESS plugin multiplesitetool -> Created Successfully

Path: /home/grav/user/plugins/multiplesitetool

これでpluginディレクトリ内にプラグインのひな型が作成されたのでそちらを使ってプラグインを仕上げていきます。

作られたプラグインのひな形ディレクトリ[grav root]user/plugins/multiplesitetool の中を覗くとblueprints.yaml というファイルが作成されています。

このファイルが管理画面で表示されるプラグインの設定画面になるので、このファイルに必要な設定項目を書き足していきます。

オリジナルプラグイン画面

項目は有効化、ディレクトリ削除の条件、ディレクトリリスト、といった感じです。

有効化の項目はデフォルトで作成されるものでプラグインの有効無効の切り替えができるトグル項目です。

ディレクトリリストはuser/sites/ディレクトリ配下のディレクトリ構成を表示、または追加や削除をおこなうためのリスト項目です。

ディレクトリ削除の条件はディレクトリリストからディレクトリを削除した場合にuser/sites/配下のディレクトリを削除するかどうかのトグル項目です。

以上の内容からblueprints.yamlを編集して

File:blueprints.yaml
name: Multiplesitetool
version: 0.1.0
description: The configuration tool for multiple-site.
icon: cogs
author:
  name: Utano Mayonaka
  email: [email protected]
homepage: https://github.com/utano-mayonaka/grav-plugin-multiplesitetool
demo: http://demo.yoursite.com
keywords: grav, plugin, etc
bugs: https://github.com/utano-mayonaka/grav-plugin-multiplesitetool/issues
docs: https://github.com/utano-mayonaka/grav-plugin-multiplesitetool/blob/develop/README.md
license: MIT

form:
  validation: strict
  fields:
    enabled:
      type: toggle
      label: PLUGIN_MULTIPLESITETOOL.PLUGIN_STATUS
      highlight: 1
      default: 0
      options:
        1: PLUGIN_MULTIPLESITETOOL.ENABLED
        0: PLUGIN_MULTIPLESITETOOL.DISABLED
      validate:
        type: bool
    deletedirectory:
      type: toggle
      label: PLUGIN_MULTIPLESITETOOL.DELETE_DIRECTORY
      highlight: 1
      default: 0
      options:
        1: PLUGIN_MULTIPLESITETOOL.ENABLED
        0: PLUGIN_MULTIPLESITETOOL.DISABLED
      validate:
        type: bool
      help: PLUGIN_MULTIPLESITETOOL.DELETE_DIRECTORY_HELP
    domains:
      type: array
      label: PLUGIN_MULTIPLESITETOOL.DOMAINLIST
      value_only: true
      help: PLUGIN_MULTIPLESITETOOL.DOMAINLIST_HELP

だいたいこんな感じになってます。

やたらとPLUGIN_MULTIPLESITETOOL~という文字がでてきますが、多言語対応にするためにlanguageファイルを別に用意したため、そちらから読み出す形になっているためです。

やり方としては、[grav root]user/plugins/multiplesitetool ディレクトリ配下にlanguagesというディレクトリを追加して、その中に各言語用のファイルを用意します。今回はデフォルトのen.yamlと日本語用のja.yamlを追加しました。

File: en.yaml
---
PLUGIN_MULTIPLESITETOOL:
  PLUGIN_STATUS: "Plugin Status"
  ENABLED: "Enabled"
  DISABLED: "Disabled"
  DELETE_DIRECTORY: "Delete site directory"
  DELETE_DIRECTORY_HELP: "Delete site directory when remove a site-domain on the domain list"
  DOMAINLIST: "Sites directory"
  DOMAINLIST_HELP: "List at user/sites directory"
  PLUGIN_MULTIPLESITETOOL.CREATE_COMPLATE: "Complate create site directory"
  PLUGIN_MULTIPLESITETOOL.CREATE_PROBLEM: "Create site directory has same problems"
File: ja.yaml
---
PLUGIN_MULTIPLESITETOOL:
  PLUGIN_STATUS: "プラグインの状態"
  ENABLED: "有効"
  DISABLED: "無効"
  DELETE_DIRECTORY: "サイトディレクトリの削除"
  DELETE_DIRECTORY_HELP: "ドメインリストからサイトを削除した場合、サイトディレクトリも削除します"
  DOMAINLIST: "サイトディレクトリ"
  DOMAINLIST_HELP: "user/sites 内のディレクトリリスト"
  PLUGIN_MULTIPLESITETOOL.CREATE_COMPLATE: "サイトディレクトリの作成に成功しました"
  PLUGIN_MULTIPLESITETOOL.CREATE_PROBLEM: "サイトディレクトリの作成に問題が発生しました"

さて肝心のプラグイン本体ですが

File:multiplesitetool
<?php
namespace Grav\Plugin;

use Grav\Common\Plugin;
use RocketTheme\Toolbox\Event\Event;

/**
 * Class MultiplesitetoolPlugin
 * @package Grav\Plugin
 */
class MultiplesitetoolPlugin extends Plugin
{
    /**
     * @var array stringy
     */
    protected $sites;

    /**
     * @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()
    {
        return [
            'onPluginsInitialized' => ['onPluginsInitialized', 0]
        ];
    }

    /**
     * Initialize the plugin
     */
    public function onPluginsInitialized()
    {
        $current = basename($this->grav['uri']->url);
        // Don't proceed if we are in the admin plugin
        if ($this->isAdmin() && $current=='multiplesitetool') {
            if ($this->active) {
                $this->sites = $this->config->get('plugins.multiplesitetool.domains');

                $sites_path = dirname($this->grav['locator']->findResource('system://')) . '/user/sites';
                if (!file_exists($sites_path)) {
                    mkdir($sites_path, 0755, true);
                }

                $sites = (array_slice(array_filter(scandir($sites_path, 0), create_function('$entry', 'return is_dir("' . $sites_path . '/$entry");')), 2));
                $this->config->set('plugins.multiplesitetool.domains', $sites);

                if (isset($_POST['task']) && $_POST['task']=='save'){
                    $deldir = (isset($_POST['data']['deletedirectory']))? $_POST['data']['deletedirectory']==1 : false;
                    $domains = (isset($_POST['data']['domains']))? $_POST['data']['domains'] : array();
                    $user_path = dirname($this->grav['locator']->findResource('system://')) . '/user';

                    foreach($domains as $key=>$value){
                        $site = $sites_path . '/' . $value;
                        if (!file_exists($site)) {
                            mkdir($site, 0755, true);
                        }
                        $res = true;
                        if (!in_array($value, $sites)){
                            exec("cp -r {$user_path}/accounts {$site}");
                            exec("cp -r {$user_path}/config {$site}");
                            exec("cp -r {$user_path}/pages {$site}");
                            $res = symlink ($user_path . '/plugins', $site . '/plugins');
                            $res = symlink ($user_path . '/themes', $site . '/themes') && $res;
                        }
                    }

                    if ($deldir) {
                        foreach($sites as $key=>$value){
                            if (!in_array($value, $domains)){
                                $site = $sites_path . '/' . $value;
                                if (file_exists($site)){
                                    exec("rm -rf {$site}");
                                }
                            }
                        }
                    }
                }
            }
            return;
        }
    }
}

といった感じになってます。管理画面内でのみ機能すればいいのでテンプレート作成時の機能などはざっくり省いて、プラグインの初期化時にほとんどの作業が完結するような内容になってます。 これが本家のプラグインの仕様に沿っているかというとはなはだ疑問が残りますが、自分が使うものなので良しという感じでしょうか。

長くなったので作成時にいろいろ気づいたことやプラグイン周りの詳細に関してはまた次の機会にでも。

execコマンドでrmとか結構きわどいことやってるので使うなとは言いませんが流用する方は自己責任でおねがいします(=゚ω゚)ノ

Last edited: 2024-07-31 01:29