今回はMaxiGalleryが管理する情報を基にMediaRSSファイルを生成するスニペットを解説していきます(オレンジの部分)。スニペット自作の細かい手順やコーディング規約などを紹介してから実際に手を動かして作ってもらった方が理解が深まると思いますが紙面の都合で割愛します。「こんなことができるのね」といった感じで見てもらえると嬉しいです。実際はMODxのリソーステーブルなども参照しますが、その辺はご愛嬌ということで・・・
1.データ仕様
1.1 MaxiGalleryのデータ構造
MaxiGalleryのMySQL内のテーブルと写真ファイル・フォルダの構成を図解します。ざっと説明すると、画像とテーブルのレコードが一対一で管理されており、gal_idが示すリソースごとにサブフォルダが作られ、各々の画像がその下に配置されます。下の例では、gal_id1,2,3それぞれに2つずつ画像をアップした格好です。
1.2 転送方式
出力対象のMediaRSSファイルと各タグへのデータ転送仕様(例)です。
| ファイルパス | : | MODxインストールURL/assets/cache/rss/photos.rss |
| タグの構成と転送 | : |
| タグ | 転送データ | 引用元 |
|---|---|---|
| channel | - | |
| atom:link | サイトURL + MRSS相対パス | グローバル変数、スニペット引数 |
| title | サイト名 | グローバル変数 |
| link | サイトURL | グローバル変数 |
| generator | サイト名 | グローバル変数 |
| copyright | 著作権文字列 | スニペット引数 |
| description | 固定文字列 + サイト名 | グローバル変数 |
| atom:icon | サイトURL + ロゴファイル相対パス | グローバル変数、スニペット引数 |
| item | 画像数分ループ | |
| title | リソース名:画像タイトル | リソース変数、MGテーブル |
| description | リサイズ画像のパス(IMGタグ有り) | グローバル変数、スニペット引数、MGテーブル |
| link | 画像ページのURL | リソース変数、MGテーブル |
| guid | 同上 | 同上 |
| pubDate | 画像の日付(RFC2822書式) | MGテーブル |
| media:description | 画像の説明 | MGテーブル |
| media:thumbnail | サムネイル画像のパス(プレフィクス付与) | グローバル変数、スニペット引数、MGテーブル |
| media:content | リサイズ画像のパス(IMGタグ無し) | グローバル変数、スニペット引数、MGテーブル |
2.スニペットの作成
2.1 外部仕様
スニペットの引数を説明します。制作するスニペットが自分専用で特に拡張性が必要なければ、引数などにせずにスニペット内でハードコーディングしてもOKです。
| 引数名 | 説明 | 値(初期値/設定例) |
|---|---|---|
| rsspath | MediaRSSファイルへの物理パス | 初期値:assets/cache/rss/mrss.rss 設定例:assets/cache/rss/photos.rss |
| mgtable | 接頭辞(“modx_”)を除いたMGのテーブル名 | 初期値:maxigallery 設定例:maxigallery |
| mgfolder | MGの画像を置くルートフォルダ名(assetsフォルダ直下にあるものと仮定) | 初期値:galleries 設定例:galleries |
| mgbigpre | リサイズ画像とは別の大きな画像ファイルの接頭辞 | 初期値:big_ 設定例:org_ |
| mgthumbpre | サムネイルファイルの接頭辞 | 初期値:tn_ 設定例:thumb_ |
| mgusebig | media:contentタグに転送する画像の種類 false:リサイズ画像固定 true:大画像があれば大画像を埋め込み |
初期値:false 設定例:true |
| logopath | CoolIrisに表示するロゴ画像の相対パス | 初期値:”"(表示しない) 設定例:assets/images/CILogo.gif |
| copyright | copyrightタグに埋め込む文字列 | 初期値:”"(タグ出力なし) 設定例:Copyright 2010 aaa. |
| includeDocs | 出力するリソースID(CSV形式のgal_idリスト) ※子リソースも包含 | 初期値:”"(1つも画像を出力しない) 設定例:1,2,3 |
| excludeDocs | 除外するリソースID(CSV形式のgal_idリスト) ※子リソースも除外 | 初期値:”"(1つも画像を外さない) 設定例:4,5 |
| limit | フィード件数 ※2010/05/07追記(記載漏れ) |
初期値:999999(≒制限なし) 設定例:20 |
| order | 表示順 ※2010/05/07追記(記載漏れ) |
初期値:date DESC, pos ASC(MGデフォルト) 設定例:pos ASC |
| timezone | RFC2822書式変換のためのタイムゾーン ※2010/05/07追記(記載漏れ) |
初期値:Asia/Tokyo 設定例:Asia/Tokyo |
2.2 処理フロー
スニペット内の処理をざっくり示すと下の感じになります。
2.3 コーディング
スニペットを新規に作成し、以下の設定を行ってから保存してください。
| スニペット名 | : | MaxiGalleryMediaRss |
| 説明 | : | MaxiGalleryのテーブルデータをrssファイルに出力 |
| スニペットコード | : |
/*==============================================================================
Title: MediaRss for MaxiGallery
Category: Snippet
Author: quickart
Author URI: http://www.quickart.jp/
License: GNU General Public License(http://www.gnu.org/licenses/gpl.html)
Version: 1.0.0
Last Update: 2009-12-24
==============================================================================*/
/******************************************************************************
* Check Parameter
******************************************************************************/
// Phisical path of RSS file on server.
$rsspath = isset($rsspath) ? $rsspath : 'assets/cache/rss/mrss.rss' ;
// Table name of MaxiGallery
$mgtable = isset($mgtable) ? $mgtable : 'maxigallery' ;
$mgtable = $modx->getFullTableName($mgtable) ;
// Folder name of MaxiGallery.
$mgfolder = isset($mgfolder) ? $mgfolder : 'galleries' ;
// Big file prefix of MaxiGallery.
$mgbigpre = isset($mgbigpre) ? $mgbigpre : 'big_' ;
// Thumbnail file prefix of MaxiGallery.
$mgthumbpre = isset($mgthumbpre) ? $mgthumbpre : 'tn_' ;
// Use big file if big file saved.
$mgusebig = isset($mgusebig) ? $mgusebig : 'false' ;
// Path of logo file.
$logopath = isset($logopath) ? $logopath : '' ;
// Text of copyright.
$copyright = isset($copyright) ? $copyright : '' ;
// Id list of included resource.
$includeDocs = isset($includeDocs) ? $includeDocs : '' ;
$includeDocs = explode(',', $includeDocs) ;
// Id list of excluded resource.
$excludeDocs = isset($excludeDocs) ? $excludeDocs : '' ;
$excludeDocs = explode(',', $excludeDocs) ;
// Feed count
$limit = isset($limit) ? $limit : '999999' ;
// Record order
$order = isset($order) ? $order : 'date DESC, pos ASC' ;
// Time zone
$timezone = isset($timezone)? $timezone : 'Asia/Tokyo' ;
/******************************************************************************
* Edit header
******************************************************************************/
$rss = '' ;
$rss .= '<?xml version="1.0" encoding="' . $modx->config['modx_charset'] . '" standalone="yes"?>' . "\n" ;
$rss .= '<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/" xmlns:atom="http://www.w3.org/2005/Atom">' . "\n" ;
$rss .= '<channel>' . "\n" ;
$rss .= '<atom:link href="' . $modx->config['site_url'] . $rsspath . '" rel="self" type="application/rss+xml" />' . "\n" ;
$rss .= '<title><![CDATA[' . $modx->config['site_name'] . ']]></title>' . "\n" ;
$rss .= '<link>' . $modx->config['site_url'] . '</link>' . "\n" ;
$rss .= '<generator><![CDATA[' . $modx->config['site_name'] . ']]></generator>' . "\n" ;
if ($copyright != '') {
$rss .= '<copyright><![CDATA[' . $copyright . ']]></copyright>' . "\n" ;
}
$rss .= '<description><![CDATA[Images of ' . $modx->config['site_name'] . ']]></description>' . "\n" ;
if ($logopath != '') {
$rss .= '<atom:icon>' . $modx->config['site_url'] . $logopath . '</atom:icon>' . "\n" ;
}
/******************************************************************************
* Query Database and Edit item
******************************************************************************/
// create included resource id list
$includeIds = array() ;
if ($includeDocs != '' && is_array($includeDocs)) {
foreach($includeDocs as $includeDoc) {
array_push($includeIds, $includeDoc);
$includeIds = $modx->getChildIds($includeDoc, 99999, $includeIds ) ;
}
}
// create excluded resource id list
$excludeIds = array() ;
if ($excludeDocs != '' && is_array($excludeDocs )) {
foreach($excludeDocs as $excludeDoc) {
array_push($excludeIds , $excludeDoc);
$excludeIds = $modx->getChildIds($excludeDoc, 99999, $excludeIds ) ;
}
}
// Edit WHERE phraze
$where = " WHERE (NOT hide='1')" ;
if (count($includeIds) >= 1) {
$where .= " AND (" ;
$or = '';
foreach($includeIds as $id) {
$where .= $or . "gal_id='" . $id . "'" ;
$or = ' OR ' ;
}
$where .= ")" ;
}
if (count($excludeIds ) >= 1) {
$where .= " AND (" ;
$and = '';
foreach($excludeIds as $id) {
$where .= $and . "gal_id<>'" . $id . "'" ;
$and = ' AND ' ;
}
$where .= ")" ;
}
// Query table data
$sql = 'SELECT * FROM ' . $mgtable . $where . ' ORDER BY ' . $order . ' LIMIT ' . $limit . ';' ;
$res = $modx->db->query($sql);
// Get row count
$totalpics = $modx->db->getRecordCount($res);
if($totalpics>0){
while($pic=$modx->fetchRow($res)) {
// Get page data
$resourceID = $pic['gal_id'] ;
$resourceFields = $modx->getDocument($resourceID) ;
// Edit item data
if ($resourceFields) {
if ($pic['title'] != '') {
$title = $resourceFields['pagetitle'] . ' : ' .$pic['title'] ;
} else {
$title = $resourceFields['pagetitle'] ;
}
$title = strip_tags(stripslashes($title)) ;
$link = $modx->makeURL($resourceID, '', '', 'full') . '?pic=' . $pic['id'] ;
$guid = $link ;
date_default_timezone_set($timezone) ;
$pubDate = date("r",strtotime($pic['date'])) ;
if ($pic['descr'] != '') {
$mediadesc = $pic['descr'] ;
} else {
$mediadesc = 'Image of ' . $resourceFields['pagetitle'] ;
}
$mediadesc = stripslashes($mediadesc) ;
$mediaurl = $modx->config['site_url'] . 'assets/' . $mgfolder . '/' . $pic['gal_id'] . '/' ;
$mediapath = $modx->config['base_path'] . 'assets/' . $mgfolder . '/' . $pic['gal_id'] . '/' ;
$mediathumburl = $mediaurl . $mgthumbpre . $pic['filename'] ;
$mediacontenturl = $mediaurl . $pic['filename'] ;
if ($mgusebig === 'true') {
if (file_exists($mediapath . $mgbigpre . $pic['filename'])) {
$mediacontenturl = $mediaurl . $mgbigpre . $pic['filename'] ;
}
}
$description = '<img src="' . $mediacontenturl . '"/>' ;
// Set item data
$rss .= "\t" . '<item>' . "\n" ;
$rss .= "\t\t" . '<title><![CDATA[' . $title . ']]></title>' . "\n" ;
$rss .= "\t\t" . '<description><![CDATA[' . $description . ']]></description>' . "\n" ;
$rss .= "\t\t" . '<link>' . $link . '</link>' . "\n" ;
// $rss .= "\t\t" . '<guid isPermaLink="false"><![CDATA[' . $guid . ']]></guid>' . "\n" ;
$rss .= "\t\t" . '<guid>' . $guid . '</guid>' . "\n" ;
$rss .= "\t\t" . '<pubDate>' . $pubDate . '</pubDate>' . "\n" ;
$rss .= "\t\t" . '<media:description type="html"><![CDATA[' .$mediadesc . ']]></media:description>' . "\n" ;
$rss .= "\t\t" . '<media:thumbnail url="' . $mediathumburl . '" />' . "\n" ;
//$rss .= "\t\t" . '<media:content url="' . $mediacontenturl . '" type="image/jpg" />' . "\n" ;
$pathinfo = pathinfo($mediacontenturl);
$rss .= "\t\t" . '<media:content url="' . $mediacontenturl . '" type="image/' . $pathinfo['extension'] . '" />' . "\n" ;
$rss .= "\t" . '</item>' . "\n" ;
}
}
}
/******************************************************************************
* Edit footer
******************************************************************************/
$rss .= '</channel>' . "\n" ;
$rss .= '</rss>' ;
/******************************************************************************
// Write file
******************************************************************************/
if ($handle = fopen($modx->config['base_path'] . $rsspath, 'w')) {
fwrite($handle, $rss) ;
fclose($handle) ;
}
?>
3.スニペットのテスト
3.1 仮実装
既存リソースまたは新規に追加したリソースに以下のスニペットコールを追加して動作を確認します。MaxiGalleryの基本パラメータを特に変更していなければ、assets/cache/rss フォルダに mrss.rss ファイルが作成されるはずです。
- includeDocs引数に画像をアップしたリソースIDを少なくとも一つ指定
- スニペットはキャッシュ無し(“[!・・・!]“)で呼び出す ※繰り返し確認すると思うので・・・
- これはスニペット単体の動きを確認するための仮実装。RSSが正しく出力されたら呼び出し文を削除
3.2 RSSの妥当性検証
W3Cのフィードバリデータなどで、出力したRSSの妥当性を検証します。
後書き
今回は、実際の開発現場で行う作業手順を意識して、情報の収集・整理(リサーチ) > 概要設計 > 詳細設計 > コーディング > テスト という流れで解説しました。システム屋さんにはお馴染みの手順や用語も、プログラミング経験の少ない方には難解に感じる部分もあったと思います。次回は、今回作ったMediaRSSをCoolIrisに読ませて画像をスライド表示させます。結果が目に見えるので今回よりは多少面白いかもしれません。
GW明けのガッカリ/ゲッソリも一時のこと。またすぐ週末ですよ。 ^^















0 comments.