2006年2月10日 星期五

兩層式的文章月份彙整

在論壇裡,有網友 hsuzy 問到如何修改樣版讓文章的月份彙整加上一層年份的分類?(請看討論串)我研究了一下,在現行的 LT 架構下,沒辦法像"我的連結部份"直接由樣版變數實作,必需要修改程式或另做 pluign 處理。當然,也可以用 smarty 的樣版語言"蠻幹"做出來。請原諒我用這兩個字,如果你不同意的話,其實 hsuzy 兄確實用 smarty 的樣版語言實作出來了。但是在我認為,用樣版語言做程式該處理的事情,終非正途。

修改程式來完成這個要求,我實作出來了,但是,除非未來 LT 官方改用相同的方式來實作,否則,這只能用來玩玩而已,因為後續的維護成本不值得這樣做(後面再說明)。

還是先看看做出來的樣子吧(以我使用的 almost-spring 模版為例):

使用年份做第二層的文章分月彙整

若有興趣玩玩看,請往下看…

原始的分月彙整

模版裡的 $archives 物件是個 ArchiveLink 物件的一維陣列,每個 ArchiveLink 物件可以取得該月文章彙整頁的連結( $link->getUrl() )、連結名稱( $link->getName() )及該月的文章數( $link->getNumArticles() )。而其中的連結名稱預設使用"二月2006"這種格式 ( "%B%Y" )。

要求

要達成 hsuzy 的要求,要做到兩件事:

  1. 將連結名稱的格式改為只使用月份 ( %B ) 。
  2. 將模版裡的 $archives 物件依年份再做分類,可以實作成二維陣列,像下面這樣:

$archives[$yearName][] = $monthLink

$yearName 為年的名稱,$monthLink 則為某月的 ArchiveLink 物件。

實作程式修改

模版裡的 $archives 物件是由 class/view/blogview.class.php 裡面的 blogview::_getArchives() 函式提供的,只要修改這個函式就行了,如下:

function _getArchives()
{
$archiveStats = $this->articles->getNumberPostsPerMonth( $this->_blogInfo->getId());

if( $archiveStats == '' )
return false;

$years = Array(); // 要傳給模版 $archives
$locale = $this->_blogInfo->getLocale();
$urls = $this->_blogInfo->getBlogRequestGenerator();

// format of dates used in the archive, but it defaults to '%B %Y' if none specified
// 這裡原本使用 $archiveDateFormat ,預設為 '%B%Y' 格式,改成將月份和年份的格式分開
$archiveYearFormat = $locale->tr( 'archive_year_format' );
$archiveMonthFormat = $locale->tr( 'archive_month_format' );

// need to check whether we got the same thing back, since that's the way Locale::tr() works instead of
// returning an empty string
// 原本定義的常數為 ARCHIVE_DEFAULT_DATE_FORMAT ,同樣改成兩個,成為未來官方功能,應該會被定義在別處。
if (!defined( 'ARCHIVE_DEFAULT_YEAR_FORMAT' ) ) define('ARCHIVE_DEFAULT_YEAR_FORMAT','%Y');
if (!defined( 'ARCHIVE_DEFAULT_MONTH_FORMAT' ) ) define('ARCHIVE_DEFAULT_MONTH_FORMAT','%B');
if( $archiveYearFormat == "archive_year_format" ) $archiveYearFormat = ARCHIVE_DEFAULT_YEAR_FORMAT;
if( $archiveMonthFormat == "archive_month_format" ) $archiveMonthFormat = ARCHIVE_DEFAULT_MONTH_FORMAT;


foreach( $archiveStats as $yearName => $year) {
$links = array(); // 搜集某月的 ArchiveLink 物件
foreach( $year as $monthName => $month ) {
// we can use the Timestamp class to help us with this...
$t = new Timestamp();
$t->setYear( $yearName );
$t->setMonth( $monthName );
$archiveUrl = $urls->getArchiveLink( $t->getYear().$t->getMonth());
$monthName = $locale->formatDate( $t, $archiveMonthFormat ); // 改成只用月份做連結名稱
$link = new ArchiveLink( $monthName, '', $archiveUrl, $this->_blogInfo->getId(), 0, $month, 0);
$links[] = $link;
}
$yearName = $locale->formatDate( $t, $archiveYearFormat ); // 使用年份名稱做為陣列的索引值,供樣版使用
$years [$yearName] = $links;
unset ( $links );
}
return $years;
}

模版配合修改

因為模版裡的 $archives 物件變成二維陣列了,模版當然要配合修改才能用。以我使用的 almost-spring 模版為例,將 panel.template 裡面的 archive 區塊修改如下:

<ul>
{foreach from=$archives item=year key=yearname }
<li>
{$yearname}
<ul><li>
{foreach from= $year item=month}
<a xhref="{$month->getUrl()}">{$month->getName()}[{$month->getNumArticles()}]</a>
{/foreach}
</li></ul>
</li>
{/foreach}
</ul>

第一次的 foreach 多了一個 key=yearname ,在取得 $year 物件的同時,也取得陣列的索引值,也就是年份名稱。而這裡的 $year 物件,就跟原來的 $archives 物件相同了,剩下的就不必多做解釋了。

真的只能玩玩而已

除非你真的考慮的很清楚了,千萬不要在你提供服務的 LT 站上使用 。為什麼?

  1. 一旦使用了這個 hack ,你要替網站上的 所有系統模版都做相對的修改 ,否則就會有用戶向你抱怨畫面出錯;另外,還得 通知所有使用自訂模版的用戶也要修改模版
  2. 除非未來 LT 官方將文章彙整改成這種樣式,否則未來升級時,就必需自行重新修改這個 hack 。就算官方真的加入這項修改,也未必用相同的方法實作,樣版還是得再改一次。

所以,除非你真的願意付出相當的維護成本來達成這項功能,否則還是玩玩就好。若真的有很多人有興趣,我再試試回報到 LT 官方,看看能不能有機會加入 LT 1.1 吧!

沒有留言:

張貼留言