Pico1.0での変更点（追記予定あり）

去年のクリスマスですが、Picoの1.0 Stableがリリースされました。

 * http://picocms.org/

今回のバージョンで記事フォーマットなど割とがっつり変わってます。プラグイン開発の観点を含めた変更点を以下に記します。使っている方はどうぞご確認ください。

# Picoコアの大きな変更点
Picoコア（lib/Pico.php）は、かなりがっつり変わってます。また、使用しているモジュールの種類が倍以上に増えていますので、composerのインストール処理にかかる時間が倍以上に増えています。

 * コンストラクタで記事のパースなどの処理を行わなくなった（実際の処理は`run()`メソッドに移行）
 * content_dirが、Picoルートディレクトリからの相対パス→絶対パスになった
 * コンフィグファイルに`content_dir`が記載されていなかった場合で、かつ`content`というディレクトリがPicoのルートディレクトリにある場合、そちらを自動設定するようになった
 * コンフィグファイルの読み取りパスが変わった（ルートディレクトリ→configディレクトリ）
 * `ROOT_DIR`、`LIB_DIR`等の定数定義がなくなった
 * サーバ変数、`REQUEST_URI`を読まなくなった
 * `.htaccess`にて、contentディレクトリ配下へのHTTPアクセスが出来ないように制限された
 * テンプレートファイルの拡張子が、.htmlから.twigになった（.htmlなテンプレートも使用できます）

詳しく書くべきところを下に書きます。

## コンストラクタで記事のパースなどの処理を行わなくなった（実際の処理は`run()`メソッドに移行）
いままで、PicoクラスはコンストラクタでCMSとしての全ての処理を行っていたのですが、それが`run()`メソッドに移動しました。このため、他のモジュールなどでPicoクラスを継承したり、呼び出して使うことがしやすくなっています。

## サーバ変数、`REQUEST_URI`を読まなくなった
こちらは、Apacheやnginxを使っている人には問題ないですが、PHPビルトインサーバを使ってテストしている人にはちょっとした問題です。

Pico標準添付の`.htaccess`や[公式サイト](http://picocms.org/docs/#url-rewriting)の指定によると、Picoの引数は全てindex.phpのうしろにQUERY_STRINGとして渡されるようになっています（つまり、`http://example.com/path/to/url`なら、`http://example.com/index.php?path/to/url`になる）。
なので、.htaccessを読まないPHPビルトインサーバでは、この設定が効かず、rewrite_urlが有効な状態ではPicoが正常動作しなくなるという問題があります。

対応するにはPico.phpの`evaluateRequestUrl()`を修正する手もあるのかと思いますが、あまり無駄にソースに手を入れたくないので、以下のようなルータースクリプトをビルトインサーバに読み込ませることにしました。

```php:router.php
<?php
if (isset($_SERVER['REQUEST_URI']) && !file_exists(__DIR__ . $_SERVER['REQUEST_URI'])) {
  $qs = $_SERVER['REQUEST_URI'];
  // 本来のクエリ文字列があれば追加
  if($qs[0] == "/") $qs = substr($_SERVER['REQUEST_URI'], 1);
  if(isset($_SERVER['QUERY_STRING'])){
    $qs = str_replace($_SERVER['QUERY_STRING'], "", $qs);
    $qs .= $_SERVER['QUERY_STRING'];
  }
  // クエリ文字列として追加
  $_SERVER['QUERY_STRING'] = $qs;
}
return false;
```

ちなみに、上記ルータスクリプトを設定して、本当にクエリ文字列があるURL(たとえば`http://example.com/path?aaa`)を渡すと、たとえパスが正しくてもNot Foundとなりますが、恐らく本家の問題ではないかと思われます（いままでは問答無用でクエリ文字列を切り捨てる実装だったので、クエリ文字列があるURLを全く考慮していないものと思われます）。あとで精査して必要ならプルリクしてみようかと。

## `.htaccess`にて、contentディレクトリ配下へのHTTPアクセスが出来ないように制限された
Pico標準添付の`.htaccess`には次の行が追加されました。

```
    RewriteRule ^(config|content|content-sample|lib|vendor)/.* - [R=404,L]
```

このため、contentディレクトリ配下に直接HTTPアクセスさせるようなプラグインを作っている方（わたしですね・・・）は、要注意です。

# プラグインに関する変更点
プラグインについては、大きく変わったのが以下の点です。

 * イベントトリガーとなるメソッドの名前が全部変更された([このへん](http://picocms.org/development/#migrating-plugins)にかいてあります)
 * プラグインはすべて、`AbstractPicoPlugin`というクラスを継承することになった（/libディレクトリの中にある）
 * プラグインについて、実行順序に関するルールが設定された
 * プラグインディレクトリ配下にファイルを配置してもコミットできなくなった(.gitignoreにpluginsディレクトリ配下のファイルが丸ごと指定されている)
 * `onPageRendering()`(元`before_render()`)の`$templateName`引数において、拡張子の指定が必須になった

また、原則として、プラグインは`protected $enabled = false;`という変数を冒頭で定義するのが基本となり、必要に応じてコンフィグファイルから、「`[プラグイン名].enabled = true`」として有効化して使うようになったようです。

なお、これらの条件を満たしていない、Pico0.x時代向けのプラグインの場合、最初からpluginsディレクトリに入っている、`00-PicoDeprecated`というプラグインが適用され、ちゃんと機能するように調整される仕組みになっています。ただし、いつまでもこの互換性が維持されるとは限らないので[早めに対応してね](http://picocms.org/development/#migrating-plugins) とのこと。

## プラグインについて、実行順序に関するルールが設定された
割と決めの問題のようですが、プラグインはPHPファイルの名前の前に、二桁の数字を指定することで、呼出し順序をある程度制御するようになりました（数字がないものについては、これら数字つきプラグインの後に呼び出されます）。
`Pico.php`の`loadPlugins()`メソッドのコメントによると

 * 00 to 19: Pico開発チーム側で作成したプラグインなど。ユーザーやサードパーティ開発者は利用不可
 * 20 to 39: 低レベルなコードヘルパープラグイン
 * 40 to 59: ページ配列に直接影響を与えるプラグイン
 * 60 to 79: テンプレートやマークダウンテキストの解釈に影響するプラグイン
 * 80 to 99: `onPageRendered`イベントを処理するプラグイン

というかたちになりました。

ちなみに、Picoはプラグインのファイル名＝中のクラス名という前提でプラグインを読み込んでいますが、ファイル名先頭の数字については無視するようです。

## プラグインディレクトリ配下にファイルを配置してもコミットできなくなった

「.gitignoreにpluginsディレクトリ配下のファイルが丸ごと指定されている」という件について、Gitを使い慣れてないとサブモジュールとしてプラグインを追加しようとして失敗するので「あれー」と悩むことがあるので注意です（自分は悩みました）
.gitignoreを編集するかサブモジュールをforceで追加しましょう。

## `onPageRendering()`(元`before_render()`)の`$templateName`引数において、拡張子の指定が必須になった

`onPageRendering()`(元`before_render()`)で指定できるテンプレート名には、テンプレートファイルの拡張子が必須になりました(いままでのテンプレート名は、拡張子として.htmlが自動的に指定されていましたが、それがつかなくなりました)。
そのため、`onPageRendering()`のテンプレート名には、拡張子を自分で設定してやるか、次のようにファイル名を見て拡張子を指定してやる必要があります。

```php
      $pico = $this->getPico();
      if (file_exists($pico->getThemesDir() . $pico->getConfig('theme') . '/tags.twig')) {
          $templateName .= 'tags.twig';
      } else {
          $templateName .= 'tags.html';
      }
```

# 記事フォーマットに関する変更点
記事フォーマットについての変更については、メタデータの書式が変更になり、YAMLとして処理されるようになりました(内部的にも、YAMLのパーサーを呼び出してそのまま処理しているようです)。
そのため、今までの記事で

```
/*
  Title: スマートフォンの基本
  Author: 3分教室
  Date: 2014-10-06T15:19:17.000Z
  Description: スマートフォンの基本について解説した動画をまとめた再生リストです。 動画によっては、複数の再生リストに登録されているものもありますのでご了承ください。
  URL: https://www.youtube.com/playlist?list=PLOinVdBt7IeTyWHd_gXTlzKddiEYNxP11
  Tag: embed
  Image: https://i.ytimg.com/vi/pXvf_Nd54_w/mqdefault.jpg
*/
```
等のように行頭に空白があったりするとメタデータを読み込んでくれません。

また、メタデータの開始・終了を示す記号も、ハイフン三文字(---)に変更になりました（これは、変更しないでも、現時点では問題なく処理されます）。

なので、新しい書式にならうと、上のメタデータは次のようになります。

```yaml
---
Title: スマートフォンの基本
Author: 3分教室
Date: 2014-10-06T15:19:17.000Z
Description: スマートフォンの基本について解説した動画をまとめた再生リストです。 動画によっては、複数の再生リストに登録されているものもありますのでご了承ください。
URL: https://www.youtube.com/playlist?list=PLOinVdBt7IeTyWHd_gXTlzKddiEYNxP11
Tag: embed
Image: https://i.ytimg.com/vi/pXvf_Nd54_w/mqdefault.jpg
---
```

また、YAMLになったので、例えば以下のように要素名の後ろにスペースがついてないメタデータ行があると、エラーになりますのでご注意ください(いままでのバージョンではどちらでもよかった)

```
---
Title: CommandRunner
Description: ファイルを読み込み、独自のコマンドコードを実行します。例えばファイルをコンパイルしたり、構文チェックを行うことができます。
URL: githubページを表示::https://github.com/TakamiChie/EditorSupportTools, CommandRunner(Meryスクリプト)::https://github.com/TakamiChie/mery-scripts/blob/master/CommandRunner.js
Download:CommandRunner.zip ←Downloadのあとのスペースが抜けている
---
````


# そのほか
## リライトURLを初期状態で使用しなくなった

リライトURL(URLをPHPを使っていないWebサイト風に見せるもの)を初期状態で利用しないようになったようです。使う場合はコンフィグファイルで'rewrite_url'をtrueに設定するようになりました。

## リクエストした記事ファイル以外のマークダウンファイル解析が行われなくなった
個人的にはちょっと大きな変更。リクエストした記事ファイル(リクエストしたURLに対応するファイル)以外のマークダウンテキスト解析が行われなくなりました。そのため、リクエストした記事ファイル以外のcontentの中身は空文字列になります(未解析状態の記事データはraw_contentに保存されている)。
今回からメタデータがYAMLになり複数行の文字列も難なく書けるようになったため、Descriptionなどで代用するようにしましょう。

## indexページの記事データURLにindexがつくようになった
indexページの記事データURLは、いままで`works/techbook/`など、ディレクトリ名までで終わっていました。
それが、Pico1.0からは、indexがつき、`works/techbook/index`という感じになります(もちろん、旧来どおり`works/techbook/`としても、ページを読み込むことは可能です)。

# まとめ
とりあえず必要なところの一覧としては、以下の通り

 * 利用者サイド
    * 記事のメタデータがYAML形式になっていない場合は（行頭に空白があれば）直すこと
    * リクエストした記事以外のcontentを読み込み表示するようなサイトを作っていた場合、Descriptionなどで代用できないか検討すること
    * プラグインを使用している場合、プラグイン名の前に数字をつけることを検討すること
 * 開発者サイド
    * プラグインの仕様を最新のバージョンに追従させること（ただし、古いプラグインもすぐ使えなくなるわけではない）
    * プラグインで、`content_dir`を見て処理を行っている場合は、見直すこと
    * `ROOT_DIR`、`LIB_DIR`等の定数はなくなっているため、使用していれば直すこと
    * Picoクラスを使用しても即CMSとしての動作を行わなくなったため、自分の拡張部分でPicoクラスを継承したり、利用したり出来ないか見直してみてもいいかもしれません。

とりあえず今調べた限り。