WordPressプラグイン審査に通るまでの実体験:exec削除→承認まで全記録

WordPress プラグイン審査 承認までの記録 WordPress
この記事は約13分で読めます。
「PDFをアップロードしたら、自動でサムネイルが生成されたらいいのに」 そんな素朴な思いから始まったプラグイン開発。完成までに何度もWordPress.orgの審査に落ち、コードを書き直し、セキュリティを見直し…。この記事では、Rapls PDF Image Creatorというプラグインを開発し、公式ディレクトリに公開するまでの全工程を、失敗談も含めて赤裸々に綴ります。

きっかけ:PDFのサムネイルが欲しい

WordPressのメディアライブラリではPDFがすべて同じアイコンで表示され、中身の区別がつきません。既存プラグインも条件に合わなかったので、自分で作ることにしました。 私のサイトでは、PDFファイルを頻繁にアップロードします。カタログ、マニュアル、レポート…。 でも、WordPressのメディアライブラリを開くと、PDFはすべて同じアイコン。 メディアライブラリPDF 「このPDF、何だっけ?」 いちいちダウンロードして開かないと中身がわからない。これが地味にストレスでした。 既存のプラグインも探しましたが、どれも微妙に違う。GhostScriptが必要だったり、有料だったり、更新が止まっていたり。 「ないなら作ろう」 エンジニアなら誰もが一度は思うこのセリフ。私もその誘惑に負けました。

開発環境の準備

Local by Flywheelでローカル環境を構築し、名前空間とオートローダーを使ったクラス設計でプラグインの基本構造を組みました。 まずはローカル環境の構築から。私はLocal by Flywheelを使っています。 プラグインの基本構造はこんな感じで設計しました: 名前空間(Namespace)を使ってクラスを整理。オートローダーも自前で実装しました。

最初の壁:PDF変換エンジン

PDF→画像変換にはImageMagickとGhostScriptの2つの方法がありますが、後述の審査でexec()が使用禁止となり、最終的にImageMagick一本に絞ることになりました。 PDFを画像に変換する方法は主に2つあります:
  1. ImageMagick(Imagick PHP拡張) – PHPから直接呼び出せる
  2. GhostScript – コマンドラインツール、exec()で実行
最初は両方に対応しようと思っていました。「ユーザーの環境に合わせて選べるようにしよう」と。 でも、これが後で大きな問題になるとは、この時は知る由もありませんでした…。

機能実装:こだわったポイント

PDFアップロード時の自動サムネイル生成、アイキャッチ画像としての設定、既存PDFの一括処理の3つにこだわりました。

1. アップロード時の自動生成

PDFをアップロードしたら、何もしなくてもサムネイルが生成される。これが一番こだわったポイントです。 add_attachmentフックを使って、PDFがアップロードされたタイミングを検知: メディアライブラリ

2. アイキャッチ画像として設定

生成したサムネイルをPDFの「アイキャッチ画像」として設定できるようにしました。 これでget_post_thumbnail_id()がPDF添付ファイルでも使えるようになります。テーマ開発者にとっては嬉しい機能のはず。

3. 既存PDFの一括処理

プラグインを有効化する前にアップロードしたPDFはどうする? 「一括生成」機能を実装しました。AJAXで1件ずつ処理して、プログレスバーで進捗を表示。 Rapls PDF Image Creator 一括変換

WordPress.org審査:地獄の始まり

審査ではexec()使用禁止、プレフィックス不足、プラグイン名の一般性、error_log()のパス露出など7項目を指摘されました。セキュリティ系の指摘が最も厳しく、GhostScriptエンジンの全削除を余儀なくされました。 ※以下のメール文面は、個人情報(メールアドレス等)を伏せたうえで、要点のみ抜粋しています。

メールのやり取り(時系列の要点)

  1. 自動プレレビュー(AI):名前/スラッグが一般的すぎる、所有権(メールドメイン)確認、プレフィックス、ディレクトリアセット同梱、Deprecated 指摘などが提示される
  2. 私の対応:プラグイン名を Rapls PDF Image Creator に変更し、スラッグも rapls-pdf-image-creator へ。所有権についても「raplsworks は自分のサイト」である旨を明確化
  3. 人のレビュー:Ghostscript エンジンで exec() を使っている点が危険として指摘される(ホスト側でブロックされる/悪用され得る)
  4. 再提出(v1.0.5)exec()/shell_exec() を完全削除し、Ghostscript エンジンを廃止。Imagick のみに一本化
  5. 再提出(v1.0.6):Plugin Check フィードバックを踏まえ、翻訳ロード等を整理。加えて「外部通信なし・追跡なし・nonce/権限チェック・適切なサニタイズ」など、審査チームが確認しやすい形で補足

メールで実際に来た主な指摘(要点)

  • 名前/スラッグが一般的すぎる:既存プラグインと混同されやすいので、ブランド/識別子を含めて区別する
  • 所有権の確認:プラグインの関連URLと、提出アカウントのメールドメインが一致しない場合は説明が必要(第三者なりすまし防止のため)
  • exec()/shell_exec() は危険:リモートコード実行につながり得る/多くのホストで無効化されているため、削除が求められる
  • プレフィックス不足:関数・グローバル・保存データ(option/meta/transient など)に衝突回避のプレフィックス(4文字以上)が必要
  • ディレクトリ用アセットは ZIP に入れない:バナー/アイコン/スクショ等は承認後に SVN の assets へアップロード(ZIP同梱は避ける)
  • Deprecated 関数:将来的に壊れる可能性があるため、代替手段へ置き換える

私が再提出コメントで書いたこと(コピペできる”短い型”)

返信は長文にせず、レビュアーが「確認すべき点」をすぐ拾えるように、次の順で短くまとめました。 プラグインが完成し、意気揚々とWordPress.orgに提出。 数日後、メールが届きました。
Your plugin has been reviewed and we have concerns…
却下。 ここから、審査との長い戦いが始まりました。

指摘1: プラグイン名が一般的すぎる

最初は「PDF Image Creator」という名前でした。
プラグイン名にユニークなプレフィックスを付けてください。
「Rapls PDF Image Creator」に変更。Raplsは私のブランド名です。

指摘2: exec()は使用禁止

これが一番痛かった。 GhostScriptエンジンはexec()関数でコマンドを実行していました。
exec()、shell_exec()、system()などのシェル実行関数は、セキュリティ上の理由から使用できません。
せっかく実装したGhostScript対応を、泣く泣く削除。ImageMagick一本に絞りました。

指摘3: プレフィックスの統一

関数名、定数、オプション名…すべてに一貫したプレフィックスが必要でした。

指摘4: flush_rewrite_rules()の削除

有効化・無効化時にflush_rewrite_rules()を呼んでいましたが、これも指摘を受けました。
このプラグインはカスタム投稿タイプやリライトルールを登録していません。不要な処理は削除してください。
確かに、意味もなく入れていました。反省。

指摘5: error_log()のファイルパス露出

デバッグ用に入れていたerror_log()が問題に。 サーバーのファイルパスが露出するのはセキュリティリスク。WP_DEBUGが有効な時だけログを出すように修正しました。

指摘6: load_plugin_textdomain()は不要

翻訳の読み込み処理を入れていましたが…
WordPress 4.6以降、WordPress.orgでホストされるプラグインは翻訳が自動的に読み込まれます。load_plugin_textdomain()は非推奨です。
知らなかった…。削除しました。

指摘7: 日本語翻訳のスタイル

日本語翻訳ファイルも審査対象でした。 WordPress日本語チームの翻訳スタイルガイドに従う必要があります。 細かいですが、約50箇所を修正しました。 なお、審査通過後に日本語翻訳を自分で承認できるようにするため、PTE(Project Translation Editor)を申請しました。プラグイン作者が自分の翻訳を素早く反映させたい場合は、PTE取得がおすすめです。

最終的なコード品質

審査を通過するために、入力のサニタイズ・出力のエスケープ・nonce検証を全箇所に徹底し、WordPress Coding Standardsに準拠したコードに仕上げました。 審査を通過するために、以下の点を徹底しました:

セキュリティ

  • すべての入力値をサニタイズ(sanitize_text_field()absint()など)
  • すべての出力をエスケープ(esc_html()esc_attr()esc_url()
  • AJAX処理には必ずnonce検証と権限チェック
  • カスタムHTMLにはwp_kses_post()でサニタイズ

コーディング規約

  • WordPress Coding Standardsに準拠
  • PHPDoc形式のコメント
  • 適切な名前空間とクラス設計

互換性

  • PHP 7.4以上で動作(readonlyプロパティやmatch式は使わない)
  • WordPress 5.0以上で動作

ついに承認!

何度もの修正を経て、ついに承認メールが届きました。exec削除、プレフィックス統一、セキュリティ対策の徹底が承認の決め手でした。 WordPress Plugin Directory 承認メール 何度もの修正を経て、ついにメールが届きました。
Congratulations, your plugin hosting request for Rapls PDF Image Creator has been approved.
正直、泣きそうになりました。

公開後の反省と学び

審査を通じてセキュリティ意識とコーディング規約の理解が大幅に向上しました。一方で、最初からガイドラインを読んでおけばGhostScript対応の無駄な工数を避けられたのが最大の反省点です。

良かったこと

  • 審査プロセスを通じて、セキュリティ意識が大幅に向上した
  • WordPressのコーディング規約を深く理解できた
  • 「動けばいい」から「正しく動く」へ意識が変わった

反省点

  • 最初からWordPress.orgのガイドラインを読んでおくべきだった
  • GhostScript対応に時間をかけすぎた(結局削除)
  • 翻訳スタイルガイドの存在を知らなかった

これからプラグインを開発する人へ

  1. まずガイドラインを読むPlugin Guidelinesは必読
  2. Plugin Check プラグインを使う – 提出前に自動チェックできる
  3. exec()系は諦める – 外部コマンド実行は審査に通らない
  4. プレフィックスは最初から統一 – 後から変更するのは大変
  5. セキュリティは妥協しない – サニタイズ・エスケープ・nonce検証

プラグインのダウンロード

Rapls PDF Image Creatorは、WordPress公式ディレクトリから無料でダウンロードできます。 Rapls PDF Image Creator プラグインページ PDFを扱うサイトを運営している方は、ぜひ試してみてください。

開発者向け:テンプレート関数

テーマ開発者向けにテンプレート関数とショートコード4種類を用意しています。get_post_thumbnail_id()でPDFのサムネイルを取得できます。 テーマ開発者の方向けに、テンプレート関数も用意しています: ショートコードも4種類用意しているので、コードを書かなくても使えます。詳しくはプラグイン紹介ページをご覧ください。

さいごに

WordPress.orgの審査は厳しいですが、その分だけ自分のコード品質が上がります。審査で落ちても成長のチャンスです。 プラグイン開発は、想像以上に学びの多い経験でした。 特にWordPress.orgの審査は厳しいですが、その分、公開されているプラグインの品質が担保されています。ユーザーとして、これは安心材料ですよね。 もし「自分でもプラグインを作ってみたい」と思っている方がいれば、ぜひ挑戦してみてください。審査で落ちても、それは成長のチャンス。私も何度も落ちました(笑) 質問があれば、コメント欄でお気軽にどうぞ!

関連記事

プラグイン開発・審査・翻訳に関連する実体験記事です。

コメント

タイトルとURLをコピーしました