2017年2月28日火曜日

Gmail APIでシステムとGmail(G Suite)を連携【調査編】

gmail-accessPOP3とSMTPを使うのは面白くないので、API経由でGmailを利用したらメールを削除することなくシステムと連携できると思い、試したときの覚書。

公式サイトを参考に

 

目次

  1. APIの使用制限
  2. システム用アカウントをGoogle Apps(G Suite)に追加
  3. Server-to-Serverのサービスアカウントを作成
  4. PHPサンプルを試す
  5. ウェブアプリケーションのOAuth2.0で認証

 


1.APIの使用制限

APIの使用制限がある。1日10億Quota Unit。メソッドごとに消費ユニットが違う。例えばメール送信は100ユニット消費する。

一秒間に250ユニットの制限がある。同時に3つ以上送信しようとすると制限に引っかかる。詳しくは公式サイトで。

メール送信はローカルのPostfixに任せた方がいいかもしれない。

 

クライアントライブラリが未成熟(?)

PHPはベータ版

Node.jsはまだアルファ版

 


2.システム用アカウントをGoogle Apps(G Suite)に追加

やろうと思っていることの概要。

システム専用のアカウントを作って、そのアカウント宛てに届いたメールを順次処理していく。

処理が終わったら「既読」ラベルを付けてアーカイブ。

Node.jsはアルファ版なのでWordPressのプラグインとしてPHPで開発することにした。

 


3.Server-to-Serverのサービスアカウントを作成

システム専用アカウントでGoogle Developer Consoleにアクセスして、API Keyを生成する。

公式サイトを参考に

簡単な手順

  1. Gmail APIを有効にする(プロジェクトの作成)
  2. 認証情報を生成
    「役割」はよく分からないので「ログ書き込み」を選択
  3. キー情報のファイルがダウンロードされる

 


4.PHPサンプルを試す

GitHubからPHP用のクライアントライブラリをダウンロードする。

Releasesに置いてあるのは依存関係も含んでいるので、そのまま解凍すれば使える。

今のバージョンはv2.1.1

公式サイトのサンプルをGmail API用に変更して実行しても「アクセストークンがない」と怒られる。

"error": "unauthorized_client",
"error_description": "Client is unauthorized to retrieve access tokens using this method."

クライアントライブラリが自動でアクセストークンを取得すると思ったら違った。

よく分からないので「サービスアカウントキー」での認証は諦め。

前にやったことのある「ウェブアプリケーション」の認証方式で実装することにした。

 


5.ウェブアプリケーションのOAuth2.0で認証

公式サイトと前の記事を参考に。あとクライアントライブラリの仕様が変わってる。

 

スコープの設定メモ。

google-api-php-client\vendor\google\apiclient-services\src\Google\Service\Gmail.php
の最初の方にconstされている。

 

部下がこれやろうとしてたら「PHPMailerを使ってPOP3とSMTPでいいじゃん」というのは間違いない。

 

< Related Posts >

2017年2月27日月曜日

【PHP】composerをインストールして依存関係管理

php_composerGoogle先生の巨大ライブラリをリポジトリにコミットしたくなかったので、composerをインストールしたときの覚書。

環境: CentOS 7, PHP 7.0.16

 

参考サイト

 

目次

  1. composerとは
  2. YUM経由でインストール
  3. composerを使ってライブラリをインストール

 


1.composerとは

PHPの依存関係管理ツール。Node.jsのNPMやRubyのBundlerを参考にしている。

composer installするとcomposer.jsonを参照して「vendor」ディレクトリにライブラリがインストールされる。

composer.lockというファイルがあるとそちらを参照してそのバージョンをインストールするので、作った人と同じ環境を構築できる。

WordPressのプラグインみたいに別ディレクトリに設置してほしい場合も対応可能。

 


2.YUM経由でインストール

remiリポジトリにあった。バージョンは1.3.2
# yum install composer

依存関係で結構な数のライブラリがインストールされる。

確認
# composer --version

Do not run Composer as root/super user! See https://getcomposer.org/root for details
Composer version 1.3.2 2017-01-27 18:23:41

 


3.composerを使ってライブラリをインストール

インストールするライブラリはこちら。

今回WordPressプラグインの中で使う。
$ cd /path/to/wordpress/wp-content/plugins/hoge/

対話形式でcomposer.jsonを作ってみる。
$ composer init

{
    "name": "dksg/hoge",
    "type": "wordpress-plugin",
    "license": "MIT"
}

項目の意味はあとで公式ドキュメントを読む。

ライブラリインストール
$ composer require google/apiclient:^2.0

vendorディレクトリにライブラリがダウンロードされた。

.gitignoreでコミットしないようにする。
$ vi .gitignore

vendor/

 

ひとまず環境が整った。

 

< Related Posts >

2017年2月15日水曜日

Twitter Bootstrap利用サイトでIE8だとimgが表示されない

ie8_picture作ったサイトを念のためIE8で確認したら画像が表示されないので対応したときの覚書。

環境: Bootstrap 3.3.7, WordPress 4.7.2

 


1.【準備編】Windows7 + IE8の環境を作る(Hyper-V)

公式サイトでIE8を搭載した仮想マシンがダウンロードできる。

認証が必要。デスクトップに書いてあるのでそのままcmdで叩く。

 


2.IE8だけ読み込むCSSを用意

試した結果表示されない原因はdisplay: tableを指定していたから。

画像は基本的に中央揃えにしたかったので、次のように設定していた(lessを使ってる)。

.img-responsive {
    &:extend(.img-responsive all);
    display: table;
    margin: 0 auto;
}

 

他のに影響与えないでIE8のみに対応したかったので、IE8だけ読み込むCSSを用意して、そちらで対応することにした。

bootstrapを使うときにお約束の記述に追記(WordPressの関数を使ってる)。

<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<link rel='stylesheet' href='<?php echo get_template_directory_uri();?>/assets/css/ie8.css' type='text/css' />
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->

ie8.cssはこんな感じ。

.img-responsive {
    /* img tag disappear in IE8 when using display:table */
    display: block;
}

あとの細かいところは気にしない。

 

< Related Posts >

2017年2月14日火曜日

WordPressで非公開(private)にした投稿はリダイレクトしないようにする

wordpress_redirectionWordPressでホームページを作成しているときの覚書。

環境: PHP 7.0.15, WordPress 4.7.2

「お問い合わせ」ページから送信した内容を非公開の投稿として保存していた。

そして気付いた。

http://hoge.com/?p=20

とPost IDを付けると

http://hoge.com/鈴木太郎/

に変換(リダイレクト)される。

これはパーマリンクの設定を「/%postname%/」にしておいて、氏名とかを記事のタイトルとして保存した場合に発生する。

Contact Form 7を使っていれば発生しない(と思う)。

 

少なくとも検索エンジンにキャッシュされると困るのでリダイレクトしないように設定した。

このp=20がなかった(is_404)時に鈴木太郎に変換している関数は
/wp-includes/canonical.phpのredirect_canonical()

下記のようにpost_typeで判定してる箇所(117行あたり)があったので

$post_type_obj = get_post_type_object($redirect_post->post_type);
if ( $post_type_obj->public && 'auto-draft' != $redirect_post->post_status ) {
    $redirect_url = get_permalink($redirect_post);
    $redirect['query'] = _remove_qs_args_if_not_in_url( $redirect['query'], array( 'p', 'page_id', 'attachment_id', 'pagename', 'name', 'post_type' ), $redirect_url );
}

「post」タイプは公開しないので、全てリダイレクトしないようにフックを仕込む

function my_registered_post_type($post_type) {
    global $wp_post_types;

    if ($post_type == 'post' ||
        $post_type == 'attachment') {
        if (isset($wp_post_types[$post_type]->public)) {
            $wp_post_types[$post_type]->public = is_user_logged_in();
        }
    }
}
add_action('registered_post_type', 'my_registered_post_type');

プレビューで使うかもしれないので、ログインしているユーザーには許可するようにしてある。

WordPressをフレームワーク的に使うことが多いので気付いて良かった。

 

< Related Posts >

2017年2月8日水曜日

WordPressがBlankだったりトップにリダイレクトするのをデバッグ

wordpress_search久しぶりにWordPressの奥深くを潜っているときの覚書。WordPressは何がどの順番で実行するのか分かりにくいのでハマると長い。

環境: PHP 7.0.15, WordPress 4.7.2

 


1.確認すること

自分用チェックリスト

  1. サーバーにエラーログが出力されているかどうか
    # less /var/log/nginx/error.log
  2. wp_loadedにフックして読み込みが完了しているかどうか確認
    参考:Plugin API/Action Reference/wp loaded | WordPress Codex
  3. template-loader.phpの$templateをデバッグ出力してテーマのどのファイルを読み込もうとしているか確認
    参考:Template Hierarchy | Theme Developer Handbook | WordPress Developer Resources
  4. WordPressの内部で使っている「name」「year」などの名前でPOSTすると動作がおかしくなる
    参考:Class Reference/WP Query | WordPress Codex
  5. 存在しない関数を実行してエラーを起こして読み込まれた順番を確認。要xdebug

 


2.xdebugのインストール手順

YUM経由でインストール
# yum install php-pecl-xdebug
# systemctl status php-fpm

php infoを見て確認
# php -i | grep xdebug

 

< Related Posts >

2017年2月6日月曜日

Bootstrap3のWEBページを印刷してもいい感じに

bootstrap_printwkhtmltopdfでHTMLをPDF化しているときの覚書。

今までウェブサイトを印刷したときのことは全く考慮してなかった。Bootstrapのデフォルト機能にお任せだったけれど、印刷しても出来るだけ読みやすくなるようにしてみた。

環境: Bootstrap 3.3.7, less 2.7.2

 


1.印刷したときの横幅

Bootstrapの場合、印刷するとExtra small devices(.col-xs-)が適用される。

これは横幅が約547pxになるから。

<計算方法>

A4縦サイズの横幅は210mm
印刷するときのデフォルトマージンが約10mm
画面解像度が72dpi
1インチ=25.4mm、1mm=0.04インチ

A4の表示領域:210mm - (10mm x 2) = 190mm
mmをinchに変換:190mm x 0.04inch = 7.6inch
inchをpxに変換:7.6inch x 72dpi = 547.2px


 


2.Bootstrapで印刷用CSS

まずはBootstrapのprint.lessをimportしない。

替わりに下記CSSを読み込むと、small device(.col-sm-)が適用されたレイアウトに出来る。

これをlessで表現すると

@media print {
  .make-grid(sm);
}

Bootstrapのgrid.lessを参照。

あとの細かい箇所は必要なときに追加していく。

@media screen {}

も有用。

 

< Related Posts >

2017年2月3日金曜日

PHPでPDF生成するためにwkhtmltopdfをインストール

wkhtmltopdf_centos7HTMLからPDFを生成するコマンドラインツールwkhtmltopdfをインストールしたときの覚書。

環境: CentOS 7 x86_64

 

目次

  1. YUM経由でインストール
  2. 日本語フォントをインストール
  3. PHPシェルから実行
  4. PHP-FPMから実行するとエラー(2017/02/06 追記)

 


1.YUM経由でインストール

EPELリポジトリにあったのでそちらを使う。
# yum search wkhtmltopdf
# yum info wkhtmltopdf

Version     : 0.12.1
Repo        : epel/x86_64

# yum install wkhtmltopdf

試してみる
# wkhtmltopdf http://dksg.co.jp test.pdf

エラー

wkhtmltopdf: cannot connect to X server

下記QAを参考にした。

# yum search xvfb
# yum install xorg-x11-server-Xvfb

再度試す。
# xvfb-run /usr/bin/wkhtmltopdf http://dksg.co.jp test.pdf

成功したけど、日本語が表示されない。

 


2.日本語フォントをインストール

インストールされているフォント一覧を表示
# fc-list

Google先生が公開しているNoto Sans CJK JPを使う。公式サイトで「Japanese」と検索

ダウンロードと解凍
# cd /usr/share/fonts/
# curl -O https://noto-website-2.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip
# mkdir NotoSansCJKjp
# unzip -d NotoSansCJKjp/ NotoSansCJKjp-hinted.zip

フォントをインストールして確認
# fc-cache -fv
# fc-list

zipファイルは削除
# rm NotoSansCJKjp-hinted.zip

試す
# xvfb-run /usr/bin/wkhtmltopdf http://dksg.co.jp test.pdf

日本語が表示された。

基本は画面を印刷をした状態のCSSが適用される(@media printが適用される)。

詳しいオプションはヘルプを参照。
# wkhtmltopdf -H

レスポンシブデザインの横幅を変えようと下記コマンドを試してみたけど変わらない。最新にすると可能かもしれない。
# xvfb-run /usr/bin/wkhtmltopdf --dpi 200 --viewport-size 1280x1024 http://dksg.co.jp test.pdf
# xvfb-run --server-args="-screen 0 1024x768x24" /usr/bin/wkhtmltopdf --use-xserver http://dksg.co.jp test.pdf

 


3.PHPシェルから実行

PHPから実行するラッパークラスがある。

内部的にproc_openして、いい感じに実行結果を返してくれるみたい。

今回複雑なパラメータを渡す予定はないのでPHP標準のexecを利用することにした。

 

PHPから実行すると日本語が表示されない。

確認方法(rootユーザーでnginxユーザーとして実行するコマンド)
# sudo -u nginx /usr/bin/xvfb-run /usr/bin/wkhtmltopdf 'http://dksg.co.jp' 'test.pdf'

フォントがあるか確認
# sudo -u nginx fc-list

よく分からないので、WEBフォントを使うことにした。

Early AccessじゃなくなってもいいようにNoto Sansも一応追加しておいた。

<link href="https://fonts.googleapis.com/css?family=Noto+Sans" rel="stylesheet" />
<link href="https://fonts.googleapis.com/earlyaccess/notosansjapanese.css" rel="stylesheet" />

css

body, table {
    font-family: "Noto Sans JP","Noto Sans Japanese","Noto Sans",sans-serif;
}

 


4.PHP-FPMから実行するとエラー(2017/02/06 追記)

実装後にexecするとエラー

which: no xauth in ((null))
xvfb-run: error: xauth command not found

下記サイトを参考に

php.iniを編集して対応する。コメントを外すだけ。
# less /etc/php-fpm.d/www.conf

env[PATH] = /usr/local/bin:/usr/bin:/bin

再起動
# systemctl restart php-fpm

動くようになったけども重すぎてタイムアウトする。

大人しくTCPDFにすれば良かったと思いながらも別プロセスでPDFを生成するように処理を変える。

 

< Related Posts >

2017年2月2日木曜日

PHPでPDF生成する方法を調査

php_pdfユーザーが入力したデータを帳票にして送信する仕組みを作っているときの覚書。8年ぐらい前にも調査した続編。

有力候補たち

名称 説明
TCPDF

公式サイト
PHPライブラリ。
サンプルが充実していて使い方も簡単。迷ったらこれ。
wkhtmltopdf

公式サイト
WebKit HTML to PDF
ウェブサイトをPDF化してくれるコマンドラインツール。
要インストールなため自サーバーが必要。
HTMLでレイアウトを生成しておけばPDFに変換できるので楽。プレビュー → ダウンロード時にコマンド実行するだけ。
PHPから利用するためのライブラリもある。
Google Drive
(Google Sheets)

開発者向けサイト
Google Driveにスプレッドシートを作っておいて、
コピー → セルに値を挿入 → PDFに変換ダウンロード
というアイデア。
エクセルにも変換できるし応用がきく。学習コストは高め。
他のサービスに依存するのでAPI仕様変更とかが恐い。容量制限もあるので注意。

Google Drive APIを試したいけど、API利用規約とかも考えるとリスクが高い。

 

TCPDFは何度も使っていて面白くないので、wkhtmltopdfを試してみる予定。

 

< 2017/02/07 追記 >
wkhtmltopdfを実装してみた感想。

PHPからwkhtmltopdfをexecで呼び出して、渡すURLも自分自身のPDF用HTMLを動的に生成するPHPアドレスにした。

wkhtmltopdfが一度に複数呼び出されると処理が追いつかずタイムアウトする。

これを安定運用するには

  • wkhtmltopdfに渡すのは動的PHPではなくローカルのHTMLとして事前に出力しておく
  • wkhtmltopdfを複数起動しないようにキュー管理する
  • 自前で実装するのではなくて、URLからPDF作成サービスがあるのでそちらを利用する
  • やっぱりTCPDFにする

帳票のフォーマットが決まっているなら、テンプレートを読み込んで流し込む方がいい。

今試そうと思っているアイデアはHTMLをテキストでデータベースに保存して、生成したPDFもBlob型でデータベースに保存する方法。

実行中かどうかはシェルコマンドで判定する。

HTML(PHP)で作成したのがそのままPDFに出来るのは本当に楽。開発も修正も。

 

< Related Posts >

Related Posts Plugin for WordPress, Blogger...

Blog Archives