7 * LICENSE: This source file is licensed under the terms of the GNU General Public License.
9 * @package Magic3 Framework
10 * @author 平田直毅(Naoki Hirata) <naoki@aplo.co.jp>
11 * @copyright Copyright 2006-2010 Magic3 Project.
12 * @license http://www.gnu.org/copyleft/gpl.html GPL License
13 * @version SVN: $Id: m_blogReadWidgetContainer.php 3836 2010-11-17 06:05:07Z fishbone $
14 * @link http://www.magic3.org
16 require_once($gEnvManager->getCurrentWidgetContainerPath() . '/m_blogBaseWidgetContainer.php');
18 class m_blogReadWidgetContainer extends m_blogBaseWidgetContainer
20 private $messageCount; // メッセージ数
21 private $isExistsMessage; // メッセージが存在するかどうか
22 private $isExistsNextPage; // 次のページがあるかどうか
23 private $pageTitle; // 画面タイトル、パンくずリスト用タイトル
24 const DEFAULT_SEARCH_COUNT = 5; // デフォルトの検索記事数
29 function __construct()
32 parent::__construct();
37 * _assign()でデータを埋め込むテンプレートファイルのファイル名を返す。
38 * 読み込むディレクトリは、「自ウィジェットディレクトリ/include/template」に固定。
40 * @param RequestManager $request HTTPリクエスト処理クラス
41 * @param object $param 任意使用パラメータ。そのまま_assign()に渡る
42 * @return string テンプレートファイル名。テンプレートライブラリを使用しない場合は空文字列「''」を返す。
44 function _setTemplate($request, &$param)
46 return 'thread_read.tmpl.html';
51 * _setTemplate()で指定したテンプレートファイルにデータを埋め込む。
53 * @param RequestManager $request HTTPリクエスト処理クラス
54 * @param object $param 任意使用パラメータ。_setTemplate()と共有。
57 function _assign($request, &$param)
60 $now = date("Y/m/d H:i:s"); // 現在日時
61 $this->currentDay = date("Y/m/d"); // 日
62 $this->currentHour = (int)date("H"); // 時間
63 $this->langId = $this->gEnv->getCurrentLanguage();
64 $this->pageTitle = ''; // 画面タイトル、パンくずリスト用タイトル
67 $entryViewCount = $this->_configArray[self::CF_ENTRY_VIEW_COUNT];// 記事表示数
68 if (empty($entryViewCount)) $entryViewCount = self::DEFAULT_VIEW_COUNT;
69 $entryViewOrder = $this->_configArray[self::CF_ENTRY_VIEW_ORDER];// 記事表示順
70 $titleColor = $this->_configArray[self::CF_TITLE_COLOR];// タイトル背景色
73 $act = $request->trimValueOf('act');
74 $pageNo = $request->trimIntValueOf(M3_REQUEST_PARAM_PAGE_NO, '1'); // ページ番号
75 if (empty($pageNo)) $pageNo = 1;
76 $entryId = $request->trimValueOf('entryid');
77 $startDt = $request->trimValueOf('start');
78 $endDt = $request->trimValueOf('end');
79 $year = $request->trimValueOf('year'); // 年指定
80 $month = $request->trimValueOf('month'); // 月指定
81 $day = $request->trimValueOf('day'); // 日指定
82 //$keyword = $request->trimValueOf('keyword');// 検索キーワード
83 $keyword = $request->mobileTrimValueOf('keyword');// 検索キーワード
84 $category = $request->trimValueOf(M3_REQUEST_PARAM_CATEGORY_ID); // カテゴリID
86 $showDefault = false; // デフォルト状態での表示
87 if ($act == 'search'){ // 検索
90 $message = '検索キーワードが入力されていません';
93 $searchCount = self::DEFAULT_SEARCH_COUNT; // 検索記事数
96 $this->gInstance->getAnalyzeManager()->logSearchWord($this->gEnv->getCurrentWidgetId(), $keyword);
102 // 全角英数を半角に、半角カナ全角ひらがなを全角カナに変換
103 $basicWord = $keyword;
104 if (function_exists('mb_convert_kana')) $basicWord = mb_convert_kana($basicWord, 'aKCV');
105 $basicWord = strtolower($basicWord); // 大文字を小文字に変換
108 $cid = $this->gAccess->getClientId();// クッキー値のクライアントID
109 //$this->db->writeKeywordLog($cid, $this->gEnv->getCurrentWidgetId(), $keyword, $basicWord);
113 $totalCount = $this->_db->searchEntryItemsCountByKeyword($now, $keyword, $this->langId);
116 $convKeyword = $request->convMobileText($keyword); // 検索キーワードを携帯用のコードへ変換
117 $pageLink = $this->createPageLink($pageNo, $totalCount, $searchCount, $this->_currentPageUrl . '&act=search&keyword=' . urlencode($convKeyword));
120 $this->_db->searchEntryItemsByKeyword($searchCount, $pageNo, $now, $keyword, $this->langId, array($this, 'searchItemsLoop'));
122 if ($this->isExistsViewData){
124 if (!empty($pageLink)){
125 $this->tmpl->setAttribute('page_link', 'visibility', 'visible'); // リンク表示
126 $this->tmpl->addVar("page_link", "page_link", $pageLink);
128 $message = self::MESSAGE_SEARCH_KEYWORD . $keyword;
129 } else { // 検索結果なしの場合
130 $this->tmpl->setAttribute('entrylist', 'visibility', 'hidden');
131 $message = self::MESSAGE_FIND_NO_ENTRY;
134 $this->setGuidanceMsg($message); // ユーザ向けメッセージ
135 $this->pageTitle = self::DEFAULT_TITLE_SEARCH; // 画面タイトル、パンくずリスト用タイトル
136 } else if ($act == 'view'){ // 記事を表示のとき
137 // コメントを受け付けるときは、コメント入力欄を表示
138 // ***** 記事を表示する前に呼び出す必要あり *****
139 /*if (!empty($receiveComment)){
140 $this->tmpl->setAttribute('entry_footer', 'visibility', 'visible'); // コメントへのリンク
142 if (!empty($category)){ // カテゴリー指定のとき
144 $totalCount = $this->_db->getEntryItemsCountByCategory($now, $category, $this->langId);
147 $pageLink = $this->createPageLink($pageNo, $totalCount, $entryViewCount, $this->_currentPageUrl . '&act=view&' . M3_REQUEST_PARAM_CATEGORY_ID . '=' . $category);
150 $this->_db->getEntryItemsByCategory($entryViewCount, $pageNo, $now, $category, $this->langId, $entryViewOrder, array($this, 'itemsLoop'));
153 $ret = $this->_db->getCategoryByCategoryId($category, $this->gEnv->getDefaultLanguage(), $row);
154 if ($ret) $title = $row['bc_name'];
156 // ブログ記事データがないときはデータなしメッセージ追加
157 if ($this->isExistsViewData){
159 if (!empty($pageLink)){
160 $this->tmpl->setAttribute('page_link', 'visibility', 'visible'); // リンク表示
161 $this->tmpl->addVar("page_link", "page_link", $pageLink);
164 $title = self::MESSAGE_NO_ENTRY_TITLE;
165 $this->setGuidanceMsg(self::MESSAGE_NO_ENTRY); // ユーザ向けメッセージ
167 } else if (!empty($year) && !empty($month)){
168 if (empty($day)){ // 月指定のとき
169 $startDt = $year . '/' . $month . '/1';
170 $endDt = $this->getNextMonth($year . '/' . $month) . '/1';
173 $totalCount = $this->_db->getEntryItemsCount($now, $startDt, $endDt, $this->langId);
176 $pageLink = $this->createPageLink($pageNo, $totalCount, $entryViewCount, $this->_currentPageUrl . '&act=view&year=' . $year . '&month=' . $month);
179 $this->_db->getEntryItems($entryViewCount, $pageNo, $now, $entryId, $startDt/*期間開始*/, $endDt/*期間終了*/, $this->langId, $entryViewOrder, array($this, 'itemsLoop'));
181 if ($this->isExistsViewData){
183 if (!empty($pageLink)){
184 $this->tmpl->setAttribute('page_link', 'visibility', 'visible'); // リンク表示
185 $this->tmpl->addVar("page_link", "page_link", $pageLink);
189 $title = $year . '年 ' . $month . '月';
191 // ブログ記事データがないときはデータなしメッセージ追加
192 if (!$this->isExistsViewData) $this->setGuidanceMsg(self::MESSAGE_NO_ENTRY); // ユーザ向けメッセージ
194 $startDt = $year . '/' . $month . '/' . $day;
195 $endDt = $this->getNextDay($year . '/' . $month . '/' . $day);
198 $totalCount = $this->_db->getEntryItemsCount($now, $startDt, $endDt, $this->langId);
201 $pageLink = $this->createPageLink($pageNo, $totalCount, $entryViewCount, $this->_currentPageUrl . '&act=view&year=' . $year . '&month=' . $month . '&day=' . $day);
204 $this->_db->getEntryItems($entryViewCount, $pageNo, $now, $entryId, $startDt/*期間開始*/, $endDt/*期間終了*/, $this->langId, $entryViewOrder, array($this, 'itemsLoop'));
206 if ($this->isExistsViewData){
208 if (!empty($pageLink)){
209 $this->tmpl->setAttribute('page_link', 'visibility', 'visible'); // リンク表示
210 $this->tmpl->addVar("page_link", "page_link", $pageLink);
215 $title = $year . '年 ' . $month . '月 ' . $day . '日';
217 // ブログ記事データがないときはデータなしメッセージ追加
218 if (!$this->isExistsViewData) $this->setGuidanceMsg(self::MESSAGE_NO_ENTRY); // ユーザ向けメッセージ
221 $this->pageTitle = $title; // カテゴリー名を画面タイトルにする
223 $showDefault = true; // デフォルト状態での表示
225 // ##### デフォルトの表示では、最新のn件の記事を表示または、記事ID指定で1つの記事を表示
227 // コメントを受け付けるときは、コメント入力欄を表示
228 if (!empty($receiveComment)){
229 if (empty($entryId)){
230 $this->tmpl->setAttribute('entry_footer', 'visibility', 'visible'); // コメントへのリンク
231 } else { // 記事ID指定の場合のみコメント入力可能
232 $this->isOutputComment = true;// コメントを出力するかどうか
234 $this->tmpl->setAttribute('show_comment', 'visibility', 'visible'); // 既存コメントを表示
235 $this->tmpl->addVar("_widget", "entry_id", $entryId); // 記事を指定
237 // ### コメント入力欄の表示 ###
238 $this->tmpl->setAttribute('add_comment', 'visibility', 'visible');
239 $this->tmpl->addVar("add_comment", "send_button_label", $sendButtonLabel);// 送信ボタンラベル
240 $this->tmpl->addVar("add_comment", "send_status", $sendStatus);// 送信状況
243 if (empty($entryId)){
245 $totalCount = $this->_db->getEntryItemsCount($now, $startDt, $endDt, $this->langId);
248 $pageLink = $this->createPageLink($pageNo, $totalCount, $entryViewCount, $this->_currentPageUrl);
251 $this->_db->getEntryItems($entryViewCount, $pageNo, $now, 0/* 期間で指定 */, $startDt/*期間開始*/, $endDt/*期間終了*/, $this->langId, $entryViewOrder, array($this, 'itemsLoop'));
253 if ($this->isExistsViewData){
255 if (!empty($pageLink)){
256 $this->tmpl->setAttribute('page_link', 'visibility', 'visible'); // リンク表示
257 $this->tmpl->addVar("page_link", "page_link", $pageLink);
261 $this->viewExtEntry = true; // 記事ID指定のときは続き(全文)を表示
262 $this->_db->getEntryItems($entryViewCount, $pageNo, $now, $entryId, $startDt/*期間開始*/, $endDt/*期間終了*/, $this->langId, $entryViewOrder, array($this, 'itemsLoop'));
265 if (!$this->isExistsViewData){
266 $this->tmpl->setAttribute('entrylist', 'visibility', 'hidden');
267 //$this->tmpl->setAttribute('add_comment', 'visibility', 'hidden');
272 // ブログ記事データがないときはデータなしメッセージ追加
273 if (!$this->isExistsViewData){
274 $title = self::MESSAGE_NO_ENTRY_TITLE;
275 $this->pageTitle = $title; // HTMLヘッダタイトル
276 $this->setGuidanceMsg(self::MESSAGE_NO_ENTRY); // ユーザ向けメッセージ
283 $titleStr = '<div align="center" style="text-align:center;';
284 if (!empty($titleColor)) $titleStr .= 'background-color:' . $titleColor . ';';// タイトル背景色
285 $titleStr .= '">' . $this->convertToDispString($title) . '</div>';
287 $this->tmpl->setAttribute('show_title', 'visibility', 'visible'); // 年月表示
288 $this->tmpl->addVar("show_title", "title", $titleStr);
292 $this->gPage->setHeadSubTitle($this->pageTitle);
295 * 取得したコンテンツ項目をテンプレートに設定する
297 * @param int $index 行番号
298 * @param array $fetchedRow 取得行
299 * @param object $param 任意使用パラメータ
300 * @return bool trueを返すとループ続行。falseを返すとその時点で終了。
302 function itemsLoop($index, $fetchedRow)
305 if (!$this->gEnv->isSystemManageUser()){ // システム運用者以上の場合はカウントしない
306 $this->gInstance->getAnalyzeManager()->updateContentViewCount(self::CONTENT_TYPE, $fetchedRow['be_serial'], $this->currentDay, $this->currentHour);
309 $entryId = $fetchedRow['be_id'];// 記事ID
310 $title = $fetchedRow['be_name'];// タイトル
311 $date = $fetchedRow['be_regist_dt'];// 日付
314 if (empty($this->pageTitle)) $this->pageTitle = $title; // 画面タイトル、パンくずリスト用タイトル
317 /*$commentCount = $this->commentDb->getCommentCountByEntryId($entryId, $this->langId); // コメント総数
318 if ($this->isOutputComment){// コメントを出力のとき
320 $ret = $this->commentDb->getCommentByEntryId($entryId, $this->langId, $row);
322 $this->tmpl->clearTemplate('commentlist');
323 for ($i = 0; $i < count($row); $i++){
324 $userName = $this->convertToDispString($row[$i]['bo_user_name']); // 投稿ユーザは入力値を使用
325 $url = $this->convertToDispString($row[$i]['bo_url']);
326 $commentInfo = $this->convertToDispString($row[$i]['bo_regist_dt']) . ' ' . $userName;
327 if (!empty($url)) $commentInfo .= '<br />' . $url;
328 $comment = $this->convertToPreviewText($this->convertToDispString($row[$i]['bo_html'])); // 改行コードをbrタグに変換
330 'comment_title' => $this->convertToDispString($row[$i]['bo_name']), // コメントタイトル
331 'comment' => $comment, // コメント内容
332 'user_name' => $userName, // 投稿ユーザ名
333 'comment_info' => $commentInfo // コメント情報
335 $this->tmpl->addVars('commentlist', $commentRow);
336 $this->tmpl->parseTemplate('commentlist', 'a');
338 } else { // コメントなしのとき
339 $this->tmpl->clearTemplate('commentlist');
341 'comment' => 'コメントはありません', // コメント内容
342 'comment_info' => '' // コメント情報
344 $this->tmpl->addVars('commentlist', $commentRow);
345 $this->tmpl->parseTemplate('commentlist', 'a');
350 $linkUrl = $this->getUrl($this->gEnv->getDefaultMobileUrl() . '?'. M3_REQUEST_PARAM_BLOG_ENTRY_ID . '=' . $entryId, true/*リンク用*/);
351 $link = '<a href="' . $this->convertUrlToHtmlEntity($linkUrl) . '" >コメント(' . $commentCount . ')</a>';
353 // HTMLを出力(出力内容は特にエラーチェックしない)
354 $entryText = $fetchedRow['be_html'];
355 if ($this->viewExtEntry){ // 続きを表示するかどうか
356 if (!empty($fetchedRow['be_html_ext'])) $entryText = $fetchedRow['be_html_ext'];// 続きがある場合は続きを出力
357 $entryText = str_replace(M3_TAG_START . M3_TAG_MACRO_ROOT_URL . M3_TAG_END, $this->getUrl($this->gEnv->getRootUrl()), $entryText);// アプリケーションルートを変換
360 $entryText = str_replace(M3_TAG_START . M3_TAG_MACRO_ROOT_URL . M3_TAG_END, $this->getUrl($this->gEnv->getRootUrl()), $entryText);// アプリケーションルートを変換
361 if (!empty($fetchedRow['be_html_ext'])){
362 $entryText .= self::MESSAGE_EXT_ENTRY_PRE . '<a href="' . $this->convertUrlToHtmlEntity($linkUrl) . '" >' . self::MESSAGE_EXT_ENTRY . '</a>';
366 $entryText = $this->gInstance->getTextConvManager()->autoConvPcContentToMobile($entryText, $this->currentRootUrl/*現在のページのルートURL*/,
367 M3_VIEW_TYPE_BLOG/*ブログコンテンツ*/, $fetchedRow['be_create_dt']/*コンテンツ作成日時*/);
370 $this->tmpl->clearTemplate('entry_footer');
372 'permalink' => $this->convertUrlToHtmlEntity($linkUrl), // パーマリンク
373 'link' => $link // コメントへのリンク
375 $this->tmpl->addVars('entry_footer', $row);
376 $this->tmpl->parseTemplate('entry_footer', 'a');
379 'permalink' => $this->convertUrlToHtmlEntity($linkUrl), // パーマリンク
381 'date' => $date, // 日付
382 'entry' => $entryText // 投稿記事
384 $this->tmpl->addVars('entrylist', $row);
385 $this->tmpl->parseTemplate('entrylist', 'a');
386 $this->isExistsViewData = true; // 表示データがあるかどうか
390 * 取得したコンテンツ項目をテンプレートに設定する
392 * @param int $index 行番号
393 * @param array $fetchedRow 取得行
394 * @param object $param 任意使用パラメータ
395 * @return bool trueを返すとループ続行。falseを返すとその時点で終了。
397 function searchItemsLoop($index, $fetchedRow)
399 $entryId = $fetchedRow['be_id'];// 記事ID
400 $title = $fetchedRow['be_name'];// タイトル
401 $date = $fetchedRow['be_regist_dt'];// 日付
404 $linkUrl = $this->getUrl($this->gEnv->getDefaultMobileUrl() . '?'. M3_REQUEST_PARAM_BLOG_ENTRY_ID . '=' . $entryId, true/*リンク用*/);
405 $link = '<a href="' . $this->convertUrlToHtmlEntity($linkUrl) . '" >' . $title . '</a>';
408 $entryText = $this->gInstance->getTextConvManager()->htmlToText($fetchedRow['be_html']);
410 // 検索結果用にテキストを詰める。改行、タブ、スペース削除。
411 $entryText = str_replace(array("\r", "\n", "\t", " "), '', $entryText);
414 if (function_exists('mb_strimwidth')){
415 $entryText = mb_strimwidth($entryText, 0, self::SEARCH_BODY_SIZE, '…');
417 $entryText = substr($entryText, 0, self::SEARCH_BODY_SIZE) . '...';
421 'title' => $link, // リンク付きタイトル
422 'date' => $date, // 日付
423 'entry' => $entryText // 投稿記事
425 $this->tmpl->addVars('entrylist', $row);
426 $this->tmpl->parseTemplate('entrylist', 'a');
427 $this->isExistsViewData = true; // 表示データがあるかどうか
433 * @param int $pageNo ページ番号(1~)。ページ番号が範囲外にある場合は自動的に調整
434 * @param int $totalCount 総項目数
435 * @param int $viewItemCount 1ページあたりの項目数
436 * @param string $baseUrl リンク用のベースURL
437 * @return string リンクHTML
439 function createPageLink(&$pageNo, $totalCount, $viewItemCount, $baseUrl)
442 $pageCount = (int)(($totalCount -1) / $viewItemCount) + 1; // 総ページ数
443 if ($pageNo < 1) $pageNo = 1;
444 if ($pageNo > $pageCount) $pageNo = $pageCount;
448 if ($pageCount > 1){ // ページが2ページ以上のときリンクを作成
449 // ページ数1から「LINK_PAGE_COUNT」までのリンクを作成
450 $maxPageCount = $pageCount < self::LINK_PAGE_COUNT ? $pageCount : self::LINK_PAGE_COUNT;
451 for ($i = 1; $i <= $maxPageCount; $i++){
453 $link = ' ' . $i;
455 $linkUrl = $this->getUrl($baseUrl . '&page=' . $i, true/*リンク用*/);
456 $link = ' <a href="' . $this->convertUrlToHtmlEntity($linkUrl) . '" >' . $i . '</a>';
461 if ($pageCount > self::LINK_PAGE_COUNT) $pageLink .= ' ...';
463 if ($pageNo > 1){ // 前ページがあるとき
464 $linkUrl = $this->getUrl($baseUrl . '&page=' . ($pageNo -1), true/*リンク用*/);
465 $link = '<a href="' . $this->convertUrlToHtmlEntity($linkUrl) . '" accesskey="1">前へ[1]</a>';
466 $pageLink = $link . $pageLink;
468 if ($pageNo < $pageCount){ // 次ページがあるとき
469 $linkUrl = $this->getUrl($baseUrl . '&page=' . ($pageNo +1), true/*リンク用*/);
470 $link = ' <a href="' . $this->convertUrlToHtmlEntity($linkUrl) . '" accesskey="2">次へ[2]</a>';