7 * LICENSE: This source file is licensed under the terms of the GNU General Public License.
10 * @author 株式会社 毎日メディアサービス
11 * @copyright Copyright 2010-2013 株式会社 毎日メディアサービス.
12 * @license http://www.gnu.org/copyleft/gpl.html GPL License
13 * @version SVN: $Id: breadcrumbWidgetContainer.php 5883 2013-03-31 12:22:13Z fishbone $
14 * @link http://www.m-media.co.jp
16 require_once($gEnvManager->getContainerPath() . '/baseWidgetContainer.php');
17 require_once($gEnvManager->getCurrentWidgetDbPath() . '/breadcrumbDb.php');
19 class breadcrumbWidgetContainer extends BaseWidgetContainer
21 private $db; // DB接続オブジェクト
22 private $currentMacroUrl; // 現在のマクロ表記URL
23 private $menuItems; // メニュー項目情報
24 private $iconTag; // パンくずリストのアイコン
25 const DEFAULT_TITLE = 'パンくずリスト'; // デフォルトのウィジェットタイトル名
26 const DEFAULT_HOME_NAME = 'ホーム'; // デフォルトのルート階層名
27 const DEFAULT_HOME_URL = '/'; // デフォルトのホームURL
28 const MAX_MENU_TREE_LEVEL = 5; // メニュー階層最大数
29 const MENU_ITEM_NONAME = '名称未設定'; // メニュー項目に名前が設定されていない場合の名前
30 const DEFAULT_ARROW_IMAGE_FILE = '/images/arrow.png'; // パンくずリスト用画像
35 function __construct()
38 parent::__construct();
41 $this->db = new breadcrumbDb();
46 * _assign()でデータを埋め込むテンプレートファイルのファイル名を返す。
47 * 読み込むディレクトリは、「自ウィジェットディレクトリ/include/template」に固定。
49 * @param RequestManager $request HTTPリクエスト処理クラス
50 * @param object $param 任意使用パラメータ。そのまま_assign()に渡る
51 * @return string テンプレートファイル名。テンプレートライブラリを使用しない場合は空文字列「''」を返す。
53 function _setTemplate($request, &$param)
55 return 'index.tmpl.html';
60 * _setTemplate()で指定したテンプレートファイルにデータを埋め込む。
62 * @param RequestManager $request HTTPリクエスト処理クラス
63 * @param object $param 任意使用パラメータ。_setTemplate()と共有。
66 function _assign($request, &$param)
68 $currentUrl = $this->gEnv->getCurrentRequestUri();
71 if (!$this->gEnv->isSystemUrlAccess($currentUrl)) return;
73 // ##### メニュー作成開始 #####
75 $visibleOnRoot = 1; // トップページでリスト表示するかどうか
76 $useHiddenMenu = 0; // 非表示のメニューウィジェットの定義を使用する
77 $separatorImgPath = ''; // 区切り画像パス
78 $paramObj = $this->getWidgetParamObj();
79 if (!empty($paramObj)){
80 $visibleOnRoot = $paramObj->visibleOnRoot;
81 if (isset($paramObj->useHiddenMenu)) $useHiddenMenu = $paramObj->useHiddenMenu; // 非表示のメニューウィジェットの定義を使用する
82 $separatorImgPath = $paramObj->separatorImgPath; // 区切り画像パス
86 $ret = $this->db->getMenuId($useHiddenMenu, $this->gEnv->getCurrentPageId(), $this->gEnv->getCurrentPageSubId(), $allMenu);
91 $iconPath = $this->gEnv->getCurrentTemplatePath() . self::TEMPLATE_ARROW_IMAGE_FILE;
92 if (file_exists($iconPath)) $iconUrl = $this->gEnv->getCurrentTemplateUrl() . self::TEMPLATE_ARROW_IMAGE_FILE;
94 // テンプレートのアイコンがないときは、デフォルトのアイコンを使用
96 $iconUrl = $this->gEnv->getCurrentWidgetRootUrl() . self::TEMPLATE_ARROW_IMAGE_FILE;
99 if (empty($separatorImgPath)){
100 $separatorImgUrl = $this->gEnv->getCurrentWidgetRootUrl() . self::DEFAULT_ARROW_IMAGE_FILE; // デフォルトの画像
102 $separatorImgUrl = $this->gEnv->getRootUrl() . $separatorImgPath; // ユーザ指定の画像
104 $this->iconTag = ' <img src="' . $this->getUrl($separatorImgUrl) . '" /> '; // 両端にスペースを入れる
107 $menuIdArray = array();
108 for ($i = 0; $i < count($allMenu); $i++){
109 $menuId = $allMenu[$i]['pd_menu_id'];
110 if (!in_array($menuId, $menuIdArray)) $menuIdArray[] = $menuId;
114 $this->db->getMenuItems($menuIdArray, $menuItems);
117 $homeName = self::DEFAULT_HOME_NAME;
118 $homeUrl = M3_TAG_START . M3_TAG_MACRO_ROOT_URL . M3_TAG_END . self::DEFAULT_HOME_URL;
119 for ($i = 0; $i < count($menuItems); $i++){
120 $url = $menuItems[$i]['md_link_url']; // マクロ表記URLを取得
121 if ($this->isRootUrl($url)){ // ルートの場合
122 $homeName = $this->getCurrentLangString($menuItems[$i]['md_name']);
128 $this->currentMacroUrl = $this->gEnv->getMacroPath($currentUrl);
129 if ($this->isRootUrl($this->currentMacroUrl)){// ルート位置の場合の処理
130 if ($visibleOnRoot){ // ルートのときリスト表示するとき
131 $html = '<span class="breadcrumbs pathway">' . $this->convertToDispString($homeName) . '</span>';
132 $this->tmpl->addVar("_widget", "link", $html);
138 $this->currentQueryArray = array();
139 list($tmp, $queryStr) = explode('?', $this->currentMacroUrl);
140 list($queryStr, $tmp) = explode('#', $queryStr);
141 if (!empty($queryStr)) parse_str($queryStr, $this->currentQueryArray); // クエリーの解析
145 for ($i = 0; $i < count($menuItems); $i++){
146 $url = $menuItems[$i]['md_link_url']; // マクロ表記URLを取得
147 if ($this->isCurrentMenuItemUrl($url)){
148 $menuItemId = $menuItems[$i]['md_id'];
152 if (empty($menuItemId)){ // メニュー上にないURLのときは現在のページから作成
153 // 現在のページがデフォルトのページのときはトップ時と同じにする
154 $pageSubId = $this->gEnv->getCurrentPageSubId();
155 if (count($this->currentQueryArray) == 1 && $this->currentQueryArray[M3_REQUEST_PARAM_PAGE_SUB_ID] == $this->gEnv->getDefaultPageSubId()){
156 if ($visibleOnRoot){ // ルートのときリスト表示するとき
157 $html = '<span class="breadcrumbs pathway">' . $this->convertToDispString($homeName) . '</span>';
158 $this->tmpl->addVar("_widget", "link", $html);
163 $line = $this->gPage->getPageInfo($this->gEnv->getCurrentPageId(), $pageSubId);
164 if (!empty($line) && !empty($line['pn_name'])) $pageName = $line['pn_name'];
166 // ページ名が取得できないときは、ページIDの名前を取得
167 if (empty($pageName)){
168 $ret = $this->db->getPageRecord($pageSubId, $row);
169 if ($ret) $pageName = $row['pg_name'];
172 // ページサブID以外のパラメータをもつ場合のみリンクを作成
173 if (count($this->currentQueryArray) == 1 && isset($this->currentQueryArray[M3_REQUEST_PARAM_PAGE_SUB_ID])){
174 $html = $this->convertToDispString($pageName);
176 $pageUrl = $this->gEnv->createCurrentPageUrl();
177 $linkUrl = $this->getUrl($pageUrl, true/*リンク用*/);
178 $html = '<a href="' . $this->convertUrlToHtmlEntity($linkUrl) . '" class="pathway">' . $this->convertToDispString($pageName) . '</a>';
180 // getHeadSubTitle()はバージョン1.10.9以降利用可能
181 if (version_compare(M3_SYSTEM_VERSION, '1.10.9') >= 0){
182 // コンテンツ名が設定されている場合は出力
183 $titleArray = $this->gPage->getHeadSubTitle();
184 if (count($titleArray) > 0){
185 $html .= $this->createTitleLink($titleArray);
191 $menuId = $menuItems[$i]['md_menu_id'];
194 $this->menuItems = array();
195 for ($i = 0; $i < count($menuItems); $i++){
196 $key = $menuItems[$i][md_id];
197 $this->menuItems[$key] = $menuItems[$i];
201 $menuPathArray = array();
202 $ret = $this->createMenuPath($menuItemId, $menuPathArray);
203 $menuPathArray = array_reverse($menuPathArray); // パスを反転
205 // ローカルメニューの場合とグローバルメニューの場合と処理を分ける
207 for ($i = 0; $i < count($allMenu); $i++){
208 if ($menuId == $allMenu[$i]['pd_menu_id']){
209 $pageSubId = $allMenu[$i]['pd_sub_id'];
213 if (!empty($pageSubId)){ // ローカルメニューのとき
214 // グローバルメニューの該当ページを取得
215 $globalMenuItemId = 0;
216 for ($i = 0; $i < count($menuItems); $i++){
217 $url = $menuItems[$i]['md_link_url']; // マクロ表記URLを取得
218 if ($this->isPageUrl($url, $pageSubId)){
219 $globalMenuItemId = $menuItems[$i]['md_id'];
223 if (!empty($globalMenuItemId)){
225 $pathArray = $menuPathArray;
226 $menuPathArray = array();
227 $ret = $this->createMenuPath($globalMenuItemId, $menuPathArray);
228 $menuPathArray = array_reverse($menuPathArray); // パスを反転
231 $menuPathArray = array_merge($menuPathArray, $pathArray);
235 $html = $this->createLink($menuPathArray);
237 if (!empty($html)){ // リンクが空のときは表示しない
238 $linkUrl = $this->getUrl($homeUrl, true/*リンク用*/);
239 $html = '<a href="' . $this->convertUrlToHtmlEntity($linkUrl) . '" class="pathway">' . $this->convertToDispString($homeName) . '</a>' . $this->iconTag . $html;// リンクの間にアイコンを挿入
240 $html = '<span class="breadcrumbs pathway">' . $html . '</span>';
241 $this->tmpl->addVar("_widget", "link", $html);
247 * @param RequestManager $request HTTPリクエスト処理クラス
248 * @param object $param 任意使用パラメータ。そのまま_assign()に渡る
249 * @return string ウィジェットのタイトル名
251 function _setTitle($request, &$param)
253 return self::DEFAULT_TITLE;
258 * @param int $menuItemId メニュー項目ID
259 * @param array $menuPathArray メニューID
260 * @param int $level 階層数
261 * @return bool true=正常終了、false=異常終了
263 function createMenuPath($menuItemId, &$menuPathArray, $level = 0)
266 if ($level >= self::MAX_MENU_TREE_LEVEL) return false;
268 if (empty($menuItemId)) return true; // メニューIDが0のときは終了
271 $menuPathArray[] = $menuItemId;
274 $menuItemInfo = $this->menuItems[$menuItemId];
275 if (isset($menuItemInfo)){
277 $parentId = $menuItemInfo['md_parent_id'];
278 $ret = $this->createMenuPath($parentId, $menuPathArray, $level + 1);
287 * @param array $menuPathArray メニューパス
288 * @return string HTML出力
290 function createLink($menuPathArray)
294 $linkCount = count($menuPathArray);
295 for ($i = 0; $i < $linkCount; $i++){
296 $menuItemId = $menuPathArray[$i];
299 $linkUrl = $this->menuItems[$menuItemId]['md_link_url'];
300 $linkUrl = $this->getUrl($linkUrl, true/*リンク用*/);
303 $name = $this->getCurrentLangString($this->menuItems[$menuItemId]['md_name']);
304 if (empty($name)) $name = self::MENU_ITEM_NONAME;
307 if ($i > 0) $outputHtml .= $this->iconTag;
309 if (empty($linkUrl) || $i == $linkCount -1){ // 最後の項目はリンク作成しない
310 $outputHtml .= $this->convertToDispString($name) . M3_NL;
312 $outputHtml .= '<a href="' . $this->convertUrlToHtmlEntity($linkUrl) . '" class="pathway">' . $this->convertToDispString($name) . '</a>' . M3_NL;
320 * @param array $titleArray タイトル情報
321 * @return string HTML出力
323 function createTitleLink($titleArray)
327 $linkCount = count($titleArray);
328 for ($i = 0; $i < $linkCount; $i++){
329 $line = $titleArray[$i];
332 $linkUrl = $this->getUrl($line['url'], true/*リンク用*/);
335 $name = $line['title'];
336 if (empty($name)) $name = self::MENU_ITEM_NONAME;
339 $outputHtml .= $this->iconTag;
341 if (empty($linkUrl) || $i == $linkCount -1){ // 最後の項目はリンク作成しない
342 $outputHtml .= $this->convertToDispString($name) . M3_NL;
344 $outputHtml .= '<a href="' . $this->convertUrlToHtmlEntity($linkUrl) . '" class="pathway">' . $this->convertToDispString($name) . '</a>' . M3_NL;
350 * メニュー項目のURLが現在のアクセス中のURLか判断
352 * @param string $url チェック対象のURL
353 * @return bool true=アクセス中、false=非アクセス
355 function isCurrentMenuItemUrl($url)
358 if ($url == $this->currentMacroUrl) return true;
361 $queryArray = array();
362 list($tmp, $queryStr) = explode('?', $url);
363 list($queryStr, $tmp) = explode('#', $queryStr);
364 if (!empty($queryStr)) parse_str($queryStr, $queryArray); // クエリーの解析
367 // $diffArray = array_diff($this->currentQueryArray, $queryArray);
368 $diffArray = array_diff_assoc($this->currentQueryArray, $queryArray);
369 if (empty($diffArray)) return true;
374 * URLがルートを指しているかどうか取得
376 * @param string $url チェック対象のURL(マクロ表記)
377 * @return bool true=ルート、false=ルート以外
379 function isRootUrl($url)
381 //$parsedUrl = parse_url($url);
382 //if (empty($parsedUrl['query'])){
383 list($tmp, $query) = explode('?', $url);
384 if (!empty($query)) list($query, $tmp) = explode('#', $query);
385 if (empty($query)){ // クエリ文字列がないことが条件。「#」はあっても良い。
387 $relativePath = str_replace(M3_TAG_START . M3_TAG_MACRO_ROOT_URL . M3_TAG_END, '', $url); // ルートURLからの相対パスを取得
388 if (empty($relativePath)){ // Magic3のルートURLの場合
390 } else if (strStartsWith($relativePath, '/') || strStartsWith($relativePath, '/' . M3_FILENAME_INDEX)){ // ルートURL配下のとき
397 * URLが指定のページを示すかどうか判断
399 * @param string $url チェック対象のURL
400 * @param string $pageSubId ページサブID
401 * @return bool true=指定のページを示す、false=指定のページ外
403 function isPageUrl($url, $pageSubId)
406 $queryArray = array();
407 list($tmp, $queryStr) = explode('?', $url);
408 list($queryStr, $tmp) = explode('#', $queryStr);
409 if (!empty($queryStr)) parse_str($queryStr, $queryArray); // クエリーの解析
411 // パラメータがサブページIDだけの場合はページサブIDで比較
412 if (count($queryArray) == 1 && isset($queryArray[M3_REQUEST_PARAM_PAGE_SUB_ID])){
413 if ($queryArray[M3_REQUEST_PARAM_PAGE_SUB_ID] == $pageSubId) return true;