実践!MODxプログラミング(第2部 スニペットの作成)

関係する箇所

関係する箇所

今回はMaxiGalleryが管理する情報を基にMediaRSSファイルを生成するスニペットを解説していきます(オレンジの部分)。スニペット自作の細かい手順やコーディング規約などを紹介してから実際に手を動かして作ってもらった方が理解が深まると思いますが紙面の都合で割愛します。「こんなことができるのね」といった感じで見てもらえると嬉しいです。実際はMODxのリソーステーブルなども参照しますが、その辺はご愛嬌ということで・・・  :mrgreen:

1.データ仕様

1.1 MaxiGalleryのデータ構造

MaxiGalleryのMySQL内のテーブルと写真ファイル・フォルダの構成を図解します。ざっと説明すると、画像とテーブルのレコードが一対一で管理されており、gal_idが示すリソースごとにサブフォルダが作られ、各々の画像がその下に配置されます。下の例では、gal_id1,2,3それぞれに2つずつ画像をアップした格好です。

MaxiGalleryのデータ構成

MaxiGalleryのデータ構成

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ファイルに出力
スニペットコード
<?php
/*==============================================================================
  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が正しく出力されたら呼び出し文を削除
[!MaxiGalleryMediaRss? &includeDocs=`999`!]

3.2 RSSの妥当性検証

W3Cのフィードバリデータなどで、出力したRSSの妥当性を検証します。

後書き

今回は、実際の開発現場で行う作業手順を意識して、情報の収集・整理(リサーチ) > 概要設計 > 詳細設計 > コーディング > テスト という流れで解説しました。システム屋さんにはお馴染みの手順や用語も、プログラミング経験の少ない方には難解に感じる部分もあったと思います。次回は、今回作ったMediaRSSをCoolIrisに読ませて画像をスライド表示させます。結果が目に見えるので今回よりは多少面白いかもしれません。

GW明けのガッカリ/ゲッソリも一時のこと。またすぐ週末ですよ。 ^^

関連ページ

にほんブログ村 IT技術ブログ Webサイト構築へにほんブログ村 デザインブログ Webデザインへ

CMSを多くの人に知ってもらいたい。そんな気持ちで参加しています。


モノ・マガジン オンライン
コメント

0 comments.

コメントフォーム



[ Ctrl + Enter ]