Manul Tech

WordPress上でPDFにパスワードを設定したプログラムのアップデート

前回、WordPress上でPDFにパスワードを設定するやつを作ったんだけど、ちょっとした問題があったのでアップデートすることに。

前回のものでも問題なく動作していたんだけど、あるPDFをアップロードした際にエラーが発生

Fatal error: Uncaught setasignFpdiPdfParserCrossReferenceCrossReferenceException: This PDF document probably uses a compression technique which is not supported by the free parser shipped with FPDI. (See https://www.setasign.com/fpdi-pdf-parser for more details)

フリーのパーサーではサポートしていないPDFですよ、と。
エラーにあるURLを見てみると、どうやらフリーのパーサーではPDF ver1.4までしかサポートしていないから、ver1.5以上のパースをしたい場合は対応したパーサー買ってね、ってことらしい。そういえばPDFにもバージョンなんてものがあったな。。

Setasign
FPDI PDF-Parser

料金プランはいくつかあって、100 EUR / Licenseからとのこと。
うーん、一万円ちょいかー。別にそれぐらい払えばいいんだけど、別の方法がないか一応調べることにした。

PDF ver1.5以上に対応しているフリーパーサー

以下のカタコト翻訳されているポストを発見。

コードログ
php – 1.4以上のPDFバージョンをサポートするFPDIフリーパーサー

なんでも同じ問題に直面して自作されたのだとか。すげーなー。
ということで有難く使わせていただくことに。

GitHub
pauln/tcpdi

READMEにある通りにpauln/tcpdi_parserFPDF_TPLもダウンロードして、path/to/TCPDFに突っ込んどく。
前回はFPDIを利用したけど、今回はいらないみたい。

require_once('lib/tcpdf/tcpdf.php');
require_once('lib/tcpdf/tcpdi.php');

$pdf = new TCPDI();
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
$page_count = $pdf->setSourceFile('path/to/sourcefile');
$pdf->SetProtection(['print', 'copy', 'modify'], 'password');

for($i = 1; $i <= $page_count; $i++){
    $page = $pdf->importPage($i);
    $pdf->AddPage();
    $pdf->useTemplate($page, 0, 0);
}
$pdf->Output('savepath/to/PDF', 'F');

前回と違うのはライブラリの読み込み部分と、new TcpdfFpdi が new TCPDIになっただけ。

しかし、またしてもエラーが

Warning: Declaration of .......

調べてみるとPHPのバージョンが7以上の場合に出るエラーのようで、

継承によりメソッドをオーバーライドする場合は、継承元と同じメソッド定義にする。
・親クラスと引数の数が異なるとNG
・デフォルト値のあり・なしが異なるとNG(値は変わってもOK)
・Typehintも同じでないとNG

とのこと。

Shin x blog
PHP E_STRICTで表示されるエラーメッセージを調べてみた

エラーが出ていたのはfpdf_tpl.php(Version 1.2.3)の275行目。

public function SetFont($family, $style = '', $size = 0) {...}
↓
//引数をTCPDFに揃える
public function SetFont($family, $style='', $size=null, $fontfile='', $subset='default', $out=true) {...}

これでOKと思ったらまた別のエラーが。

ERROR: count(): Parameter must be an array or an object that implements Countable ...

countメソッドのパラメーターがおかしいらしい。今度はtcpdi_parser.php(Version 1.1)で。
該当箇所の486行目を見てみるとこんなコードだった。

} elseif (($key == '/Index') AND ($v[0] == PDF_TYPE_ARRAY AND count($v[1] >= 2))) {

..countメソッドの中に比較演算子。。こんな書き方ってあったんだろうか。一応調べてみたけど見当たらず。でも、$v[1] >= 2が返す値はboolean型のはずだからcountする意味はあるんだろうか。。
よくわかんないけど、$v[1]が2以上ならいいのだろうということで(適当)、以下のように変更。

} elseif (($key == '/Index') AND ($v[0] == PDF_TYPE_ARRAY AND ($v[1] >= 2))) {

countとっただけ。
これでエラーも出ずに、無事にPDF ver1.5でもパースすることができました!
結果的にFPDIを使わなくなったことでファイル容量も少なくなってよかったかな。

コメント0