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-2013 Magic3 Project.
12 * @license http://www.gnu.org/copyleft/gpl.html GPL License
13 * @version SVN: $Id: commentTopWidgetContainer.php 6155 2013-07-02 00:02:49Z fishbone $
14 * @link http://www.magic3.org
16 require_once($gEnvManager->getWidgetContainerPath('comment') . '/commentBaseWidgetContainer.php');
18 class commentTopWidgetContainer extends commentBaseWidgetContainer
20 private $message; // ユーザ向けメッセージ
21 private $pageNo; // ページ番号
22 private $cmd; // 実行コマンド
23 private $commentSerialNo; // コメントシリアル番号
24 private $isReadImageCheck; // 画像読み込みチェックかどうか
25 private $isErrorInReadImage; // 画像読み込み中にエラーがあるかどうか
26 private $currentPageUrl; // 現在のページURL
27 private $currentPageRootUrl;
28 private $widgetTitle; // ウィジェットタイトル
29 private $userLimited; // ユーザ制限あり
30 private $commentVisible; // コメントを表示する
31 private $commentAccept; // コメントを受け付ける
32 private $isExistsComment; // 表示するコメントがあるかどうか
33 private $useTitle; // コメント入力項目(タイトルあり)
34 private $useAuthor; // コメント入力項目(投稿者名あり)
35 private $useEmail; // コメント入力項目(Eメールあり)
36 private $useUrl; // コメント入力項目(URLあり)
37 private $useAvatar; // コメント入力項目(アバターあり)
38 private $permitHtml; // HTMLあり
39 private $permitImage; // 画像あり
40 private $autolink; // 自動リンク
41 private $addLib = array(); // 追加スクリプト
42 private $avatarSize; // アバター画像サイズ
43 private $maxImageSize; // 画像最大サイズ
44 private $imageDir; // 画像格納ディレクトリ
45 private $imageFileInfoArray; // 画像ファイル情報
46 const COMMENT_ID_SEPARATOR = ':'; // コメントID作成用セパレータ
47 const DEFAULT_TITLE = 'コメント'; // デフォルトのウィジェットタイトル名
48 const LINK_PAGE_COUNT = 5; // リンクページ数
50 const MESSAGE_NOT_PERMITTED_REFER = '閲覧は許可されていません'; // コメント閲覧権限がない場合
51 const MESSAGE_NOT_PERMITTED_POST = '投稿は許可されていません'; // コメント投稿権限がない場合
52 const MESSAGE_NO_COMMENT = 'コメントは投稿されていません'; // コメントが投稿されていないメッセージ
53 const NO_COMMENT_TITLE = 'タイトルなし'; // 未設定時のコメントタイトル
54 const NO_COMMENT_AUTHOR = '投稿者名なし'; // 未設定時のコメント投稿者名
55 const COMMENT_TITLE_FORMAT = '「%s」についてのコメント'; // コメント用タイトルフォーマット
56 const AVATAR_TITLE_TAIL = 'のアバター';
57 const COOKIE_LIB = 'jquery.cookie'; // 名前保存用クッキーライブラリ
58 const PERMALINK_ICON_FILE = '/images/system/permalink.png'; // 「パーマリンク」アイコン
59 const PERMA_BUTTON_ICON_SIZE = 16; // ボタン用アイコンサイズ
64 function __construct()
67 parent::__construct();
69 $this->imageDir = $this->gEnv->getIncludePath() . commentCommonDef::UPLOAD_IMAGE_DIR; // 画像格納ディレクトリ
70 if (!is_dir($this->imageDir)) @mkdir($this->imageDir, M3_SYSTEM_DIR_PERMISSION);
75 * _assign()でデータを埋め込むテンプレートファイルのファイル名を返す。
76 * 読み込むディレクトリは、「自ウィジェットディレクトリ/include/template」に固定。
78 * @param RequestManager $request HTTPリクエスト処理クラス
79 * @param object $param 任意使用パラメータ。そのまま_assign()に渡る
80 * @return string テンプレートファイル名。テンプレートライブラリを使用しない場合は空文字列「''」を返す。
82 function _setTemplate($request, &$param)
84 return 'main.tmpl.html';
89 * _setTemplate()で指定したテンプレートファイルにデータを埋め込む。
91 * @param RequestManager $request HTTPリクエスト処理クラス
92 * @param object $param 任意使用パラメータ。_setTemplate()と共有。
95 function _assign($request, &$param)
97 $contentsId = ''; // 共通コンテンツID
98 $this->cmd = $request->trimValueOf(M3_REQUEST_PARAM_OPERATION_COMMAND);
99 if ($this->cmd == M3_REQUEST_CMD_DO_WIDGET){ // ウィジェット単体実行
100 // 画像IDからコメントシリアル番号取得
101 // コメントに添付されている場合はコメントの表示条件をチェック
102 $imageId = $request->trimValueOf(commentCommonDef::REQUEST_PARAM_IMAGE_ID); // 画像ID
103 $ret = $this->gInstance->getFileManager()->getAttachFileInfoByFileId(commentCommonDef::$_viewContentType, $imageId, $attachFileRow, false/*登録状態区別せず*/);
105 // コメントのアクセス可能状況をチェック
106 $this->commentSerialNo = $attachFileRow[af_content_id]; // コメントシリアル番号
107 if (empty($this->commentSerialNo)){ // コメントに未添付の画像の場合
108 // クライアントIDが同じであればダウンロード可能
109 $clientId = $this->gAccess->getClientId();
110 if (!empty($clientId) && $clientId == $attachFileRow[af_client_id]){
111 $this->downloadImage($request); // 画像取得
114 $ret = self::$_mainDb->getCommentItem($this->commentSerialNo, $row);
115 if ($ret && !$row['cm_deleted'] && $row['cm_status'] == 2/*コメント公開中*/){
116 $this->contentType = $row['cm_content_type']; // コンテンツタイプ
117 $contentsId = $row['cm_contents_id']; // 共通コンテンツID
122 $this->contentType = $this->gPage->getContentType();
124 switch ($this->contentType){
125 case M3_VIEW_TYPE_CONTENT: // 汎用コンテンツ
126 $contentsId = $request->trimValueOf(M3_REQUEST_PARAM_CONTENT_ID);
127 if (empty($contentsId)) $contentsId = $request->trimValueOf(M3_REQUEST_PARAM_CONTENT_ID_SHORT);
129 case M3_VIEW_TYPE_PRODUCT: // 商品情報(Eコマース)
130 $contentsId = $request->trimValueOf(M3_REQUEST_PARAM_PRODUCT_ID);
131 if (empty($contentsId)) $contentsId = $request->trimValueOf(M3_REQUEST_PARAM_PRODUCT_ID_SHORT);
133 case M3_VIEW_TYPE_BBS: // BBS
134 $contentsId = $request->trimValueOf(M3_REQUEST_PARAM_BBS_THREAD_ID);
135 if (empty($contentsId)) $contentsId = $request->trimValueOf(M3_REQUEST_PARAM_BBS_THREAD_ID_SHORT);
137 case M3_VIEW_TYPE_BLOG: // ブログ
138 $contentsId = $request->trimValueOf(M3_REQUEST_PARAM_BLOG_ENTRY_ID);
139 if (empty($contentsId)) $contentsId = $request->trimValueOf(M3_REQUEST_PARAM_BLOG_ENTRY_ID_SHORT);
141 case M3_VIEW_TYPE_WIKI: // wiki
142 $contentsId = $request->getWikiPageFromQuery(); // 「=」なしのパラメータはwikiパラメータとする
144 case M3_VIEW_TYPE_USER: // ユーザ作成コンテンツ
145 $contentsId = $request->trimValueOf(M3_REQUEST_PARAM_ROOM_ID);
146 if (empty($contentsId)) $contentsId = $request->trimValueOf(M3_REQUEST_PARAM_ROOM_ID_SHORT);
148 case M3_VIEW_TYPE_EVENT: // イベント情報
149 $contentsId = $request->trimValueOf(M3_REQUEST_PARAM_EVENT_ID);
150 if (empty($contentsId)) $contentsId = $request->trimValueOf(M3_REQUEST_PARAM_EVENT_ID_SHORT);
152 case M3_VIEW_TYPE_PHOTO: // フォトギャラリー
153 $contentsId = $request->trimValueOf(M3_REQUEST_PARAM_PHOTO_ID);
154 if (empty($contentsId)) $contentsId = $request->trimValueOf(M3_REQUEST_PARAM_PHOTO_ID_SHORT);
159 // 共通コンテンツIDがない場合は非表示にする
160 if (empty($contentsId)){
161 //$this->cancelParse(); // テンプレート変換処理中断
162 $this->exitWidget(); // ウィジェット終了処理
167 $ret = self::$_mainDb->getConfig($this->contentType, ''/*全体の定義*/, $row);
169 $viewType = $row[commentCommonDef::FD_VIEW_TYPE]; // コメントタイプ(0=フラット、1=ツリー)
170 $viewCount = $row[commentCommonDef::FD_MAX_COUNT]; // 表示項目数
171 $viewDirection = $row[commentCommonDef::FD_VIEW_DIRECTION]; // 表示順
172 $this->commentVisible = $row[commentCommonDef::FD_VISIBLE]; // コメントを表示する
173 $commentVisibleDefault = $row[commentCommonDef::FD_VISIBLE_D]; // コメントを表示する(個別デフォルト)
174 $this->commentAccept = $row[commentCommonDef::FD_ACCEPT_POST]; // コメントを受け付ける
175 $commentAcceptDefault = $row[commentCommonDef::FD_ACCEPT_POST_D]; // コメントを受け付ける(個別デフォルト)
176 $this->userLimited = $row[commentCommonDef::FD_USER_LIMITED]; // ユーザ制限あり
177 $needAuthorize = $row[commentCommonDef::FD_NEED_AUTHORIZE]; // 認証が必要かどうか
178 $this->permitHtml = $row[commentCommonDef::FD_PERMIT_HTML]; // HTMLあり
179 $this->permitImage = $row[commentCommonDef::FD_PERMIT_IMAGE]; // 画像あり
180 $this->autolink = $row[commentCommonDef::FD_AUTOLINK]; // 自動リンク
181 $maxLength = $row[commentCommonDef::FD_MAX_LENGTH]; // 文字数
182 $this->maxImageSize = $row[commentCommonDef::FD_MAX_IMAGE_SIZE]; // 画像最大サイズ
183 $this->useTitle = $row[commentCommonDef::FD_USE_TITLE]; // タイトルあり
184 $this->useAuthor = $row[commentCommonDef::FD_USE_AUTHOR]; // 投稿者名あり
185 $this->useEmail = $row[commentCommonDef::FD_USE_EMAIL]; // Eメールあり
186 $this->useUrl = $row[commentCommonDef::FD_USE_URL]; // URLあり
187 $this->useAvatar = $row[commentCommonDef::FD_USE_AVATAR]; // アバターあり
188 } else { // 定義が取得できないとき
189 //$this->cancelParse(); // テンプレート変換処理中断
190 $this->exitWidget(); // ウィジェット終了処理
195 $ret = self::$_mainDb->getConfig($this->contentType, $contentsId, $row);
197 if ($this->commentVisible) $this->commentVisible = $row[commentCommonDef::FD_VISIBLE]; // コメントを表示する
198 if ($this->commentAccept) $this->commentAccept = $row[commentCommonDef::FD_ACCEPT_POST]; // コメントを受け付ける
199 } else { // 個別の定義がない場合はデフォルトを取得
200 if ($this->commentVisible) $this->commentVisible = $commentVisibleDefault; // コメントを表示する
201 if ($this->commentAccept) $this->commentAccept = $commentAcceptDefault; // コメントを受け付ける
204 if (!$this->commentVisible){
205 //$this->cancelParse(); // テンプレート変換処理中断
206 $this->exitWidget(); // ウィジェット終了処理
210 $this->currentPageUrl = $this->gEnv->createCurrentPageUrl();// 現在のページURL
211 $this->currentPageRootUrl = $this->gEnv->getRootUrlByCurrentPage();
212 $sendButtonLabel = '投稿'; // 送信ボタンラベル
213 $sendStatus = 0; // 送信状況
214 $avatarFormat = $this->gInstance->getImageManager()->getDefaultAvatarFormat(); // 画像フォーマット取得
215 $this->gInstance->getImageManager()->parseImageFormat($avatarFormat, $imageType, $imageAttr, $this->avatarSize); // 画像情報取得
218 $act = $request->trimValueOf('act');
219 $pageNo = $request->trimIntValueOf('page', '1'); // ページ番号
220 if ($this->useTitle){
221 $title = $request->trimValueOf('title');
225 if ($this->useAuthor){
226 $author = $request->trimValueOf('author'); // 投稿者名
229 $userName = $this->gEnv->getCurrentUserName();
230 if (!empty($userName)) $author = $userName;
234 if ($this->useEmail){
235 $email = $request->trimValueOf('email');
237 // ログイン中はログインユーザのEメールを取得
238 $userEmail = $this->gEnv->getCurrentUserEmail();
239 if (!empty($userEmail)) $email = $userEmail;
244 $url = $request->trimValueOf('url');
248 $comment = $request->trimValueOf('comment');
249 if ($this->permitHtml){ // HTML送信の場合はBBCodeをHTMLに変換
250 $commentHtml = $this->parseComment($comment);
252 $sendStatus = intval($request->trimValueOf('sendstatus')); // 送信ステータス
253 if ($sendStatus < 0 || 1 < $sendStatus) $sendStatus = 0;
254 $postTicket = $request->trimValueOf('ticket'); // POST確認用
257 $isCommentValid = false;
258 $commentId = $request->trimValueOf('commentid'); // コメントID
259 if (!empty($commentId) && $commentId = md5($this->contentType . self::COMMENT_ID_SEPARATOR . $contentsId)) $isCommentValid = true;
261 $isInit = false; // 初期表示かどうか
262 if ($this->cmd == M3_REQUEST_CMD_DO_WIDGET){ // ウィジェット単体実行
263 if (!$this->userLimited || ($this->userLimited && $this->gEnv->isCurrentUserLogined())){ // ユーザ制限なし、または、ユーザ制限ありでログイン済みの場合
264 $this->downloadImage($request); // 画像取得
266 $this->exitWidget(); // ウィジェット終了処理
268 } else if ($act == 'checkcomment' && $sendStatus == 0){ // コメント確認のとき
269 if (!empty($postTicket) && $postTicket == $request->getSessionValue(M3_SESSION_POST_TICKET) && $isCommentValid){ // 正常なPOST値のとき
271 if ($this->useAuthor){
272 $this->checkInput($author, '投稿者');
274 if (empty($maxLength)){ // 空のときは長さのチェックなし
275 $this->checkInput($comment, 'コメント内容');
277 $this->checkLength($comment, 'コメント内容', $maxLength);
279 if ($this->useEmail) $this->checkMailAddress($email, 'Eメール', true);
281 // ##### 画像ありの場合は画像を取り込む #####
282 if ($this->permitHtml && $this->permitImage){
284 $commentHtml = $this->convertImageUrl($commentHtml);
285 if ($this->isErrorInReadImage){
286 $this->setUserErrorMsg('画像読み込みに失敗しました');
292 if ($this->getMsgCount() == 0){
293 $this->setGuidanceMsg('この内容でコメントを投稿しますか?');
296 $sendButtonLabel = '投稿'; // 送信ボタンラベル
297 $sendStatus = 1;// 送信状況を「確定」に変更
300 $postTicket = md5(time() . $this->gAccess->getAccessLogSerialNo());
301 $request->setSessionValue(M3_SESSION_POST_TICKET, $postTicket); // セッションに保存
302 } else { // ハッシュキーが異常のとき
306 $request->unsetSessionValue(M3_SESSION_POST_TICKET); // セッション値をクリア
308 } else if ($act == 'sendcomment' && $sendStatus == 1){ // コメント受信のとき
309 if (!empty($postTicket) && $postTicket == $request->getSessionValue(M3_SESSION_POST_TICKET) && $isCommentValid){ // 正常なPOST値のとき
311 if ($this->useAuthor){
312 $this->checkInput($author, '投稿者');
314 if (empty($maxLength)){ // 空のときは長さのチェックなし
315 $this->checkInput($comment, 'コメント内容');
317 $this->checkLength($comment, 'コメント内容', $maxLength);
319 if ($this->useEmail) $this->checkMailAddress($email, 'Eメール', true);
321 // ##### 画像ありの場合は画像を取り込む #####
322 if ($this->permitHtml && $this->permitImage){
324 $this->imageFileInfoArray = array();
325 $clientId = $this->gAccess->getClientId();
326 if (!empty($clientId)){
327 $ret = $this->gInstance->getFileManager()->getAttachFileInfoByClientId(commentCommonDef::$_viewContentType, $clientId, $imageFileRows);
329 for ($i = 0; $i < count($imageFileRows); $i++){
330 $fileRow = $imageFileRows[$i];
331 $newInfoObj = new stdClass;
332 $newInfoObj->title = '';
333 $newInfoObj->filename = '';
334 $newInfoObj->fileId = $fileRow['af_file_id'];
335 $newInfoObj->originalUrl = $fileRow['af_original_url']; // 取得先URL
336 $this->imageFileInfoArray[] = $newInfoObj;
342 $this->isReadImageCheck = true; // 画像読み込みチェック
343 $commentHtml = $this->convertImageUrl($commentHtml);
344 if ($this->isErrorInReadImage){
345 $this->setUserErrorMsg('画像読み込みに失敗しました');
350 if ($this->getMsgCount() == 0){
352 if (!empty($comment) &&
353 !empty($postTicket) && $postTicket == $request->getSessionValue(M3_SESSION_POST_TICKET)){ // 正常なPOST値のとき
355 $commentStatus = 0; // 未設定
356 if (!$needAuthorize) $commentStatus = 2; // 認証が必要でない場合は自動的に公開
359 $addType = 0; // フラット(最後に追加)
360 if ($this->permitHtml){ // HTML送信の場合はBBCodeをHTMLに変換
361 $ret = self::$_mainDb->addComment($addType, $this->contentType, $this->_langId, $contentsId, commentCommonDef::$_deviceType, 0/*親コメントシリアル*/,
362 $title, $commentHtml, $url, $author, $email, $commentStatus, $newSerial);
364 $ret = self::$_mainDb->addComment($addType, $this->contentType, $this->_langId, $contentsId, commentCommonDef::$_deviceType, 0/*親コメントシリアル*/,
365 $title, $comment, $url, $author, $email, $commentStatus, $newSerial);
368 // ##### 添付ファイル情報を更新 #####
370 $ret = $this->gInstance->getFileManager()->updateAttachFileInfo(commentCommonDef::$_viewContentType, $newSerial, 0, $newSerial,
371 $this->imageFileInfoArray, $this->imageDir);
375 $this->setGuidanceMsg('コメントを投稿しました');
389 $postTicket = md5(time() . $this->gAccess->getAccessLogSerialNo());
390 $request->setSessionValue(M3_SESSION_POST_TICKET, $postTicket); // セッションに保存
392 $this->setUserErrorMsg('コメントの投稿に失敗しました');
397 $request->unsetSessionValue(M3_SESSION_POST_TICKET); // セッション値をクリア
399 } else { // 送信時入力エラーの場合は初期画面に戻す
404 $postTicket = md5(time() . $this->gAccess->getAccessLogSerialNo());
405 $request->setSessionValue(M3_SESSION_POST_TICKET, $postTicket); // セッションに保存
407 } else { // ハッシュキーが異常のとき
411 $request->unsetSessionValue(M3_SESSION_POST_TICKET); // セッション値をクリア
413 } else if ($act == 'sendcancel' && $sendStatus == 1){ // コメントキャンセルのとき
414 if (!empty($postTicket) && $postTicket == $request->getSessionValue(M3_SESSION_POST_TICKET) && $isCommentValid){ // 正常なPOST値のとき
415 $this->setGuidanceMsg('コメントをキャンセルしました');
421 $postTicket = md5(time() . $this->gAccess->getAccessLogSerialNo());
422 $request->setSessionValue(M3_SESSION_POST_TICKET, $postTicket); // セッションに保存
423 } else { // ハッシュキーが異常のとき
427 $request->unsetSessionValue(M3_SESSION_POST_TICKET); // セッション値をクリア
430 $isInit = true; // 初期表示かどうか
436 $postTicket = md5(time() . $this->gAccess->getAccessLogSerialNo());
437 $request->setSessionValue(M3_SESSION_POST_TICKET, $postTicket); // セッションに保存
439 // ##### 初期表示時は仮登録の添付ファイルを削除 #####
440 $this->gInstance->getFileManager()->cleanAttachFileInfo(commentCommonDef::$_viewContentType, $this->imageDir);
444 $this->widgetTitle = $this->createTitle($this->contentType, $contentsId);
446 // ##### コメントを表示 #####
447 $showComment = false; // コメント表示するかどうか
448 if (!$this->userLimited || ($this->userLimited && $this->gEnv->isCurrentUserLogined())){ // ユーザ制限なし、または、ユーザ制限ありでログイン済みの場合
449 if ($sendStatus == 0){ // 初期表示の場合はすべてのコメントを表示
450 //$this->tmpl->setAttribute('show_comment_list', 'visibility', 'visible'); // 既存コメントを表示
452 if ($viewType == 1) $this->tmpl->setAttribute('show_reply', 'visibility', 'visible'); // 「返信」ボタン表示
453 if ($this->useTitle) $this->tmpl->setAttribute('show_title', 'visibility', 'visible'); // タイトル
454 if ($this->useAvatar) $this->tmpl->setAttribute('show_avatar', 'visibility', 'visible'); // アバター
457 $totalCount = self::$_mainDb->getCommentCount($this->contentType, $this->_langId, $contentsId, true/*公開コメントのみ*/);
458 $pageLink = $this->createPageLink($pageNo, $totalCount, $viewCount, $this->currentPageUrl);
461 self::$_mainDb->getComment($this->contentType, $this->_langId, $contentsId, $viewCount, $pageNo, $viewDirection, array($this, 'itemsLoop'));
464 //if (!$this->isExistsComment) $this->tmpl->setAttribute('comment_list', 'visibility', 'hidden');
465 if ($this->isExistsComment) $this->tmpl->setAttribute('show_comment_list', 'visibility', 'visible'); // 既存コメントを表示
467 // 初期表示以外の場合はリプライ先のコメントのみ表示
470 $showComment = true; // コメント表示するかどうか
472 $this->message = self::MESSAGE_NOT_PERMITTED_REFER; // 閲覧不可メッセージ
475 // コメントを受け付けるときは、コメント入力欄を表示
476 if ($showComment && $this->commentAccept){
477 $this->tmpl->setAttribute('add_comment', 'visibility', 'visible'); // コメント投稿欄を表示
480 if ($this->useTitle){
481 $this->tmpl->setAttribute('input_title', 'visibility', 'visible'); // タイトルあり
482 $this->tmpl->addVar("input_title", "title", $this->convertToDispString($title));
484 if ($this->useAuthor){
485 $this->tmpl->setAttribute('input_author', 'visibility', 'visible'); // 投稿者名あり
486 $this->tmpl->addVar("input_author", "author", $this->convertToDispString($author));
489 if ($this->gEnv->isCurrentUserLogined()){
490 $this->tmpl->addVar("input_author", "author_disabled", 'readonly');
491 $this->tmpl->setAttribute('update_cookie_author', 'visibility', 'hidden');
492 $this->tmpl->setAttribute('init_cookie_author', 'visibility', 'hidden');
495 if ($this->useEmail){
496 $this->tmpl->setAttribute('input_email', 'visibility', 'visible'); // Eメールあり
497 $this->tmpl->addVar("input_email", "email", $this->convertToDispString($email));
499 // ログイン中はログインユーザのEメールを表示
500 $userEmail = $this->gEnv->getCurrentUserEmail();
501 if ($this->gEnv->isCurrentUserLogined() && !empty($userEmail)){ // Eメールが設定されている場合のみ
502 $this->tmpl->addVar("input_email", "email_disabled", 'readonly');
503 $this->tmpl->setAttribute('update_cookie_email', 'visibility', 'hidden');
504 $this->tmpl->setAttribute('init_cookie_email', 'visibility', 'hidden');
508 $this->tmpl->setAttribute('input_url', 'visibility', 'visible'); // URLあり
509 $this->tmpl->addVar("input_url", "url", $this->convertToDispString($url));
512 //if ($this->useAvatar) $this->tmpl->setAttribute('input_title', 'visibility', 'visible'); // アバターあり
514 if ($sendStatus == 1){ // 確認画面のとき
515 $this->tmpl->addVar("input_title", "title_disabled", 'readonly');
516 $this->tmpl->addVar("input_author", "author_disabled", 'readonly');
517 $this->tmpl->addVar("input_email", "email_disabled", 'readonly');
518 $this->tmpl->addVar("input_url", "url_disabled", 'readonly');
519 $this->tmpl->addVar("input_comment", "comment_disabled", 'readonly');
520 $this->tmpl->setAttribute('cancel_button', 'visibility', 'visible'); // キャンセルボタン表示
523 $this->tmpl->setAttribute('update_cookie_author', 'visibility', 'hidden');
524 $this->tmpl->setAttribute('init_cookie_author', 'visibility', 'hidden');
525 $this->tmpl->setAttribute('update_cookie_email', 'visibility', 'hidden');
526 $this->tmpl->setAttribute('init_cookie_email', 'visibility', 'hidden');
530 if ($this->permitHtml){
531 if ($sendStatus == 0){ // 初期状態のとき
532 $this->tmpl->setAttribute('input_comment', 'visibility', 'visible'); // コメント入力フィールド表示
534 $this->tmpl->setAttribute('show_wysiwyg', 'visibility', 'visible'); // wysiwygエディター表示
535 $this->addLib[] = ScriptLibInfo::LIB_CKEDITOR; // CKEditorライブラリを追加
537 $this->tmpl->setAttribute('show_comment', 'visibility', 'visible');
538 $this->tmpl->addVar('show_comment', 'comment_html', $commentHtml); // HTMLコメント
539 $this->tmpl->addVar('show_comment', 'comment', $this->convertToDispString($comment)); // コメントソース
542 $this->tmpl->setAttribute('input_comment', 'visibility', 'visible'); // コメント入力フィールド表示
543 $this->tmpl->addVar('input_comment', 'comment', $this->convertToDispString($comment)); // コメントソース
547 $commentId = md5($this->contentType . self::COMMENT_ID_SEPARATOR . $contentsId); // コメントID作成用セパレータ
549 $this->tmpl->addVar("add_comment", "send_button_label", $sendButtonLabel);// 送信ボタンラベル
550 $this->tmpl->addVar("add_comment", "send_status", $sendStatus);// 送信状況
551 $this->tmpl->addVar("add_comment", "status", $sendStatus); // 送信ステータス
552 $this->tmpl->addVar("add_comment", "ticket", $postTicket); // 画面確認用
553 $this->tmpl->addVar("add_comment", "comment_id", $commentId); // コメントID
555 //if ($sendStatus != 0 || $this->getMsgCount() > 0){ // 初期状態以外または入力エラーがあるとき
556 if (!$isInit){ // 初期表示以外のとき
558 $this->tmpl->setAttribute('scrollup_comment', 'visibility', 'visible');
561 // 名前保存用のスクリプトライブラリ追加
562 $this->tmpl->setAttribute('init_form', 'visibility', 'visible');
563 $this->tmpl->setAttribute('update_cookie', 'visibility', 'visible');
564 $this->addLib[] = self::COOKIE_LIB;
566 } else { // コメント投稿不可の場合
567 if (empty($this->message)) $this->message = self::MESSAGE_NOT_PERMITTED_POST; // 投稿不可メッセージ
570 // コメントがないときは投稿なしメッセージを表示
571 if (empty($this->message) && !$this->isExistsComment){
572 $this->message = self::MESSAGE_NO_COMMENT;
575 // 初期表示の場合で入力エラーメッセージがない場合はメッセージを表示
576 //if ($sendStatus == 0 && $this->getMsgCount() == 0 && !empty($this->message)){
577 if ($isInit && !empty($this->message)){
578 $this->tmpl->setAttribute('message', 'visibility', 'visible');
579 $this->tmpl->addVar("message", "message", $this->convertToDispString($this->message));
585 * @param RequestManager $request HTTPリクエスト処理クラス
586 * @param object $param 任意使用パラメータ。そのまま_assign()に渡る
587 * @return string ウィジェットのタイトル名
589 function _setTitle($request, &$param)
591 return $this->widgetTitle;
596 * @param RequestManager $request HTTPリクエスト処理クラス
599 function exitWidget()
601 if ($this->cmd == M3_REQUEST_CMD_DO_WIDGET){ // ウィジェット単体実行
602 // ダウンロード不可のときはエラーログを残す
604 if (!empty($this->commentSerialNo)) $msgDetail .= 'コメントシリアル番号=' . $this->commentSerialNo;
605 $this->writeUserError(__METHOD__, '画像ファイルへの不正なアクセスを検出しました。画像ID=' . $imageId, 2200, $msgDetail);
608 $this->gPage->abortPage();
611 $this->gPage->setResponse(403/*アクセス禁止*/);
614 $this->gPage->exitSystem();
616 $this->cancelParse(); // テンプレート変換処理中断
622 * @param RequestManager $request HTTPリクエスト処理クラス
625 function downloadImage($request)
627 $imageId = $request->trimValueOf(commentCommonDef::REQUEST_PARAM_IMAGE_ID); // 画像ID
630 $this->gPage->abortPage();
633 $downloadCompleted = false; // ダウンロード処理完了かどうか
635 if (empty($this->commentSerialNo)){ // まだ画像が登録されていない場合
636 $downloadFile = $this->imageDir . DIRECTORY_SEPARATOR . $imageId;
637 $downloadFilename = $attachFileRow['af_filename'];
638 if (empty($downloadFilename)) $downloadFilename = $attachFileRow['af_original_filename'];
641 $ret = $this->gPage->downloadFile($downloadFile, $downloadFilename);
642 $downloadCompleted = true; // ダウンロード処理完了かどうか
644 $ret = $this->gInstance->getFileManager()->getAttachFileInfo(commentCommonDef::$_viewContentType, $this->commentSerialNo, $attachFileRows);
646 for ($i = 0; $i < count($attachFileRows); $i++){
647 $fileRow = $attachFileRows[$i];
648 if ($imageId == $fileRow['af_file_id']){
649 //$downloadFile = commentCommonDef::getAttachFileDir() . DIRECTORY_SEPARATOR . $imageId;
650 $downloadFile = $this->imageDir . DIRECTORY_SEPARATOR . $imageId;
651 $downloadFilename = $fileRow['af_filename'];
652 if (empty($downloadFilename)) $downloadFilename = $fileRow['af_original_filename'];
655 $ret = $this->gPage->downloadFile($downloadFile, $downloadFilename);
656 $downloadCompleted = true; // ダウンロード処理完了かどうか
662 if ($downloadCompleted){ // ダウンロード処理完了のとき
664 $this->gInstance->getAnalyzeManager()->logContentDownload(commentCommonDef::$_viewContentType . commentCommonDef::DOWNLOAD_TYPE_IMAGE, $imageId);
667 if (!empty($this->commentSerialNo)) $msgDetail .= 'コメントシリアル番号=' . $this->commentSerialNo;
668 $this->writeError(__METHOD__, '画像ファイルのダウンロードに失敗しました。画像ファイルが見つかりません。画像ID=' . $imageId, 2200, $msgDetail);
672 $this->gPage->exitSystem();
677 * @param string $contentType コンテンツタイプ
678 * @param string $contentsId 共通コンテンツID
681 function createTitle($contentType, $contentsId)
683 $title = self::DEFAULT_TITLE;
685 switch ($contentType){
686 case M3_VIEW_TYPE_CONTENT: // 汎用コンテンツ
687 $ret = self::$_mainDb->getContentById(''/*PC用コンテンツ*/, $this->_langId, $contentsId, $row);
688 if ($ret) $contentName = $row['cn_name'];
690 case M3_VIEW_TYPE_PRODUCT: // 商品情報(Eコマース)
691 $ret = self::$_mainDb->getProductById($contentsId, $this->_langId, $row);
692 if ($ret) $contentName = $row['pt_name'];
694 case M3_VIEW_TYPE_BBS: // BBS
697 case M3_VIEW_TYPE_BLOG: // ブログ
698 $ret = self::$_mainDb->getEntryById($contentsId, $this->_langId, $row);
699 if ($ret) $contentName = $row['be_name'];
701 case M3_VIEW_TYPE_WIKI: // wiki
702 $contentName = $contentsId;
704 case M3_VIEW_TYPE_USER: // ユーザ作成コンテンツ
705 $ret = self::$_mainDb->getRoomById($contentsId, $this->_langId, $row);
706 if ($ret) $contentName = $row['ur_name'];
708 case M3_VIEW_TYPE_EVENT: // イベント情報
709 $ret = self::$_mainDb->getEventById($contentsId, $this->_langId, $row);
710 if ($ret) $contentName = $row['ee_name'];
712 case M3_VIEW_TYPE_PHOTO: // フォトギャラリー
713 $ret = self::$_mainDb->getPhotoById($contentsId, $this->_langId, $row);
714 if ($ret) $contentName = $row['ht_name'];
717 if (!empty($contentName)){
718 $title = sprintf(self::COMMENT_TITLE_FORMAT, $contentName);
723 * JavascriptライブラリをHTMLヘッダ部に設定
725 * JavascriptライブラリをHTMLのheadタグ内に追加出力する。
726 * _assign()よりも後に実行される。
728 * @param RequestManager $request HTTPリクエスト処理クラス
729 * @param object $param 任意使用パラメータ。
730 * @return string,array Javascriptライブラリ。出力しない場合は空文字列を設定。
732 function _addScriptLibToHead($request, &$param)
734 return $this->addLib;
737 * 取得したコンテンツ項目をテンプレートに設定する
739 * @param int $index 行番号
740 * @param array $fetchedRow 取得行
741 * @param object $param 任意使用パラメータ
742 * @return bool trueを返すとループ続行。falseを返すとその時点で終了。
744 function itemsLoop($index, $fetchedRow)
746 $contentsId = $fetchedRow['cm_contents_id']; // 共通コンテンツID
747 $permaLink = commentCommonDef::COMMENT_PERMA_HEAD . $fetchedRow['cm_no']; // コメントパーマリンク
749 if ($this->useTitle){
750 $commentTitle = $fetchedRow['cm_title']; // コメントタイトル
751 if (empty($commentTitle)) $commentTitle = self::NO_COMMENT_TITLE;
752 $titleTag = '<a name="' . $permaLink . '" href="#' . $permaLink . '">' . $this->convertToDispString($commentTitle) . '</a>';
754 $permaUrl = commentCommonDef::createCommentUrl($this->contentType, $contentsId, $fetchedRow['cm_no']);
755 $permaTag = '<a href="' . $this->convertUrlToHtmlEntity($permaUrl) . '"><img src="' . $this->getUrl($this->gEnv->getRootUrl() . self::PERMALINK_ICON_FILE) .
756 '" width="' . self::PERMA_BUTTON_ICON_SIZE . '" height="' . self::PERMA_BUTTON_ICON_SIZE . '" title="パーマリンク" alt="パーマリンク" style="border:none;margin:0;padding:0;" /></a>';
757 $commentTag = $fetchedRow['cm_message'];
760 if ($this->useAuthor){
761 $userName = $fetchedRow['lu_name'];
762 if (empty($userName)) $userName = $fetchedRow['cm_author'];
764 if (empty($userName)) $userName = self::NO_COMMENT_AUTHOR;
768 if ($this->useAvatar){
769 $avatarUrl = $this->gInstance->getImageManager()->getAvatarUrl($fetchedRow['lu_avatar']);
770 $avatarTitle = $this->convertToDispString($userName) . self::AVATAR_TITLE_TAIL;
771 $avatarTag = '<img src="' . $this->getUrl($avatarUrl) . '" width="' . $this->avatarSize . '" height="' . $this->avatarSize .
772 '" border="0" alt="' . $avatarTitle . '" title="' . $avatarTitle . '" />';
778 $url = $fetchedRow['cm_url'];
779 if (!empty($url)) $urlTag = '<br />URL: <a href="' . $this->convertUrlToHtmlEntity($url) . '" target="_blank">' . $this->convertToDispString($url) . '</a>';
783 if ($this->permitHtml){ // HTMLコメントの場合
784 // BBコード変換で自動リンクは作成される
786 //$commentTag = $this->convertM3ToHtml($fetchedRow['cm_message'], true/*改行コーをbrタグに変換*/);
787 $commentTag = str_replace(M3_TAG_START . M3_TAG_MACRO_ROOT_URL . M3_TAG_END, $this->currentPageRootUrl, $commentTag);// アプリケーションルートを変換
789 if ($this->autolink){ // 自動リンクの場合
790 $commentTag = preg_replace("/(https?):\/\/([\w;\/\?:\@&=\+\$,\-\.!~\*'\(\)%#]+)/", "<a href=\"$1://$2\" target=\"_blank\">$1://$2</a>", $commentTag);
792 $commentTag = $this->convertToPreviewText($this->convertToDispString($commentTag));// 改行コードをbrタグに変換
796 'title' => $titleTag, // タイトル
797 'avatar' => $avatarTag, // アバター
798 'author' => $this->convertToDispString($userName), // 投稿者名
799 'date' => $this->timestampToDate($fetchedRow['cm_create_dt']), // コメント投稿日(日付)
800 'time' => $this->timestampToTime($fetchedRow['cm_create_dt']), // コメント投稿日(時間)
801 'permalink' => $permaTag, // パーマリンクアイコン
802 'url' => $urlTag, // URL
803 'comment' => $commentTag // コメント内容
805 $this->tmpl->addVars('comment_list', $row);
806 $this->tmpl->parseTemplate('comment_list', 'a');
807 $this->isExistsComment = true; // 表示データがあるかどうか
813 * @param int $pageNo ページ番号(1~)。ページ番号が範囲外にある場合は自動的に調整
814 * @param int $totalCount 総項目数
815 * @param int $viewItemCount 1ページあたりの項目数
816 * @param string $baseUrl リンク用のベースURL
817 * @return string リンクHTML
819 function createPageLink(&$pageNo, $totalCount, $viewItemCount, $baseUrl)
822 $pageCount = (int)(($totalCount -1) / $viewItemCount) + 1; // 総ページ数
823 if ($pageNo < 1) $pageNo = 1;
824 if ($pageNo > $pageCount) $pageNo = $pageCount;
828 if ($pageCount > 1){ // ページが2ページ以上のときリンクを作成
829 // ページ数1から「LINK_PAGE_COUNT」までのリンクを作成
830 $maxPageCount = $pageCount < self::LINK_PAGE_COUNT ? $pageCount : self::LINK_PAGE_COUNT;
831 for ($i = 1; $i <= $maxPageCount; $i++){
833 $link = ' ' . $i;
835 $linkUrl = $this->getUrl($baseUrl . '&page=' . $i, true/*リンク用*/);
836 $link = ' <a href="' . $this->convertUrlToHtmlEntity($linkUrl) . '" >' . $i . '</a>';
841 if ($pageCount > self::LINK_PAGE_COUNT) $pageLink .= ' ...';
843 if ($pageNo > 1){ // 前ページがあるとき
844 $linkUrl = $this->getUrl($baseUrl . '&page=' . ($pageNo -1), true/*リンク用*/);
845 $link = '<a href="' . $this->convertUrlToHtmlEntity($linkUrl) . '" >前へ</a>';
846 $pageLink = $link . $pageLink;
848 if ($pageNo < $pageCount){ // 次ページがあるとき
849 $linkUrl = $this->getUrl($baseUrl . '&page=' . ($pageNo +1), true/*リンク用*/);
850 $link = ' <a href="' . $this->convertUrlToHtmlEntity($linkUrl) . '" >次へ</a>';
856 * BBCodeのコメントを解析し、HTMLに変換
858 * @param string $src コメント入力
859 * @return string HTML変換したコメント
861 function parseComment($src)
863 $commentHtml = $this->gInstance->getTextConvManager()->convBBCodeToHtml($src, true);
869 * @param string $html 変換元コンテンツ
870 * @return string 変換後コンテンツ
872 function convertImageUrl($html)
874 $str = '/<img[^<]*?src\s*=\s*[\'"]+(.+?)[\'"]+[^>]*?>/si';
875 $dest = preg_replace_callback($str, array($this, "_convert_image_url_callback"), $html);
881 * @param array $matchData 検索マッチデータ
882 * @return string 変換後データ
884 function _convert_image_url_callback($matchData)
889 if ($this->isErrorInReadImage) return ''; // 画像読み込みエラー発生
891 //$destTag = $matchData[0]; // マッチしたタグ全体
893 $imageUrl = $matchData[1];
894 if ($this->gEnv->isSystemUrlAccess($imageUrl)){ // システム内のファイルのとき
896 if ($this->isReadImageCheck){
897 if ($index < count($this->imageFileInfoArray)){
898 $fileInfo = $this->imageFileInfoArray[$index];
899 if (!empty($imageUrl) && $imageUrl == $fileInfo->originalUrl){ // 取得先URL比較
900 $imageId = $fileInfo->fileId; // 画像ID
901 $imagePath = $this->imageDir . DIRECTORY_SEPARATOR . $imageId;
904 $this->gInstance->getImageManager()->getImageInfo($imagePath, $width, $height);
906 $param = commentCommonDef::REQUEST_PARAM_IMAGE_ID . '=' . $imageId;
907 $newUrl = $this->createCmdUrlToCurrentWidget($param, true/*マクロ形式で取得*/);
908 $destTag = '<img src="' . $newUrl . '" width="' . $width . '" height="' . $height . '" />';
910 $this->isErrorInReadImage = true; // 画像読み込みエラー発生
913 $this->isErrorInReadImage = true; // 画像読み込みエラー発生
916 if (empty($imageUrl)){
917 $this->isErrorInReadImage = true; // 画像読み込みエラー発生
920 $imageId = $this->gInstance->getFileManager()->createRandFileId();
921 $originalFilename = basename($imageUrl); // 元のファイル名
922 $imagePath = $this->imageDir . DIRECTORY_SEPARATOR . $imageId;
925 $tmpFile = tempnam($this->gEnv->getWorkDirPath(), M3_SYSTEM_WORK_UPLOAD_FILENAME_HEAD);
926 if ($tmpFile !== false){
929 if ($input = @fopen($imageUrl, 'r')){
930 $ret = file_put_contents($tmpFile, $input);
931 if ($ret !== false) $ret = true;
939 $ret = $this->gInstance->getImageManager()->createImage($tmpFile, $imagePath, $this->maxImageSize, commentCommonDef::OUTPUT_IMAGE_TYPE, $destSize);
944 $ret = $this->gInstance->getFileManager()->addAttachFileInfo(commentCommonDef::$_viewContentType, $imageId, $imagePath, $originalFilename, $imageUrl);
947 // 画像が作成できない場合は画像を表示しない
949 $param = commentCommonDef::REQUEST_PARAM_IMAGE_ID . '=' . $imageId;
950 $newUrl = $this->createCmdUrlToCurrentWidget($param);
951 $destTag = '<img src="' . $this->getUrl($newUrl) . '" width="' . $destSize['width'] . '" height="' . $destSize['height'] . '" />';
953 if (!$ret) $this->isErrorInReadImage = true; // 画像読み込みエラー発生
958 $this->isErrorInReadImage = true; // 画像読み込みエラー発生