WordPressのプラグインで認証付きダウンローダー

S3に入れて置いたデータをwordpressのプラグインで認証付きのダウンローダを作れないかとの検討

プラグインは便利なので、Wordpressにログインした人のみがダウンロードできるようにしたい

こんな感じでできました

環境

    • s3にファイルを格納しておく
      wordpressはec2
      プラグインはショートコードでWordpressの固定ページなどに埋め込む
  • 仕様

    http://example.com/downloader?img=dir/file.png&token=session&userid=userid
    
    • img: S3のファイルパス
    • token: wordpressのセッションID
    • userid: wordpressのログインID(ログイン名ではなくWordpress内部でのログイン番号)

    データ

    以下に格納しておく
    s3://example/dir/file.png

    ショートコード

    固定ページをhttp://example.com/downloaderで作成し、以下を埋め込む

    [sample_downloader]
    

    プラグイン

    sample_downloaderディレクトリ以下にmain.phpで作成

    run($userid,$token,$img);
    }
    
    require_once( plugin_dir_path(__FILE__) . 'vendor/autoload.php' );
    add_shortcode('sample_downloader','sample_downloader_func');
    use Aws\S3\S3Client;
    
    
    class SampleDownloader{
        function run($userid,$token,$img){
            $bucket="example";
    
            // 認証
            $wp_token=wp_get_session_token();
            $wp_userid=wp_get_current_user();
            if($userid!=$wp_userid->ID || $wp_token!=$token){
                header("HTTP/1.1 401 Unauthorized");
                return "Authorized Error";
            }
    
            try{
    
                $s3Client = S3Client::factory(array(
                        'version' => 'latest',
                        'region'  => 'ap-northeast-1'
    	        ));
                
                $result = $s3Client->getObject([
                    'Bucket' => $bucket,
                    'Key' => $img
                ]);
                $body=$result["Body"];
    
    
                $fname=basename($img);
                $sfx=pathinfo($fname, PATHINFO_EXTENSION);
                header("HTTP/1.1 200 OK");
    
                // これで本体から出力されるHTMLをクリアする
    	    if (ob_get_length() > 0) {
                    ob_end_clean();
                }
    
                switch($sfx){
                    case "svg":
                        header('Content-Type: image/svg+xml');
                        break;
                    case "png":
                        header('Content-Type: image/pmg');
                        break;
                    case "jpg":
                    case "jpeg":
                        header('Content-Type: image/jpeg');
                        break;
                    case "gif":
                        header('Content-Type: image/gif');
                        break;
                    case "csv":
                        header('Content-Type: text/csv');
                        break;
                    case "json":
                        header('Content-Type: application/json');
                        break;
                    case "pdf":
                        header('Content-Type: application/pdf');
                        break;
                    case "xls":
                        header('Content-Type: application/vnd.ms-excel');
                        break;
                    case "xlsx":
                        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
                        break;
                    case "ppt":
                        header('Content-Type: application/vnd.ms-powerpoint');
                        break;
                    case "pptx":
                        header('Content-Type: application/vnd.openxmlformats-officedocument.presentationml.presentation');
                        break;
                    case "doc":
                        header('Content-Type: application/msword');
                        break;
                    case "docx":
                        header('Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
                        break;
                    default:
                        header('Content-Type: application/octet-stream');
                }
    
                header('Content-Disposition: attachment; filename='.$fname);
                return $body;
    
            }catch(Exception $e){
                header("HTTP/1.1 500 Internal Server Error");
    	    return "Error";
            }
        }
    }
    ?>
    
    

    デプロイ

    zipファイルを作成しWordpressのプラグインでアップロード
    cd sample_downloader
    composer  require aws/aws-sdk-php
    cd ..
    zip -r sample_downloader.zip sample_downloader/*php sample_downloader/vendor
    

    wordpressのエラー

    2,3日前に,以前作成したWordpressのサイトが,
    エラーで入れなくなったと連絡がありました。

    さくらインターネットで運用しているのですが,サポートに連絡しても
    埒が開かないので,こちらにヘルプ依頼が。

    確かに,Wordpressのログインができないようになっています。
    仕方がないので,SSHログインしてみたところ, dead.letter  が。

    この問題を解決しようとする際、以下の情報を聞かれるかもしれません。
    WordPress バーション5.8.1
    現在のテーマ: Spacious (バージョン 1.9.4)
    現在のプラグイン: Contact Form 7 (バージョン 5.5.1)
    PHP バージョン5.6.40
    
    エラー詳細
    ===============
    エラータイプ E_PARSE が wp-content/plugins/contact-form-7/admin/includes/welcome-panel.php ファイルの 9 行目で発生しました。 エラーメッセージ: syntax error, unexpected 'print' (T_PRINT), expecting identifier (T_STRING)
    

    こんなエラーが出てました。どうやらプラグインの自動アップデートでやられたようです。
    ContactForm7なのでたくさん使われているはずなのに,それほど大きな問題になっていないのはなぜ?

    調べたところどうやら,これが原因。

    さくっと,welcome-panel.phpを修正し

    Line 9: Rename function to public function _print()
    Line 223: Rename to $column->_print();
    

    動きました。

    どうやら,このサイトはphp5.6で運用していたのが原因かもしれません。
    このあとPHP7.4にアップデートしておきました。

    Day Of Yearカレンダープラグイン

    WordPressのプラグインでDayOfYearを表示するものを作成してみました

    プラグイン作成準備

    最初にディレクトリを作成します。今回は自分用に作成するので特に名前も気にしていないのですが、公開する場合には名前のかぶらないものにすることをお勧めします。

    $ mkdir utbt_doycalendar
    

    このディレクトリにplugin.phpファイルを作成しヘッダを作成します。
    この辺りはお決まりですので、このあたりのサイトに書かれている通りにします

    
    
    
    

    こんな感じで十分でしょうか?

    ショートコード対応

    今回はWordpressのプラグインとしてショートコードをページに記入レバ表示できるような仕様にします。
    また、ページには1年間分のカレンダーを表示し、年をテキストボックスでフォーム入力し、Submitすることにより切り替えます。
    この際に、FormからはGetパラメタで送信し、プラグイン内でGetパラメタを取得して年を切り替えます。

    カレンダー作成

    最初から作ってもいいのですが、こちらを参考にさせていただきました。

    ソースコード

    で、完成したコードがこちら

    
    
    calendar($year);
    }
    
    add_shortcode('utbt_calendar','utbt_calendar_func');
      class UtbtCalendar{
    
        function calendar($year=''){
    
    
            if (empty($year) && empty($month)) {
                $year = date('Y');
            }
            $html="
    Input Yea r:"; for($i=1;$i<=12;$i++){ $html.=$this->calendar_exec($year,$i); } $html.="
    "; return $html; } //http://shanabrian.com/web/php_calendar.php private function calendar_exec($year = '', $month = '') { $tab=""; $str=""; if (empty($year) && empty($month)) { $year = date('Y'); $month = date('n'); } //月末の取得 $l_day = date('j', mktime(0, 0, 0, $month + 1, 0, $year)); //初期出力 $html = << {$year}/{$month} Sun Mon Tue Wed Thr Fri Sat \n EOM; $lc = 0; // 月末分繰り返す for ($i = 1; $i < $l_day + 1;$i++) { $classes = array(); $class = ''; // 曜日の取得 $week = date('w', mktime(0, 0, 0, $month, $i, $year)); // 曜日が日曜日の場合 if ($week == 0) { $str .= $tab."\t\t\n"; $lc++; } // 1日の場合 if ($i == 1) { if($week != 0) { $str .= $tab."\t\t\n"; $lc++; } $str .= $this->repeatEmptyTd($week); } if ($week == 6) { array_push($classes, '#0000FF'); } else if ($week == 0) { array_push($classes , '#FF0000'); } if (count($classes) > 0) { $class = '"'.implode(' ', $classes).'"'; } $doy = date('z', mktime(0, 0, 0, $month, $i, $year))+1; $str .= $tab."\t\t\t".''.$i.'('.$doy.')'."\n"; // 月末の場合 if ($i == $l_day) { $str .= $this->repeatEmptyTd(6 - $week); } // 土曜日の場合 if ($week == 6) { $str .= $tab."\t\t\n"; } } $html .=$str; $html .= "\n"; return $html; } private function repeatEmptyTd($n = 0) { return str_repeat("\t\t \n", $n); } } ?>

    リリース

    できたコードをディレクトリごとZIPファイルにし、Wordpressのプラグインに追加します。
    また、ページにはこんな感じで書けば無事カレンダーが表示されます

    [utbt_calendar]
    

    デモ

    作成したデモサイトはこちらになります