管理画面のプラグインメニューに「設定」リンクを追加する

Posted コメントするカテゴリー: WordPress

管理画面のプラグインを管理する画面で、プラグインメニューのタイトルの下に「設定」リンクを表示する方法を試します。

まず、プラグイン内に下記のようなフィルターフックを記述します。

add_filter('plugin_action_links_' . plugin_basename( __FILE__ ), array($this, 'plugin_action_links'), 10, 2);

続いて、次のような関数を追記します。

public function plugin_action_links($links, $file)
{
    $url = admin_url('admin.php?page=' . __FILE__);
    $url = '<a href="' . esc_url($url) . '">' . __( 'Settings' ) . '</a>';
    array_unshift($links, $url);
    return $links;
}

こうすることで、プラグインの管理画面の該当プラグインの下部に「設定
」リンクが表示されます。

URLについては、関数内で定義しているので、適宜書き換えるようにします。

カスタム投稿タイプを取得する

Posted コメントするカテゴリー: WordPress

登録されているカスタム投稿タイプの一覧を取得するには、次の関数を使います。

$post_types = get_post_types(array('public' => true));

この結果をprint_rで中身を確認してみます。

print_r($post_types);

結果、次のように出力されます。

Array
(
    [post] => post
    [page] => page
    [attachment] => attachment
)

上記のように、カスタム投稿タイプの一覧を取得することができます。

管理画面(ログイン画面)にjsを追加する

Posted コメントするカテゴリー: WordPress

ログイン画面にたいしてjsファイルを読み込む場合は、次のように書きます。

add_action('login_enqueue_scripts', 'my_script');

function my_script() {
    wp_enqueue_script('login_script', plugins_url('js/sample.js', __FILE__));
}

add_actionの第一引数に「login_enqueue_scripts」を設定するとログイン画面に対してプログラムが読み込まれます。

独自cssを読み込む

Posted コメントするカテゴリー: WordPress

独自のcssファイルを読み込む方法もjsファイルと同様の記述をします。

具体的には以下の記述をします。

wp_register_style();

wp_enqueue_style();

registerの関数は、実行時に出力を行わない形でcssファイルを登録します。
実際にブラウザ上に出力するにはenqueueのほうを使います。

独自jsファイルの読み込み

Posted コメントするカテゴリー: WordPress

プラグイン独自のjavascriptファイルを読み込む場合、以下の関数を使用します。

wp_enqueue_script($handle, $src, $deps, $ver, $in_footer);

各引数は次の意味になります。

$handle
ユニークな名前(ID)。wordpressシステム全体でユニークとなるIDを付ける。

$scr
jsファイルまでのurl

$deps
依存関係があるjsファイルの$handleを配列で指定する

$ver
jsファイルのバージョンを指定

$in_footer
「< script >」タグを「」直前ではなく、直前で出力する場合「true」と書きます。

まとめると、次のように書きます。

add_action('wp_enqueue_scripts', 'my_script');
function my_script() {
    wp_enqueue_script(
        'sample.js',
        plugins_url('js/sample.js', __FILE__),
        array('jquery'),
        '1.0',
        true
    );
}

jqueryファイルの読み込み

Posted コメントするカテゴリー: WordPress

開発したプラグイン内ではjavascriptファイルを用意して、javascriptの使用することができます。
(関連記事はこちらの記事を参照)

また、明示的にjqueryファイルを読み込む場合の書き方を調べます。

wordpressにはデフォルトでjqueryファイルが格納されているので、そのファイルを読み込む方法は下記のように記述します。

wp_enqueue_script('jquery');

この記述を行うことにより、jquery.jsのファイルが読み込まれます。

作成したプラグインを国際化対応する(まとめ)

Posted コメントするカテゴリー: WordPress

ここまでの作業で、プラグインの国際化の準備は整っています。
必要なポイントは以下になります。

  • プラグイン内で「_()」や「_e()」で翻訳部分を記述する
  • POTファイルを元に、POファイルとMOファイルを作成する
  • プラグインを読み込む記述をする(コンストラクタ内)
  • プラグインのヘッダーコメントに国際化を宣言する
  • 翻訳する
  • プラグインディレクトリに「languages」ディレクトリを作成する
  • 上記ディレクトリ内にPOTファイル、POファイル、MOファイルを設置する

また、一度翻訳した後のプラグインに対して、更新をかけようとした場合は、POTファイルを元に翻訳部分を更新してPOファイルとMOファイルを作成しなおします。

作成したプラグインを国際化対応する(その8)

Posted コメントするカテゴリー: WordPress

前回の投稿でpotファイルとmoファイルが手元にできています。

次に下記の国際化の為のコメントを、プラグインのphpファイルのファイルヘッダーに追加します。

Text Domain: SamplePlugin1
Domain Path: /languages

ここで指定するText Domainはこの投稿時で引数で指定した名称と同じにします。

作成したプラグインを国際化対応する(その7)

Posted コメントするカテゴリー: WordPress

前回の投稿でダウンロードしたPoeditでPOTファイルを作成します。

POTファイルは、_()や_e()の関数で指定したメッセージを翻訳する元となるファイルです。

まず、翻訳対象のプラグインのPOTファイルを作成します。
今回は「SamplePlugin1.php」というファイル名でプラグインを作っているので、単純にSamplePlugin1.potとします。

内容は以下のように書き、保存します。

msgid "mes1"
msgstr ""

次にPoeditで、potファイルを開きます。
メニューの「ファイル」→「POTファイルを元に更新・・・」を選択し、potファイルを読み込みます。

画面では以下のようになります。

potファイルを読み込むと、言語を指定するダイアログが表示されるので、確認のうえ、OKボタンを押します。

すると、次のような初期画面になります。

翻訳後の意味を、ツール下部の翻訳欄に記載します。

すると、ツールの中央上部にある「ソーステキスト」の訳として「翻訳-日本語(日本)」の欄に訳したテキストが入ります。

ここまでの流れの最後で、メニューの「ファイル」→「名前をつけて保存」を選択し、poファイルを保存します。
この時、同時にmoファイルも保存されます。

poファイルとmoファイルを作成するところまでで、一旦ブログを区切ります。(続きはまた次回へ)

作成したプラグインを国際化対応する(その6)

Posted コメントするカテゴリー: WordPress

ここまで準備してきたプラグインのphpに対し、
ここからは「POEDIT」というツールを使い、POファイルを作成します。

POEDDTIはこちらからダウンロードします。
(このブログを書いた時点で「Poedit-2.0.6-setup.exe」でした)

インストールして起動すると次のようになります。

起動後にメニュー→ファイル→設定から、「翻訳者に関する情報」を登録しておきます。

作成したプラグインを国際化対応する(その5)

Posted コメントするカテゴリー: WordPress

国際化対応その5は、プラグインのプログラムのコンストラクタ内で言語ファイルを読み込むように設定します。

具体的には以下のように記述します。

$plugin_dir = basename(dirname(__FILE__));

load_plugin_textdomain( 'プラグイン名', false,  . basename( dirname( __FILE__ ) ).'/languages' );

プラグイン名については、今回は「SamplePlugin1」というベースネームがあるので、以下のように書きます。

$plugin_dir = basename(dirname(__FILE__));

load_plugin_textdomain( 'SamplePlugin1, false, basename( dirname( __FILE__ ) ).'/languages' );

作成したプラグインを国際化対応する(その3)

Posted コメントするカテゴリー: WordPress

国際化対応するその3は、テキストドメインの決定です。

wordpressがプラグインを識別する為に、ユニークな名前にします。

プラグイン名にすると分かりやすく、運用がしやすいです。

今回は、これまで作ってきたプラグインの「SamplePlugin1」という名前にします。

また、この名前の決定は、後ほど出てくるPOファイルやMOファイルになります。

作成したプラグインを国際化対応する(その2)

Posted コメントするカテゴリー: WordPress

前回の作成したプラグインを国際化する対応について、
もう少し詳しく落とし込みます。

詳しくは公式ドキュメントのこちらのページに記載されています。

これまでに作成してきたプラグインは、以下のディレクトリになります。

/ワードプレスをインストールしたディレクトリ/wp-content/plugins/SamplePlugin1/

まず、このディレクトリ内に多言語用のディレクトリを新規作成します。

/ワードプレスをインストールしたディレクトリ/wp-content/plugins/SamplePlugin1/languages

作成したプラグインを国際化対応する

Posted コメントするカテゴリー: WordPress

WordPressの国際化対応をするには、ライブラリでGNU gettextを使用します。

■POTファイル
Portable Object Templateの略です。
翻訳対象となるメッセージと翻訳結果を保存するファイルのテンプレートとなるものです。

■POファイル
翻訳対象となるメッセージと翻訳結果を保存します。

■MOファイル
Machine Objectの略です。
翻訳結果を表示する為に必要になるファイルです。

実際に国際化する為には、上記の概念を把握した上で作成していきます。

ショートコードを改修する(その2)

Posted コメントするカテゴリー: WordPress

前回まで作成したショートコードをさらに改修します。

ショートコードを利用する側で、次のような記載の場合があります。

[samplelist3]なんらかの記述[/samplelist3]

この場合は、以下のような関数になります。

/**
 * ショートコード(その3)
 */
function samplelistFunction3($param, $content = '')
{
    
    if ($content == "") {
        return;
    } else {
        extract(
            shortcode_atts(
                array("class" => "default"),
                $atts
            )
        );
        
        return '<p class="' . esc_attr($class) . '">' . esc_html($content) . '</p>';
    }
    
}
 
add_shortcode('samplelist3', 'samplelistFunction3');

ショートコードを改修する

Posted コメントするカテゴリー: WordPress

このブログで実装を進めてきたプラグインについて、以前の記事になりますが、ショートコードを実装しました。

その時に実装した内容はこちらの記事になります。

今回はその時に実装したショートコードプラグインを改造してみます。

まず、前回のコードはちなみに下記のようになっています。

/**
 * ショートコード
 */
function samplelistFunction()
{
    //データ一覧
    $disp_html =<<< EOL
<form action="" method="post">
<h2>データ一覧(ショートコードテスト)</h2>

<div class="wrap">

<table class="wp-list-table widefat striped posts">
    <tr>
        <th nowrap>ID</th>
        <th nowrap>名前</th>
        <th nowrap>登録日時</th>
    </tr>
EOL;

    global $wpdb;

    $tbl_name = $wpdb->prefix . 'sample_mst';
    $sql = "SELECT * FROM {$tbl_name} ORDER BY id;";
    $rows = $wpdb->get_results($sql);

    foreach($rows as $row) {

$disp_html .=<<<EOL
    <tr>
        <td>{$row->id}</td>
        <td>{$row->sample_name}</td>
        <td>{$row->create_date}</td>
        <td>
    </tr>
EOL;
    }

    $disp_html .=<<< EOL
</table>

</div>

</form>
EOL;

    return $disp_html;
}

add_shortcode('samplelist', 'samplelistFunction');

上記のコードを投稿側で使用するには、

[samplelist]

のように書きます。

その際に、ショートコードのパラメータ部分を記述し、プログラム側に値として渡す方法を書きます。

[samplelist2 text="TEST"]

プラグイン側の記述も同様にパラメータを受け取るように変更します。

/**
 * ショートコード(その2)
 */
function samplelistFunction2($param)
{
    $default_param = array(
        "text" => "default text"
    );
    
    $merged_param = shortcode_atts($default_param, $param);
    extract($merged_param);
    
    return esc_html($text);
}

add_shortcode('samplelist2', 'samplelistFunction2');

上記のように実装し、投稿時には

[samplelist2 text="テスト値"]

のようにショートコードを使うことができます。

実際には値を渡す他に、IDやプラグインの挙動を制御するパラメータを渡す用途があるので、設計によって仕様を決めて実装をします。

ウィジェットの管理画面側で、値を保持&更新する

Posted コメントするカテゴリー: WordPress

作成中のウィジェットは、主にユーザ側への表示でしたが、このウィジェットに対し、管理画面側でなんらかの値を登録&更新する仕組みを実装します。

ウィジェットのソース内に以下のメソッドを追加します。

/**
 * 管理画面側のパラメータ調整用コード
 */
public function form($par)
{
    //入力された文字列(title)を取得
    if (isset($par["title"])) {
        $title = esc_attr($par["title"]);
    } else {
        $title = "";
    }

    //フォーム用のIDを取得
    $title_id = $this->get_field_id('title');
    
    //フォーム用のnameを取得
    $title_name = $this->get_field_name('title');
    
    //フォーム部分の表示
    echo <<<EOL
<label for="{$title_id}"><?php echo _e('Title:'); ?></label>
<input type="text" class="widefat" id="{$title_id}" name="{$title_name}" value="{$title}">
EOL;
}

こうすることで、管理画面で追加したウィジェットの部分に更新用のフォームが表示されます。

仮に「title」というパラメータ名として話を進めます。

上記のコードを書いた後に管理画面にアクセスすると、次のような画面になります(赤枠部分が追加箇所)。

この表示されたフォーム部分に対し、テキストを入力し保存ボタンを押します。

すると、保存しました。というメッセージになり、値が更新されます。

更新後は

<label for="{$title_id}"><?php echo _e('Title:'); ?></label>

というラベル部分の「echo _e(‘title’);」の箇所が表示され、入力した値が確認できます。

更新した値はウィジェット表示側のメソッド「public function widget」で$parの変数に格納されているので、下記のようにechoすることでユーザ側画面のサイドバーに表示されます。

public function widget($args, $par)
{
    echo $args["before_widget"];

    echo $args["before_title"];
    echo "これはウィジェットでの表示です";
    echo $args["after_title"];

    echo "ここは中身です";
    
    echo esc_html($par["title"]);

    echo $args["after_widget"];
    
}

ウィジェットの内容を表示する

Posted コメントするカテゴリー: WordPress

前回作成したウィジェットに、ブログ画面側の表示ロジックを入れてみます。

前回のソースコードを基に、public function widgetメソッドに対し、次のように記載します。

public function widget($args, $par)
{
    echo $args["before_widget"];

    echo $args["before_title"];
    echo "これはウィジェットでの表示です";
    echo $args["after_title"];

    echo "ここは中身です";
    echo $args["after_widget"];
}

次に、管理側の外観→ウィジェットの画面で、ウィジェットエリアに作成したsampleのウィジェットをセットします。

こうすることで、ブログ側のサイドメニューにウィジェットを表示することができます。

ウィジェットを作成する

Posted コメントするカテゴリー: WordPress

前回までは主にプラグインの作成についてやってきましたが、ここからは若干方針を変更して、ウィジェットの作成をやってみます。

まず、ウィジェットを作りにあたり、プラグイン用のフォルダに新規ファイルを作成します。

分かりやすいようにサーバ上の以下のフォルダ「SamplePlugin1」直下に新規ファイルを作成します。

/wordpressがインストールされているフォルダ/wp-content/plugins/SamplePlugin1

上記の場所に「SampleWidget1.php」を作成し、中には次のように記載します。

<?php

/*
Plugin Name: SampleWidget1
Plugin URI:  http://
Description: サンプルウィジェット。
Version:     1.0
Author:      sample
Author URI:  http://
License:     GPL2
License URI: https://www.gnu.org/licenses/gpl-2.0.html
*/

add_action(
    'widgets_init',
    create_function('', 'return register_widget("sample_widget");')
);

/**
 * Widget Class
 */
class sample_widget extends WP_Widget
{
    function __construct()
    {
        
        $widget_ops = array("description" => "Sample");
        $control_ops = array("width" => 400, "height" => 300);
        
        parent:: __construct(
            false,
            "Sample",
            $widget_ops,
            $control_ops
        );
        
    }
    
    public function widget($args, $par)
    {
        
    }
    
}

この記述だけで、管理画面のプラグイン画面には次のように表示されます。

その後「有効化」リンクを押して有効にします。

有効化した後は、管理画面の「外観」の中の「ウィジェット」というリンクが表示されるので、画面を開きます。

次に、管理画面の右側を確認すると、次のようなSampleウィジェットが表示されます。

この時、注意が必要なのは、テーマ側の作りによって、ウィジェットをサポートしていないと、管理メニュー内に「ウィジェット」というメニュー項目そのものが表示されなくなります。

ウィジェットを使う場合は、テーマ側の構造も把握しておくと良いです。

HTTP APIの検証(その4)

Posted コメントするカテゴリー: WordPress

前回に引き続き、HTTP APIの検証をします。

その4としてwp_remote_retrieve_response_code と wp_remote_retrieve_response_messageを試してみます。

//HTTP APIのテスト
$url = "http://hogehoge.fuga/";
$response = wp_remote_get($url, $args);

$return_code = wp_remote_retrieve_response_code($response);
var_dump($return_code);

$return_message = wp_remote_retrieve_response_message($response);
var_dump($return_message);

上記のコードを実行すると、以下のような結果が返ってきます(状況によります)

200

OK

また、wp_remote_get関数を使う場合の注意としては、$urlをesc_url()の関数を使う必要があります。
これはURL内にエスケープが必要な文字列があった場合に、安全に関数を動作させる為に必要になります。

具体的には、以下のように書くと良いです。

//HTTP APIのテスト
$url = "http://hogehoge.fuga/";
$response = wp_remote_get(esc_url($url), $args);

HTTP APIの検証(その3)

Posted コメントするカテゴリー: WordPress

前回に引き続き、HTTP APIの検証を行います。

3回目の関数はwp_remote_retrieve_headeresです。
前回同様、wp_remote_getした後に、この関数の戻り値をvar_dumpしてみます。

実際に下記のように書きました(ドメイン部分のみダミー値です)

//HTTP APIのテスト
$url = "http://hogehoge.fuga/";
$response = wp_remote_get($url, $args);

$return_value3 = wp_remote_retrieve_headers($response);
var_dump($return_value3);

var_dumpした結果、次のようになります。

object(Requests_Utility_CaseInsensitiveDictionary)[6275]
  protected 'data' => 
    array (size=9)
      'date' => string 'Sun, 04 Mar 2018 09:23:35 GMT' (length=29)
      'server' => string 'Apache' (length=6)
      'expires' => string 'Thu, 19 Nov 1981 08:52:00 GMT' (length=29)
      'cache-control' => string 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0' (length=62)
      'pragma' => string 'no-cache' (length=8)
      'set-cookie' => string 'PHPSESSID=547f926e3c6f4ec48bbc4966fb60a386; path=/' (length=50)
      'vary' => string 'Accept-Encoding,User-Agent' (length=26)
      'content-encoding' => string 'gzip' (length=4)
      'content-type' => string 'text/html; charset=UTF-8' (length=24)

結果表示をブラウザで確認したので、上記の値が全てではないかもしれませんが、取得項目はおおよそ把握できます。
詳しい出力結果はログに出力する等の工夫が必要です。

wp_remote_retrieve_headerでは、取得する項目を第二引数で指定する代わりに、wp_remote_retrieve_headersではヘッダー情報の全体を一気に取得してくる。という点が大きく異なります。

それぞれで使用する場面によって適切な使い方をする必要がありそうです。

HTTP APIの検証(その2)

Posted コメントするカテゴリー: WordPress

前回の投稿に引き続き、HTTP APIの検証を行います。

前回は「wp_remote_retrieve_header」の関数を試しましたが、今回は「wp_remote_retrieve_body」を書いてみます。

//HTTP APIのテスト
$url = "http://hogehoge.fuga/";
$response = wp_remote_get($url, $args);

$return_value = wp_remote_retrieve_body($response);

最後の「$return_value」をvar_dumpすると、相手先サーバから取得してきたサイトのHTMLソースが格納されています。

利用方法は開発場面により応用が必要ですが、手軽に外部サーバの情報を取得できる点は便利な反面、むやみにアクセスしすぎない等の配慮が必要になります。

HTTP APIについての検証

Posted コメントするカテゴリー: WordPress

前回の「HTTP API」について、実際のコードを書いて動作させて検証してみます。

まず、「wp_remote_get」について書いてみます。

プラグイン内の任意の箇所に以下のようなコードを書きました。(URLはダミーに置き換えています)

//HTTP APIのテスト
$url = "http://hogefuga.fuga/";
$response = wp_remote_get($url, $args);

このコードを実行し、$responseの値をvar_dumpで内容を見ると、以下のような結果が返ってきます。
長いですが、全て記載します。

Array
(
    [headers] => Requests_Utility_CaseInsensitiveDictionary Object
        (
            [data:protected] => Array
                (
                    [date] => Fri, 02 Mar 2018 15:04:02 GMT
                    [server] => Apache
                    [expires] => Thu, 19 Nov 1981 08:52:00 GMT
                    [cache-control] => no-store, no-cache, must-revalidate, post-check=0, pre-check=0
                    [pragma] => no-cache
                    [set-cookie] => PHPSESSID=1b6419888d849d81ce51d2cec9ddd499; path=/
                    [vary] => Accept-Encoding,User-Agent
                    [content-encoding] => gzip
                    [content-type] => text/html; charset=UTF-8
                )

        )

    [body] => 
    [response] => Array
        (
            [code] => 200
            [message] => OK
        )

    [cookies] => Array
        (
            [0] => WP_Http_Cookie Object
                (
                    [name] => PHPSESSID
                    [value] => 1b6419888d849d81ce51d2cec9ddd499
                    [expires] => 
                    [path] => /
                    [domain] => hogefuga.fuga
                )

        )

    [filename] => 
    [http_response] => WP_HTTP_Requests_Response Object
        (
            [response:protected] => Requests_Response Object
                (
                    [body] => 
                    [raw] => HTTP/1.1 200 OK
Date: Fri, 02 Mar 2018 15:04:02 GMT
Server: Apache
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: PHPSESSID=1b6419888d849d81ce51d2cec9ddd499; path=/
Vary: Accept-Encoding,User-Agent
Content-Encoding: gzip
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
                  [headers] => Requests_Response_Headers Object
                        (
                            [data:protected] => Array
                                (
                                    [date] => Array
                                        (
                                            [0] => Fri, 02 Mar 2018 15:04:02 GMT
                                        )

                                    [server] => Array
                                        (
                                            [0] => Apache
                                        )

                                    [expires] => Array
                                        (
                                            [0] => Thu, 19 Nov 1981 08:52:00 GMT
                                        )

                                    [cache-control] => Array
                                        (
                                            [0] => no-store, no-cache, must-revalidate, post-check=0, pre-check=0
                                        )

                                    [pragma] => Array
                                        (
                                            [0] => no-cache
                                        )

                                    [set-cookie] => Array
                                        (
                                            [0] => PHPSESSID=1b6419888d849d81ce51d2cec9ddd499; path=/
                                        )

                                    [vary] => Array
                                        (
                                            [0] => Accept-Encoding,User-Agent
                                        )

                                    [content-encoding] => Array
                                        (
                                            [0] => gzip
                                        )

                                    [content-type] => Array
                                        (
                                            [0] => text/html; charset=UTF-8
                                        )

                                )

                        )

                    [status_code] => 200
                    [protocol_version] => 1.1
                    [success] => 1
                    [redirects] => 0
                    [url] => http://hogefuga.fuga/
                    [history] => Array
                        (
                        )

                    [cookies] => Requests_Cookie_Jar Object
                        (
                            [cookies:protected] => Array
                                (
                                    [PHPSESSID] => Requests_Cookie Object
                                        (
                                            [name] => PHPSESSID
                                            [value] => 1b6419888d849d81ce51d2cec9ddd499
                                            [attributes] => Requests_Utility_CaseInsensitiveDictionary Object
                                                (
                                                    [data:protected] => Array
                                                        (
                                                            [path] => /
                                                            [domain] => hogefuga.fuga
                                                        )

                                                )

                                            [flags] => Array
                                                (
                                                    [creation] => 1520003042
                                                    [last-access] => 1520003042
                                                    [persistent] => 
                                                    [host-only] => 1
                                                )

                                            [reference_time] => 1520003042
                                        )

                                )

                        )

                )

            [filename:protected] => 
            [data] => 
            [headers] => 
            [status] => 
        )

)

これはサーバから返された結果になり、全ての結果情報が格納されているようです。

この中にはレスポンスヘッダやHTMLのbody内の文字列(上記の結果からは削除してあります)、などのコンテンツデータも取得できました。

この結果に対し、wordpressでは結果内容を簡単に解析するヘルパー関数があるようです。

ヘルパー関数の例を記載します。

//本文を取得
wp_remote_retrieve_body()

//ヘッダの値を取得
wp_remote_retrieve_header()

//全てのヘッダ情報を取得
wp_remote_retrieve_headers()

//ステータスコードを取得
wp_remote_retrieve_response_code()

//ステータスメッセージを取得
wp_remote_retrieve_response_message()

上記のどの命令を使うかは、場面により異なりますが、
まず、検証の為に「wp_remote_retrieve_header()」を使ってみます。

先ほど冒頭で書いた「wp_remote_get」の結果に対し、使ってみます。

//HTTP APIのテスト
$url = "http://hogefuga.fuga/";
$response = wp_remote_get($url, $args);

//ここで使用する
$header_value = wp_remote_retrieve_header($response, "date");

第二引数の「date」は、取得したいヘッダーの項目名を指定しています。別の項目名でもOKです。

この処理を実行した際、「$header_value」の変数には

Fri, 02 Mar 2018 15:20:49 GMT

等という値が取得されています。

本来であれば、ヘッダーの値を取得する前に、ステータスチェック等を行い、その上で値を取得する。等の対策が必要になってきます。

HTTP APIについて

Posted コメントするカテゴリー: WordPress

HTTP APIは、外部サーバに対してHTTP接続を行うAPIのようです。
実際に書いてみないと分からないことが多いので、まずは試しながら動きを確認してみます。

公式ドキュメントはこちらを参考にしています。

HTTP APIの関数は以下のものがあります。

wp_remote_get()
wp_remote_post()
wp_remote_haed()
wp_remote_request()

まずはドキュメントを読み、実際に試していきます。

Transients APIについて

Posted コメントするカテゴリー: WordPress

前回の投稿と似た機能を持つAPIを調査しました。

Transients APIというAPIで、ドキュメントはこちらのサイトになります。

このAPIは、データを一時的にデータベースへ保存するAPIで、
保存期間に有効期限を設定し、有効期限がすぎると削除されることが特徴です。

関数としては、次のものを使います。
それぞれ、データ保存時と、データ取得時です。

データ保存時
set_transient($transient, $value, $expiration);

第1引数は保存名(キー名のようなもの)、第2引数は値を表し、第3引数は有効期限の秒数を指定します。
データ取得時
get_transient($transient);

これらは、短時間のデータ保存が必要な場面で使用することが良さそうです。
実践で必要な場面があったら試す予定です。

WordPressAPIについて

Posted コメントするカテゴリー: WordPress

wordpressが標準装備していて、プラグインのプログラム内から呼び出して使用できるAPIがあります。

数あるAPIの中から、代表的なAPIを実際にプログラムして、使ってみます。

まずは、Options API という値を保持する為のAPIを使ってみます。
これまで作ってきたプラグインの画面遷移時の動きを利用して、画面遷移の間で値が保持できているかを確認してみます。

まず、データ一覧画面で

update_option("test", "a");

という記述を行い、これを登録画面→確認画面で、取得して表示してみます。

次に、登録確認画面側に、以下のように記述します。

$test_value = get_option("test");
echo $test_value; //内容チェック用に強引に出力する

これで、新規登録後の確認画面で「a」という文字列が表示されることが確認できました(画面キャプチャは省略します)。

保持したデータを削除するには

delete_option("test");

という記述で値を消すことができます。

update_optionと同様のAPIにadd_optionというAPIがあります。
これは画面アクセス時に対し、update_optionはまとめてデータ取得するのに対し、add_optionはget_optionを行う度にデータベースへ問い合わせが発生します。(add_optionの第4引数を使用時)

厳密に言えば、add_optionを多用すると、パフォーマンスが下がる原因になるようです。

データ登録時のエラー処理を変更する

Posted コメントするカテゴリー: WordPress

これまでの開発ではデータ登録時のエラー処理は、古典的(?)な書き方で入力チェック→エラー内容表示を行っていました。

wordpressには元々エラー処理用のクラスがあるので、それに置き換えてみようと思います。

まずは、入力画面から登録ボタンを押した際の、確認画面の処理を見直します。

//エラー処理を入れる為のオブジェクト生成
$error = new WP_Error();

//入力値チェック(複数のエラーチェックをここで行う)
if (!strlen($_POST["sample_name"])) {
    $error->add("error", "名前を入力してください");
}
if (!strlen($_POST["sample_text"])) {
    $error->add("error", "テキストを入力してください");
}

//エラーコードがある場合は、登録画面を再表示する
if ($error->get_error_code()) {
    //ここで改めて登録フォームを表示する
}

まず、「$error = new WP_Error();」とすることで、エラー処理用のクラスを呼び、オブジェクトを生成しておきます。

次に、入力値チェックを行います。
入力値のチェック方法は色々あると思いますが、ここでは「strlen」を使って単純に文字列(の長さ)があるか無いかで判定しています。
(チェック用の関数の使い方は、別方法がありますが、ここでは割愛いたします)

最後に、「$error->get_error_code()」でエラーだった場合のコードを取得し、エラー表示を行うか、どうかの判定をします。

エラーだった場合は、改めて登録フォームを表示します。

次に、エラー時の登録フォーム側のプログラムを調整します。

//エラー処理
if ($error->get_error_codes()) {
    echo "<div class='error'>";
    echo "<ul>";
    foreach ($error->get_error_messages() as $value) {
        echo "<li>" . esc_html($value) . "</li>";
    }
    echo "</ul>";
    echo "</div>";
}

$errorオブジェクトを渡し、エラーコードの有無を判定します。
エラーだった場合、エラー内容をエラーの個数分表示しています。

具体的な画面は次のようになります。

入力フォームの初期画面

エラーだった場合の再表示画面

エラーメッセージの表示時のクラス名

<div class='error'>

はwordpressに標準搭載されているcssのクラス名なので、画面のエラー文言の表現が統一されて便利です。

また、

<div class='updated'>

というクラス名もあり、その場合は正常に更新されたケースで使用するとよいです。

登録フォームに対し、CSRF対策を入れる

Posted コメントするカテゴリー: WordPress

これまでに作成したプラグインは、データ登録画面で、入力フォームを表示し、次の画面で内容チェック、その後に完了画面を表示する。という一連の動作になっています。

この時、入力フォームから確認画面へ遷移する際のセキュリティとして、CSRF攻撃がされる場面が想定されます。

このCSRF攻撃に対応する為に、対策を入れます。
具体的には、入力画面のform開始タグの直下に、以下の命令を書きます。

<?php wp_nonce_field("my-nonce-key", "my-form"); ?>

また、確認画面側では、次のように書いて、CSRFのチェックを行います。

//CSRF対策用のチェック
if (isset($_POST["my-form"]) && $_POST["my-form"]) {
    if (check_admin_referer("my-nonce-key", "my-form")) {
        //問題がなければ、ここで処理を続行
        
    }
}

ポイントとなる箇所だけを書きましたが、フォーム内に「wp_nonce_field」を、確認画面のチェック処理で「check_admin_referer」を、それぞれ使うということで、覚えておいてよいかと思います。

メディアアップローダを使わずにファイルのアップロードを行う

Posted コメントするカテゴリー: WordPress

前回の投稿ではメディアアップローダの画面を利用したファイルのアップロードを書きましたが、今回は単純なプログラムによるファイルのアップロードを書きます。

プラグインを作成する方向性としては、無意味な実装になるかもしれませんが、ここは実験がてらやってみます。

まず、作成中のプラグインのTOP画面にファイルアップロード用のボタンを追加します。

    function disp()
    {
        echo <<< EOL
<form action="" method="post">

    <h2>データ一覧</h2>
    <input type='submit' name='submit[regist]' class='button-primary' value='新規登録' />
    <input type='submit' name='submit[regist_file]' class='button-primary' value='新規登録(ファイルアップロード)' />

    <div class="wrap">

    <table class="wp-list-table widefat striped posts">
        <tr>
            <th nowrap>ID</th>
            <th nowrap>名前</th>
            <th nowrap>テキスト</th>
            <th nowrap>チェック</th>
            <th nowrap>ラジオ</th>
            <th nowrap>セレクト</th>
            <th nowrap>テキストエリア</th>
            <th nowrap>登録日時</th>
            <th nowrap>詳細</th>
            <th nowrap>編集</th>
        </tr>
EOL;

以下、省略します…

すると次のような画面になります。

続いて、ボタンを押下した際の動作を決める関数に、ファイルアップロード用画面と、アップロードボタンを押された際のメソッドを追加します。

function sample_plugin()
{
    if (isset($_REQUEST["submit"]["detail"])) {
        //他の処理は記述を省略します…

    } else if (isset($_REQUEST["submit"]["regist_file"])) {
        //ファイルアップロード用画面
        self::regist_file();
    } else if (isset($_REQUEST["submit"]["regist_file_up"])) {
        //ファイルアップロード処理
        self::regist_file_up();

    } else {
        self::disp();
    }
}

次に、画面上の「新規登録(ファイルアップロード)」ボタンを押した時の処理を書きます。

function regist_file($error_message_flg = null)
{
    echo <<< EOL
<h2>ファイルアップロード</h2>
<div class="wrap">
<div class="wrap">
<table class="wp-list-table widefat striped posts">
    <tr>
        <td>ファイルアップロード</td>
        <td>
            <form method="post" action="" enctype="multipart/form-data">
                CSVを選択してアップロードボタンを押してください<br />
                <input type="file" name="upfilename" />
                <input type="submit" value="アップロード">
                <input type="hidden" name="submit[regist_file_up]" value="on">
            </form>

        </td>
    </tr>
</table>
</div>
<form action="" method="post">
    <input type='submit' name='submit[file_upload]' class='button-primary' value='戻る' />
    <input type="hidden" name="form_id" value="{$form_id}">
    <input type="hidden" name="create_date" value="{$create_date}">
</form>
</div>
EOL;

}

今はデザインやレイアウトについては、割愛して書いています。
画面はこのようになります。

画面上から、ファイルを選択してアップロードボタンを押した後の処理は次のように書きました。

function regist_file_up()
{
    //CSVファイルがアップロードされた場合
    if (is_uploaded_file($_FILES["upfilename"]["tmp_name"])) {
        
        // wordpressが用意している関数
        $upload_dir = wp_upload_dir();
        
        // ファイル名を取得してアップロード処理を行う
        $upload_file_name = $upload_dir['basedir'] . "/" . $_FILES["upfilename"]["name"];
        if (move_uploaded_file($_FILES["upfilename"]["tmp_name"], $upload_file_name)) {
            chmod($upload_file_name, 0777);

            // アップロード&ファイル権限の変更が完了したら成功とする
            $message = "ファイルをアップロードいたしました";
        }
        
    } else {
        $message = "ファイルのアップロードが失敗しました";
    }

    //完了メッセージの出力
    echo <<< EOL
<h2>ファイルアップロード完了</h2>
<form action="" method="post">
<div class="wrap">
    {$message}
</div>
<input type='submit' name='submit[]' class='button-primary' value='戻る' />
</form>
EOL;

}

書き方は一般的なファイルアップロードによる処理と、変わらないですが、「wp_upload_dir();」というwordpressが用意している関数を使っている点がポイントになります。

この関数をコールし、「$upload_dir[‘basedir’]」という値をとることにより、wordpressの「uploads」ディレクトリまでのフルパスを参照できます。

そうすることで、uploadsディレクトリ直下にファイルをアップロードすることができています。

完了後は、次のような画面になります。

これで、ファイルをアップロードが完了します。
工夫や改善の余地はありますが、基本的な流れはできているので、あとはどのように応用するかになります。