a-blog cmsでPDFファイルのサムネイル画像を生成してみる【さくら編】

**ImageMagick** を使って、a-blog cmsでPDFファイルのアップロード時にサムネイル画像を生成してみる第二弾。

[ローカルでの設定（MAMP編）](http://qiita.com/nyatto/items/b36ba6ecf862a822cd55)の続きです。

せっかくなので、レンタルサーバにも設定してみます。
サーバはさくらのスタンダードです。

## 設定の流れ

1. サーバの設定
2. a-blog cmsのカスタマイズ
3. PDFアップロード！

## Step1: サーバの設定
さくらのレンタルサーバでは、全プランで ImageMagick が使えるようになっているそうです。

サーバコントロールパネルにログインし、「PHP設定の編集」メニューから **php.ini** に Imagick（PHP拡張モジュール）エクステンションの記述を追加します。

```
extension=imagick.so
```

これだけで phpInfo に imagick が表示されました。簡単！

![imagick_sakura.png](https://qiita-image-store.s3.amazonaws.com/0/111287/15980636-5146-7f75-f6ce-8b96bfeba644.png)

## Step2: a-blog cmsのカスタマイズ
[MAMP編](http://qiita.com/nyatto/items/b36ba6ecf862a822cd55) と同様にカスタマイズし、ファイルをアップします。

### 1. カスタムフィールドを作成
**/admin/entry/field.html** にPDFファイルをアップロードするカスタムフィールドを記述します（お好みでincludeファイルに）。

[カスタムフィールドメーカー](http://developer.a-blogcms.jp/tools/) でファイルのカスタムフィールドを作成し、画像ファイルのパス ( /images/fileicon/pdf.gif ) を変数 ( **%{ARCHIVES_DIR}{pdfThumbnail}** ) 変更します。

```html
<table class="entryFormTable acms-admin-table-entry">
	<tr>
		<th>PDFファイル</th>
		<td>
			<!-- BEGIN pdfFile@path:veil -->
			<input type="hidden" name="pdfFile@old" value="{pdfFile@path}" />
			<input type="hidden" name="pdfFile@secret" value="{pdfFile@secret}" />
			<input type="hidden" name="pdfFile@fileSize" value="{pdfFile@fileSize}" />
			<label for="input-checkbox-pdfFile@edit" class="acms-admin-form-checkbox">
				<input type="checkbox" name="pdfFile@edit" value="delete" id="input-checkbox-pdfFile@edit" />
				<i class="acms-admin-ico-checkbox"></i> 削除
			</label>
			<a href="%{ARCHIVES_DIR}{pdfFile@path}"><img src="%{ARCHIVES_DIR}{pdfThumbnail}" width="120" alt="" /></a>
			<!-- END pdfFile@path:veil -->
			<input type="file" name="pdfFile" />
			<input type="hidden" name="field[]" value="pdfFile" />
			<input type="hidden" name="pdfFile@baseName" value="{pdfFile@baseName}" />
			<input type="hidden" name="pdfFile:extension" value="file" />
			<input type="hidden" name="pdfFile@extension" value="pdf" />
		</td>
	</tr>
</table>
```

### 2. Hookを有効に設定
**config.server.php** でフック拡張を有効（0→1）に変更。

```php
define('HOOK_ENABLE', 1);
```

### 3. 独自処理の追加
**/php/ACMS/User/Hook.php** の **beforePostFire** function内に以下のコードを追加。

```php
public function beforePostFire($thisModule)
{
    if ( !sessionWithContribution() ) return false;  // 権限チェック

    $class      = get_class($thisModule);              // モジュールのクラス名取得
    $destDir    = sprintf('%03d', BID).'/thumbnail/';  // サムネイルを保存するディレクトリ名
    $fieldName  = 'pdfFile';                           // アップロードするPDFのフィールド名
    $thumbnailFieldName = 'pdfThumbnail';              // サムネイル画像の変数名

    // PDFファイルを元のファイル名に
    switch($class) {
        case 'ACMS_POST_Entry_Insert':
        case 'ACMS_POST_Entry_Update':

        $thisModule->Post->_aryField['pdfFile@filename'][0] = 'pdf/'.$_FILES['pdfFile']['name'];

        break;
    }

    // エントリーの作成or更新のみ
    if ( !in_array($class, array(
        'ACMS_POST_Entry_Insert',
        'ACMS_POST_Entry_Update'
    )) ) {
        return false;
    }

    $Post   =& $thisModule->Post;  // POSTデータを取得
    $bid    = $Post->get('bid');
    $cid    = $Post->get('cid');

    if ( !isset($_FILES[$fieldName]['tmp_name']) ) return false;

    $source = $_FILES[$fieldName]['tmp_name'];
    if ( !is_readable($source) ) return false;

    $myurl  = $source.'[0]';  // PDFの1ページを指定

    try {
        $image  = new Imagick();
        $image->setResolution(140, 140);  // 解像度を指定
        $image->readimage($myurl);        // PDFの読み込み
        $image->setImageFormat('png');

        ACMS_POST::setupDir(ARCHIVES_DIR.$destDir, intval(config('permission_dir')));  // 保存先ディレクトリの作成
        $file   = $_FILES['pdfFile']['name'].'.png';  // 保存ファイル名 (元のファイル名.png)
        $dest   = ARCHIVES_DIR.$destDir.$file;        // 保存先

        $image->writeImage($dest);
        $image->destroy();

        // カスタムフィールドに登録する為、POSTデータにサムネイル画像のパスを登録
        $Post->add('field', $thumbnailFieldName);
        $Post->add($thumbnailFieldName, $destDir.$file);
    } catch(Exception $e) {
        echo $e->getMessage();
    }
}
```

## 〈追記〉エントリー編集後も画像を保持する
エントリーを編集すると画像が消える問題、生成した画像は残っているので、画像のパスの書き方を変えることで解決したいと思います！

### ファイル名とパスを見てみる
サムネイル画像をPDFファイル名と連動したことで、それぞれのパスは以下のようになります（ブログIDが1のとき）。

PDFファイル: /archives/001/pdf/***filename*.pdf**
サムネイル画像: /archives/001/thumbnail/***filename.pdf*.png**

PDFファイルのパス ( 001/pdf/*filename*.pdf ) はカスタムフィールドの値 **{pdfFile@path}** なので、これに画像の拡張子を追加する ( **{pdfFile@path}.png** ) と画像のファイル名は取得できますね。

生成したサムネイル画像の保存先がPDFファイルと同じ場所 ( /archives/001/pdf ) ならこのままでOKでした。でもわたしはサムネイル画像は個別に管理したいのです。画像のパスを pdf ディレクトリから thumbnail に変更する必要があります。

そこで登場するのが **校正オプションの拡張** です！

### 校正オプションの拡張
まずはファイルを準備します。

> ダウンロードパッケージのomakeフォルダに含まれるファイルを、設置先にコピーします。
> 
> コピー元
> (*ダウンロードパッケージの展開先*)/omake/php/ACMS/User/Corrector.php
> コピー先
> (*a-blog cms設置先*)**/php/ACMS/User/Corrector.php**
> 
> 所定の位置にファイルがコピーされていれば、自動で校正オプションが拡張されるようになります。

参考）[校正オプションの拡張について](https://developer.a-blogcms.jp/document/develop/#eid1818)

**Corrector.php** に以下のコードを追加します。

```php
function pdf2thumb($txt, $args = array())
{
    if ( mb_strpos($txt, '/pdf/') ) {
        $txt = str_replace( '/pdf/', '/thumbnail/', $txt );
    }
    return $txt;
}
```

表示側の画像のパスを **{pdfThumbnail}** から **{pdfFile@path}.png** に変更し、作成した校正オプションを追加します。

```html
<!-- BEGIN pdfFile@path:veil -->
<a href="%{ARCHIVES_DIR}{pdfFile@path}" target="_blank"><img src="%{ARCHIVES_DIR}{pdfFile@path}[pdf2thumb].png" width="120" alt="" /></a>
<!-- END pdfFile@path:veil -->
```

{pdfFile@path}**[pdf2thumb]**.png のように校正オプションを追加することで 001/**pdf**/*filename.pdf*.png が 001/**thumbnail**/*filename.pdf*.png になります。

カスタムフィールドの画像のパスも変更しておきましょう。

```html
<table class="entryFormTable acms-admin-table-entry">
	<tr>
		<th>PDFファイル</th>
		<td>
			<!-- BEGIN pdfFile@path:veil -->
			<input type="hidden" name="pdfFile@old" value="{pdfFile@path}" />
			<input type="hidden" name="pdfFile@secret" value="{pdfFile@secret}" />
			<input type="hidden" name="pdfFile@fileSize" value="{pdfFile@fileSize}" />
			<label for="input-checkbox-pdfFile@edit" class="acms-admin-form-checkbox">
				<input type="checkbox" name="pdfFile@edit" value="delete" id="input-checkbox-pdfFile@edit" />
				<i class="acms-admin-ico-checkbox"></i> 削除
			</label>
			<a href="%{ARCHIVES_DIR}{pdfFile@path}"><img src="%{ARCHIVES_DIR}{pdfFile@path}[pdf2thumb].png" width="120" alt="" /></a>
			<!-- END pdfFile@path:veil -->
			<input type="file" name="pdfFile" />
			<input type="hidden" name="field[]" value="pdfFile" />
			<input type="hidden" name="pdfFile@baseName" value="{pdfFile@baseName}" />
			<input type="hidden" name="pdfFile:extension" value="file" />
			<input type="hidden" name="pdfFile@extension" value="pdf" />
		</td>
	</tr>
</table>
```

これでエントリーを編集しても画像が消えることはなくなりました。

## Step3: PDFアップロード！
カスタムフィールドでPDFファイルをアップロードしてみると、サイズの大きなファイルはアップロードできないことが判明しました。

### 1. アップロードできる上限サイズを確認

a-blog cms 管理ページのサイドメニューから「**チェックリスト**」へ。
「**サーバー環境情報**」を見ると、デフォルトの設定が

> アップロード上限サイズ　2M
> POSTデータ上限サイズ　8M

になっています。

![checklist_default.png](https://qiita-image-store.s3.amazonaws.com/0/111287/75030b22-3c1f-9691-7a5d-a5067e2b4924.png)

### 2. アップロードできる上限サイズを変更
**php.ini** ファイルを編集して上限サイズを変更します。

```
; アップロード上限サイズ
upload_max_filesize = 20M
; POSTデータ上限サイズ
post_max_size = 20M
```

わたしは20MBに設定しました。

![checklist_after.png](https://qiita-image-store.s3.amazonaws.com/0/111287/a740c2ad-298e-c82a-e926-b1e3919c7b7f.png)

### 3. PDFファイルをアップロード
再度試してみると、2MBを超えるファイルでもアップロードできるようになりました。

![entry.png](https://qiita-image-store.s3.amazonaws.com/0/111287/4b07ccc1-c4df-0a4f-4b11-6491509658a5.png)

サムネイル画像もちゃんと生成できていますね！

### 4. もしアップロードできなかったら…
上限サイズを変更してもファイルがアップロードできないときは **/archives** ディレクトリ以下のパーミッションを確認します。
（共用サーバの場合はパーミッションを705、専用サーバ・VPSの場合は777に設定）

最終的な **php.ini** はこんな感じに。

![phpini_sakura.png](https://qiita-image-store.s3.amazonaws.com/0/111287/58c55301-92e2-eaf8-2432-8ed41b20e16c.png)

## おわりに
ツール等をインストールする必要が無いので、ローカルで設定するよりもはるかに簡単でした！
さくらのレンタルサーバほんと大好き。

## 参考サイト
- [GD ・ ImageMagick(PerlMagick)は使えますか？｜さくらインターネット公式サポートサイト](https://help.sakura.ad.jp/app/answers/detail/a_id/1043)
- [さくらインターネットでは、PHP で extension=imagick.so するだけで ImageMagick が使えます : WEB 職人](http://webcraft.seesaa.net/article/181368260.html)