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-2011 Magic3 Project.
12 * @license http://www.gnu.org/copyleft/gpl.html GPL License
13 * @version SVN: $Id: m_bbs_2chBaseWidgetContainer.php 4037 2011-03-19 13:54:56Z fishbone $
14 * @link http://www.magic3.org
16 require_once($gEnvManager->getContainerPath() . '/baseMobileWidgetContainer.php');
17 require_once($gEnvManager->getCurrentWidgetDbPath() . '/bbs_2chDb.php');
19 class m_bbs_2chBaseWidgetContainer extends BaseMobileWidgetContainer
21 protected $_db; // DB接続オブジェクト
22 protected $_configArray; // BBS定義値
23 protected $_headCss; // CSS定義
24 protected $_boardId; // 掲示板ID
25 protected $_currentPageUrl; // 現在のページのURL
26 // protected $_postUrl; // POST用のURL
27 protected $_autolink; // リンクを自動作成
28 protected $_spacer; // スペーサ
29 const SPACER_FORMAT = '<div style="background-color:#aaaaaa;margin:1px 0;height:1px;"><img src="%s/images/system/spacer.gif" width="1" height="1" /></div>'; // スペーサフォーマット
30 const MACRO_RES_MAX_NO = 'RES_MAX_NO'; // レス上限数マクロ
31 const DEFAULT_BBS_ID = 'board1'; // デフォルトの掲示板ID
32 const DEFAULT_LAST_MESSAGE_COUNT = 50; // メッセージ取得用デフォルトの最新メッセージ数
33 const DEFAULT_MESSAGE_COUNT_PER_PAGE = 100; // メッセージ取得用デフォルトの1ページあたりメッセージ数
34 const DEFAULT_BOTTOM_MESSAGE = '<center><b>どのような形の削除依頼であれ公開させていただきます。</b></center>'; // デフォルトのトップ画面下部メッセージ
35 const DEFAULT_THREAD_END_MESSAGE = "このスレッドは[#RES_MAX_NO#]を超えました。\r\nもう書けないので、新しいスレッドを立ててくださいです。。。"; // デフォルトのレス上限メッセージ
36 const DEFAULT_EMAIL_NOT_UPDATE = 'sage'; // スレッドの日付更新を行わないEmailアドレス
37 const DEFAULT_ADMIN_NAME = 'サイト運営者'; // サイト運営者名
38 const CF_BBS_TITLE = 'title'; // 掲示板タイトル
39 const CF_TITLE_COLOR = 'title_color'; // タイトルカラー
40 const CF_TOP_LINK = 'top_link'; // トップ画像のリンク先
41 const CF_TOP_IMAGE = 'top_image'; // トップ画像
42 const CF_BBS_GUIDE = 'bbs_guide'; // 掲示板規則
43 const CF_BOTTOM_MESSAGE = 'bottom_message'; // トップ画面下部メッセージ
44 const CF_THREAD_END_MESSAGE = 'thread_end_message'; // レス上限メッセージ
45 const CF_BG_IMAGE = 'bg_image'; // 背景画像
46 const CF_BG_COLOR = 'bg_color'; // 背景色
47 const CF_TEXT_COLOR = 'text_color'; // 文字色
48 const CF_MENU_COLOR = 'menu_color'; // メニュー背景色
49 const CF_MAKE_THREAD_COLOR = 'makethread_color'; // スレッド作成部背景色
50 const CF_THREAD_COLOR = 'thread_color'; // スレッド表示部背景色
51 const CF_LINK_COLOR = 'link_color'; // リンク色
52 const CF_ALINK_COLOR = 'alink_color'; // リンク色
53 const CF_VLINK_COLOR = 'vlink_color'; // リンク色
54 const CF_NAME_COLOR = 'name_color'; // 投稿者名文字色
55 const CF_FILE_UPLOAD = 'file_upload'; // ファイルアップロード許可
56 const CF_SUBJECT_LENGTH = 'subject_length'; // 件名最大長
57 const CF_NAME_LENGTH = 'name_length'; // 投稿者名最大長
58 const CF_EMAIL_LENGTH = 'email_length'; // emailアドレス最大長
59 const CF_MESSAGE_LENGTH = 'message_length'; // 最大メッセージ長
60 const CF_ERR_MESSAGE_COLOR = 'err_message_color'; // エラーメッセージ文字色
61 const CF_SUBJECT_COLOR = 'subject_color'; // 件名文字色
62 const CF_LINE_LENGTH = 'line_length'; // 投稿文行長
63 const CF_LINE_COUNT = 'line_count'; // 投稿文行数
64 const CF_RES_ANCHOR_LINK_COUNT = 'res_anchor_link_count'; // レスアンカーリンク数
65 const CF_THREAD_COUNT = 'thread_count'; // トップ画面に表示するスレッド最大数
66 const CF_RES_COUNT = 'res_count'; // トップ画面に表示するレス最大数
67 const CF_THREAD_RES = 'thread_res'; // 1スレッドに投稿できるレス番号の上限
68 const CF_MENU_THREAD_COUNT = 'menu_thread_count'; // メニューに表示するスレッド最大数
69 const CF_SHOW_EMAIL = 'show_email'; // Eメールアドレスを表示
70 const CF_AUTOLINK = 'autolink'; // 自動的にリンクを作成
71 const CF_NONAME_NAME = 'noname_name'; // 名前未設定時の表示名
72 const CF_ADMIN_NAME = 'admin_name'; // サイト運営者名
74 const TASK_TOP = 'top'; // トップ画面
75 const TASK_SUBJECT = 'subject'; // スレッド件名
76 const TASK_THREAD = 'thread'; // スレッド処理
77 const TASK_NEW_THREAD = 'newthread'; // スレッド新規作成
78 const TASK_READ_THREAD = 'read'; // スレッド表示
83 function __construct()
86 parent::__construct();
89 $this->_db = new bbs_2chDb();
94 $this->_boardId = self::DEFAULT_BBS_ID;
95 //$this->_currentPageUrl = $this->gEnv->createCurrentPageUrl(); // 現在のページのURL
96 $this->_currentPageUrl = $this->gEnv->createCurrentPageUrlForMobile(); // 現在のページのURL
97 // $this->_postUrl = $this->gEnv->getCurrentRequestUri(); // POST用のURL
98 $this->_autolink = $this->_configArray[self::CF_AUTOLINK]; // リンクを自動作成
99 $this->_spacer = sprintf(self::SPACER_FORMAT, $this->getUrl($this->gEnv->getRootUrl()));// スペーサ作成
104 * _setTemplate()で指定したテンプレートファイルにデータを埋め込む。
106 * @param RequestManager $request HTTPリクエスト処理クラス
107 * @param object $param 任意使用パラメータ。_setTemplate()と共有。
110 function _postAssign($request, &$param)
113 $titleColor = $this->_configArray[self::CF_TITLE_COLOR]; // タイトルカラー
114 $topImage = $this->_configArray[self::CF_TOP_IMAGE];
115 if (!empty($topImage)){
116 $topLink = $this->convertUrlToHtmlEntity($this->_configArray[self::CF_TOP_LINK]); // トップ画像のリンク先
119 $pos = strpos($topImage, '/');
120 if ($pos === false){ // ファイル名だけのとき
121 $topImage = $this->gEnv->getCurrentWidgetImagesUrl() . '/' . $topImage;
123 $topImage = str_replace(M3_TAG_START . M3_TAG_MACRO_ROOT_URL . M3_TAG_END, $this->gEnv->getRootUrl(), $topImage);
125 $topImage = '<img src="' . $topImage . '" border="0" />';
126 if (!empty($topLink)) $topImage = '<a href="' . $topLink . '">' . $topImage . '</a>';
128 $this->tmpl->addVar("_widget", "top_image", $topImage); // トップ画像
131 $title = $this->_configArray[self::CF_BBS_TITLE]; // 掲示板タイトル
132 $this->tmpl->addVar("_widget", "bbs_title", $this->convertToDispString($title));
133 $this->tmpl->addVar("_widget", "guide", $this->_configArray[self::CF_BBS_GUIDE]);
137 /* $bgImage = $this->_configArray[self::CF_BG_IMAGE];
138 $pos = strpos($bgImage, '/');
139 if ($pos === false){ // ファイル名だけのとき
140 $bgImage = $this->gEnv->getCurrentWidgetImagesUrl() . '/' . $bgImage;
142 $bgImage = str_replace(M3_TAG_START . M3_TAG_MACRO_ROOT_URL . M3_TAG_END, $this->gEnv->getRootUrl(), $bgImage);
144 $bgColor = $this->_configArray[self::CF_BG_COLOR];
145 $textColor = $this->_configArray[self::CF_TEXT_COLOR]; // 文字色
146 // $bbsStyle .= 'background-image:url(' . $bgImage . ');';
147 $bbsStyle .= 'background-color:' . $bgColor . ';';
148 $bbsStyle .= 'color:' . $textColor . ';';
149 $this->tmpl->addVar("_widget", "bbs_style", $bbsStyle);
151 $menuColor = $this->_configArray[self::CF_MENU_COLOR]; // メニュー背景色
152 $menuStyle .= 'background-color:' . $menuColor . ';';
153 $this->tmpl->addVar("_widget", "menu_style", $menuStyle);
156 if ($this->getMsgCount(1) > 0 || $this->getMsgCount(2) > 0){ // エラーメッセージが出力されているとき
157 $errMessageColor = $this->_configArray[self::CF_ERR_MESSAGE_COLOR]; // エラーメッセージ色
158 if (!empty($errMessageColor)){
159 $errMessageStyle .= 'color:' . $errMessageColor . ';';
160 $attr = 'style="' . $errMessageStyle . '"';
161 $this->setMessageAttr($attr);
166 $cssId = $this->gEnv->getCurrentWidgetId() . '_0';
167 $this->_headCss .= '#' . $cssId . ' a {text-decoration:underline;}' . M3_NL;
168 $this->_headCss .= '#' . $cssId . ' a:link {color:' . $this->_configArray[self::CF_LINK_COLOR] . ';}' . M3_NL;
169 $this->_headCss .= '#' . $cssId . ' a:active {color:' . $this->_configArray[self::CF_ALINK_COLOR] . ';}' . M3_NL;
170 //$this->_headCss .= '#' . $cssId . ' a:hover {color:' . $this->_configArray[self::CF_VLINK_COLOR] . ';}' . M3_NL;
171 $this->_headCss .= '#' . $cssId . ' a:visited {color:' . $this->_configArray[self::CF_VLINK_COLOR] . ';}' . M3_NL;
172 $this->tmpl->addVar("_widget", "css_id", $cssId); // CSS用ID
175 $this->tmpl->addVar("_widget", "bbs_url", $this->convertUrlToHtmlEntity($this->getUrl($this->gEnv->createCurrentPageUrl(), true)));
176 $this->tmpl->addVar("_widget", "subject_url", $this->convertUrlToHtmlEntity($this->getUrl($this->gEnv->createCurrentPageUrl() . '&task=' . self::TASK_SUBJECT, true))); // スレッド件名
177 $this->tmpl->addVar("_widget", "newthread_url", $this->convertUrlToHtmlEntity($this->getUrl($this->gEnv->createCurrentPageUrl() . '&task=' . self::TASK_NEW_THREAD, true))); // 新規スレッド作成
182 * CSSデータをHTMLのheadタグ内に追加出力する。
183 * _assign()よりも後に実行される。
185 * @param RequestManager $request HTTPリクエスト処理クラス
186 * @param object $param 任意使用パラメータ。
187 * @return string CSS文字列。出力しない場合は空文字列を設定。
189 function _addCssToHead($request, &$param)
191 return $this->_headCss;
196 * @return bool true=取得成功、false=取得失敗
198 function _loadConfig()
200 $this->_configArray = array();
203 $ret = $this->_db->getAllConfig($rows);
206 $configCount = count($rows);
207 for ($i = 0; $i < $configCount; $i++){
208 $key = $rows[$i]['tg_id'];
209 $value = $rows[$i]['tg_value'];
210 $this->_configArray[$key] = $value;
218 * @param string $boardId 掲示板ID
219 * @param string $threadId スレッドID(-1のときチェックなし)
220 * @param string $name ユーザ名
221 * @param string $email Eメールアドレス
222 * @param string $message 投稿文
223 * @return bool true=正常終了、false=異常終了
225 function checkMessageInput($boardId, $threadId, $name, $email, $message)
228 if ($threadId != -1) $this->checkInput($threadId, 'スレッドID');
229 $this->checkInput($message, '本文', 'ERROR:本文がありません!');
231 if ($this->getMsgCount() == 0){
233 if ($threadId != -1){
234 $ret = $this->_db->getThreadInfo($boardId, $threadId, $row);
237 $resCount = $this->_configArray[self::CF_THREAD_RES];
238 if ($row['th_message_count'] >= $resCount){
239 $this->setUserErrorMsg('このスレッドは' . $resCount . 'を超えました。<br /> もう書けないので、新しいスレッドを立ててくださいです。。。');
243 /*#.datが存在してないか書けないならばいばい
244 if (!is_writable($DATAFILE)) DispError("ERROR!","ERROR:このスレッドには書けません!");*/
246 $this->setUserErrorMsg('ERROR:スレッドIDが不正です!');
251 if (function_exists('mb_strlen')){
252 $length = mb_strlen($message);
254 $length = strlen($message);
256 if ($length > $this->_configArray[self::CF_MESSAGE_LENGTH]){
257 $this->setUserErrorMsg('ERROR:本文が長すぎます!(最大文字数' . $this->_configArray[self::CF_MESSAGE_LENGTH] . ')');
260 $lines = preg_split("/(\015\012)|(\015)|(\012)/", $message);
261 if (count($lines) > $this->_configArray[self::CF_LINE_COUNT]) $this->setUserErrorMsg('ERROR:改行が多すぎます!');
264 $maxLineLength = $this->_configArray[self::CF_LINE_LENGTH];
265 foreach ($lines as $line) {
267 if (function_exists('mb_strlen')){
268 $length = mb_strlen($line);
270 $length = strlen($line);
272 if ($length > $maxLineLength){
273 $this->setUserErrorMsg('ERROR:長すぎる行があります!(最大文字数' . $maxLineLength . ')');
279 if (preg_match_all("/>>[0-9]/", $message, $matches) > $this->_configArray[self::CF_RES_ANCHOR_LINK_COUNT]) $this->setUserErrorMsg('レスアンカーリンクが多すぎます!');
283 if (function_exists('mb_strlen')){
284 $length = mb_strlen($name);
286 $length = strlen($name);
288 if ($length > $this->_configArray[self::CF_NAME_LENGTH]) $this->setUserErrorMsg('ERROR:名前が長すぎます!(最大文字数' . $this->_configArray[self::CF_NAME_LENGTH] . ')');
291 if (function_exists('mb_strlen')){
292 $length = mb_strlen($email);
294 $length = strlen($email);
296 if ($length > $this->_configArray[self::CF_EMAIL_LENGTH]) $this->setUserErrorMsg('ERROR:メールアドレスが長すぎます!(最大文字数' . $this->_configArray[self::CF_EMAIL_LENGTH] . ')');
298 if ($this->getMsgCount() == 0){
307 * @param string $message 変換元メッセージ
308 * @param string $threadId スレッドID
309 * @return string 変換後メッセージ
311 function convDispMessage($message, $threadId)
314 if (!empty($this->_autolink)){ // 自動リンク作成のとき
315 $message = preg_replace("/(https?):\/\/([\w;\/\?:\@&=\+\$,\-\.!~\*'\(\)%#]+)/", "<a href=\"$1://$2\" target=\"_blank\">$1://$2</a>", $message);
318 $baseUrl = $this->convertUrlToHtmlEntity($this->getUrl($this->_currentPageUrl . '&' . M3_REQUEST_PARAM_BBS_THREAD_ID . '=' . $threadId, true));
319 $messageUrl = $baseUrl . $this->convertUrlToHtmlEntity('&' . M3_REQUEST_PARAM_ITEM_NO . '=');
320 $messageListUrl = $baseUrl . $this->convertUrlToHtmlEntity('&' . M3_REQUEST_PARAM_LIST_NO . '=');
321 $message = preg_replace("/>>([0-9]+)(?![-\d])/", '<a href="' . $messageUrl . '$1" target="_blank">>>$1</a>', $message);
322 $message = preg_replace("/>>([0-9]+)\-([0-9]+)/", '<a href="' . $messageListUrl . '$1-$2" target="_blank">>>$1-$2</a>', $message);