PHP 初心者が WordPress の プラグイン 作成 ! part71 ( ココナラブログの要素ビルダー作成・・・ )

この記事では PHP 初心者 が WordPress プラグイン を 作成 します。 part71 では要素ビルダーの実装方針を変更します。

要素ビルダークラスはひとまず作成できました。

PHP 初心者が WordPress の プラグイン 作成 ! part70 ( ココナラブログの要素ビルダー作成 )

さてこれからココナラブログ用に区切り線やリンク、画像の要素に変換するぞ!と思ったのですが結構時間がかかることに気が付きました。

要素はネストする

HTMLの要素というのはネスト(要素の中に要素)することができます。

<p>hoge <b>fuga</b> hago</p>

こんな風にネストされると変換はとても複雑なものになります。

単純に1行1要素を想定していましたが浅はかでした😅

時間が足りない

気づいたらこのシリーズ70を超えています!

100までには終わらせたいと思っていているのでもう時間がありません!

こうしよう

現実的な対応をしたいと思います。

  • 構成ビルダーにてWordPressのタグをすべて除去
  • 除去できなかったタグはすべてHTMLエスケープ
  • リンクを無効化(http,httpsはttp, ttpsに)

これなら簡単そうです。
画像もなんとかしたかったのですがこのシリーズではあきらめることにしました!

せっかく要素ビルダーを作成したのでこちらに記述していきます。

よし実装だ!

タグをすべて除去する正規表現は以下の記事にありましたので参考にさせていただきました。

正規表現サンプル(HTMLタグを削除する(記号で囲まれた文字の削除)) (hodade.com)

class.coconara-builder.php

<?php
class Coconara_Builder {

    // 文字列
    private string $lineText;

    // デバッグモード
    private bool $debug;

    // 編集用の変数
    private string  $fixedText;

    /**
     * コンストラクタ
     * @param string $lineText 1行分のWordPress文字列
     * @param bool $debug デバッグフラグ
     */
    function __construct(string $lineText, bool $debug = false) {
        // デバッグモードをセット
        $this->debug = $debug;
        
        // オリジナルテキストをセット
        $this->lineText = $lineText;

        // タグを全て除去
        $this->fixedText = preg_replace("<(\"[^\"]*\"|'[^']*'|[^'\">])*>", "", $this->lineText);

        // リンクを無効化
        $this->fixedText = str_replace("http", "ttp", $this->fixedText);

    }

    /**
     * ココナラブログのbodyプロパティ用の文字列を取得する
     * @return bodyプロパティ文字列
     */
    function getBody() : string{
        
        return "<div data-v-22617325=\\\"\\\" class=\\\"c-blogBody_text\\\">{$this->fixedText}</div>";
    }

    /**
     * ココナラブログのbodyTextプロパティ用の文字列を取得する
     * @return bodyTextプロパティ文字列
     */
    function getBodyText() : string {
        return "{$this->fixedText}\\n";
    }

    /**
     * 文字列が空かどうか確認する
     */
    function isEmpty() : bool {
        return empty($this->fixedText);
    }

}

呼び出し側(class.coconara-helper.php)では以下のような感じです。

require_once 'class.coconara-builder.php';
・
・
・
・
/**
 * 投稿する
 * @param string $title タイトル
 * @param string $contents コンテンツ
 * @return bool 投稿成功・失敗
 */
public function post(string $title, string $contents) : bool {
    $result = false;

    // ログイン
    if($this->login()) {
        // ブログ画面に遷移(ブログを投稿する→記事の種類選択で編集画面に遷移)
        if($this->moveAndWait('document.querySelector("a.c-subLink_item-blog").click()')
            && $this->moveAndWait('document.querySelector("button.button.is-primary").click()', waitTime:10000)) {


                // ブログを編集する

                // 本文を分解する
                $fixedRetuenCodeContents = str_replace(array("\r\n", "\r", "\n"), "\n", $contents);
                $contentArray = explode("\n", $fixedRetuenCodeContents);
                
                // 値の生成
                $contentForBody = "";
                $contentForBodyText = "";
                foreach ($contentArray as $item) {

                    // ビルダー生成
                    $builder = new Coconara_Builder($item, true);
                    
                    if(!$builder->isEmpty()) {
                        // body用の値
                        $contentForBody .= $builder.getBody();
                        
                        // bodyText用の値
                        $contentForBodyText .= $builder.getBodyText();
                    }
                }
                 
                // ヘッドレスブラウザに渡すクエリの作成
                $titleAndContentsQuery = 
                '(() => {
                    obj = document.querySelector("[data-v-46ae5ace]");
                    obj.__vue__.title = "'.$title.'";
                    obj.__vue__.body = "'.$contentForBody.'";
                    obj.__vue__.bodyText = "'.$contentForBodyText.'";
                    obj.__vue__.blogEmpty = false;
                })()';

                // 処理実行
                $this->execute($titleAndContentsQuery);


                // 公開画面を編集し投稿する

                // 画面表示
                if($this->moveAndWait('document.querySelector("button.button.c-blogPost_triggerPublish").click();', waitTime:10000)) {

                    // カテゴリとハッシュタグを指定
                    $categoryAndHashTagQuery = 
                    '(() => {
                        // カテゴリの選択
                        document.querySelector("div.c-blogPublishing_category select option[value=\"9\"").selected = true;
                        document.querySelector("div.c-blogPublishing_category select").dispatchEvent(new Event("change"));
                  
                        // ハッシュタグの指定
                        obj = document.querySelector("[data-v-46ae5ace]");
                        obj.__vue__.blogTagNames.push(" IT");
                        obj.__vue__.blogTagNames.push(" WordPress");
                
                    })()';

                    // 処理実行
                    $this->execute($categoryAndHashTagQuery);


                    // 投稿!
                    if($this->moveAndWait('document.querySelector("button[data-v-6c22d71e].button.is-primary").click();', waitTime:10000)) {
                        $result = true;
                    } else {
                        $result = false;
                    }
                } else {
                    $result = false;
                }
        } else {
            $result = false;
        }
    } else {
        $result = false;
    }

    if($this->debug) {
        // screenshot(10秒待機)
        $this->page->screenshot()->saveToFile('/var/www/html/post.png', 10000);
    }
    return $result;
}

まとめ

ココナラブログの要素ビルダーの実装を行いました。

いつの間にかpart70を超えていたので焦っています😄

果たして本番のWordPressに乗せられるのかどうか・・・少し怪しくなってきましたね。
しかし、なんとなくPHPのことが理解できるようになりました。プラグインの完成まで最後までがんばります。

今日はここまで!