source: branches/version-2_12-dev/data/class/pages/LC_Page_Sitemap.php @ 22206

Revision 22206, 10.8 KB checked in by kim, 11 years ago (diff)

#2003 copyrightを2013に更新

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-httpd-php; charset=UTF-8
RevLine 
[16385]1<?php
2/*
[16582]3 * This file is part of EC-CUBE
4 *
[22206]5 * Copyright(c) 2000-2013 LOCKON CO.,LTD. All Rights Reserved.
[16385]6 *
7 * http://www.lockon.co.jp/
[16582]8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
[16385]22 */
23
24// {{{ requires
[20534]25require_once CLASS_EX_REALDIR . 'page_extends/LC_Page_Ex.php';
[16385]26
27/**
28 * Sitemapプロトコル ファイル生成モジュール.
29 * PHP versions 4 and 5
30 *
31 * <pre>
32 * このモジュールは Sitemapプロトコルに対応した XMLファイルを出力する.
33 * EC-CUBE インストールディレクトリの htmlディレクトリへ配置することにより動作する.
34 *
35 * このモジュールにより, 以下のページのサイトマップが生成される.
36 * 1. $staticURL で指定したページ
37 * 2. 管理画面のデザイン管理から生成したページ
38 * 3. 公開されているすべての商品一覧ページ
39 * 4. 公開されているすべての商品詳細ページ
40 *
41 * このモジュールを設置後, 各検索エンジンにサイトマップを登録することにより, 検索エンジンの
42 * インデックス化が促進される.
43 * </pre>
44 * @see https://www.google.com/webmasters/tools/siteoverview?hl=ja
45 * @see https://siteexplorer.search.yahoo.com/mysites
46 *
47 * @author Kentaro Ohkouchi
48 * @version $Id:sitemap.php 15532 2007-08-31 14:39:46Z nanasess
49 *
50 * :TODO: 各ページの changefreq や priority を指定できるようにする
51 * :TODO: filemtime 関数を使えば、静的なページの更新時間も取得できそう
52 */
[20344]53class LC_Page_Sitemap extends LC_Page_Ex {
[16385]54
55    // }}}
56    // {{{ properties
57
58    /** 動的に生成しないページの配列 */
59    var $staticURL;
60
61    /** ページリスト */
62    var $arrPageList;
63
64    // }}}
65    // {{{ functions
66
67    /**
68     * Page を初期化する.
69     *
70     * @return void
71     */
72    function init() {
73        parent::init();
[20540]74
[17607]75        $this->staticURL = array();
[20540]76
[19998]77        $this->staticURL[] = HTTP_URL . 'rss/' . DIR_INDEX_PATH;
[16385]78    }
79
80    /**
81     * Page のプロセス.
82     *
83     * @return void
84     */
85    function process() {
86        // ページのデータを取得
[20946]87        // FIXME PCサイトのみに限定している。ある程度妥当だとは思うが、よりベターな方法はないだろうか。
88        $this->arrPageList = $this->getPageData('device_type_id = ?', DEVICE_TYPE_PC);
[16385]89
90        //キャッシュしない(念のため)
[21514]91        header('Paragrama: no-cache');
[16385]92
93        //XMLテキスト
[21514]94        header('Content-type: application/xml; charset=utf-8');
[16385]95
96        // 必ず UTF-8 として出力
[21514]97        mb_http_output('UTF-8');
[16385]98        ob_start('mb_output_handler');
99
[20538]100        echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
101        echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
[16385]102
103        // TOPページを処理
[20098]104        $arrTopPagesList = $this->getTopPage($this->arrPageList);
105        $this->createSitemap($arrTopPagesList[0]['url'],
106                             $this->date2W3CDatetime($arrTopPagesList[0]['update_date']),
[16385]107                             'daily', 1.0);
108
[17602]109        // 静的なページを処理
110        foreach ($this->staticURL as $url) {
111            $this->createSitemap($url, '', 'daily', 1.0);
112        }
113
[16385]114        // 編集可能ページを処理
[20098]115        $arrEditablePagesList = $this->getEditablePage($this->arrPageList);
116        foreach ($arrEditablePagesList as $arrEditablePage) {
117            $this->createSitemap($arrEditablePage['url'],
118                                 $this->date2W3CDatetime($arrEditablePage['update_date']));
[16385]119        }
120
121        // 商品一覧ページを処理
[20098]122        $arrProductPagesList = $this->getAllProducts();
123        foreach ($arrProductPagesList as $arrProductPage) {
124            $this->createSitemap($arrProductPage['url'], '', 'daily');
[16385]125        }
126
127        // 商品詳細ページを処理
[20098]128        $arrDetailPagesList = $this->getAllDetail();
129        foreach ($arrDetailPagesList as $arrDetailPage) {
130            $this->createSitemap($arrDetailPage['url'],
131                                 $this->date2W3CDatetime($arrDetailPage['update_date']));
[16385]132        }
133
[20538]134        echo '</urlset>' . "\n";
[16385]135    }
136
137    /**
138     * デストラクタ.
139     *
140     * @return void
141     */
142    function destroy() {
143        parent::destroy();
144    }
145
146    /**
147     * Sitemap の <url /> を生成する.
148     *
149     * @param string $loc ページの URL ※必須
150     * @param string $lastmod ファイルの最終更新日 YYYY-MM-DD or W3C Datetime 形式
151     * @param string $changefreq ページの更新頻度
152     * @param double $priority URL の優先度
153     * @return Sitemap 形式の <url />
154     * @see https://www.google.com/webmasters/tools/docs/ja/protocol.html#xmlTagDefinitions
155     * TODO Smarty に移行すべき?
156     */
[21527]157    function createSitemap($loc, $lastmod = '', $changefreq = '', $priority = '') {
[16385]158        printf("\t<url>\n");
[21593]159        printf("\t\t<loc>%s</loc>\n", htmlentities($loc, ENT_QUOTES, 'UTF-8'));
[16385]160        if (!empty($lastmod)) {
161            printf("\t\t<lastmod>%s</lastmod>\n", $lastmod);
162        }
163        if (!empty($changefreq)) {
164            printf("\t\t<changefreq>%s</changefreq>\n", $changefreq);
165        }
[21441]166        if (!empty($priority)) {
[16385]167            printf("\t\t<priority>%01.1f</priority>\n", $priority);
168        }
169        printf("\t</url>\n");
170    }
171
172    /**
173     * TOPページの情報を取得する.
174     *
[20098]175     * @param array $arrPageList すべてのページ情報の配列
[16385]176     * @return array TOPページの情報
177     */
[20098]178    function getTopPage($arrPageList) {
[16385]179        $arrRet = array();
[20098]180        foreach ($arrPageList as $arrPage) {
[21481]181            if ($arrPage['page_id'] == '1') {
[20098]182                $arrRet[0] = $arrPage;
[16385]183                return $arrRet;
184            }
185        }
186    }
187
188    /**
189     * すべての編集可能ページの情報を取得する.
190     *
[20098]191     * @param array $arrPageList すべてのページ情報の配列
[16385]192     * @return array 編集可能ページ
193     */
[20098]194    function getEditablePage($arrPageList) {
[16385]195        $arrRet = array();
[20098]196        foreach ($arrPageList as $arrPage) {
197            if ($arrPage['page_id'] > 4) {
198                $arrRet[] = $arrPage;
[16385]199            }
200        }
201        return $arrRet;
202    }
203
204    /**
205     * すべての商品一覧ページを取得する.
206     *
207     * @return array 検索エンジンからアクセス可能な商品一覧ページの情報
208     */
[17558]209    function getAllProducts() {
[20540]210
[21317]211        // XXX: 商品登録の無いカテゴリは除外する方が良い気もする
[20507]212        $objQuery = SC_Query_Ex::getSingletonInstance();
[21514]213        $sql = 'SELECT category_id FROM dtb_category WHERE del_flg = 0';
[18772]214        $result = $objQuery->getAll($sql);
[16385]215
216        $arrRet = array();
[17558]217        foreach ($result as $row) {
[16385]218            // :TODO: カテゴリの最終更新日を取得できるようにする
[20540]219
[20538]220            $arrPage['url'] = HTTP_URL . 'products/list.php?category_id=' . $row['category_id'];
[20098]221            $arrRet[] = $arrPage;
[16385]222        }
223        return $arrRet;
224    }
225
226    /**
227     * すべての商品詳細ページを取得する.
228     *
229     * @return array 検索エンジンからアクセス可能な商品詳細ページの情報
230     */
[17558]231    function getAllDetail() {
[20507]232        $objQuery = SC_Query_Ex::getSingletonInstance();
[21514]233        $sql = 'SELECT product_id, update_date FROM dtb_products WHERE del_flg = 0 AND status = 1';
[18772]234        $result = $objQuery->getAll($sql);
[16385]235
236        $arrRet = array();
[17558]237        foreach ($result as $row) {
[20540]238
[21481]239            $arrPage['update_date'] = $row['update_date'];
[20540]240
[20538]241            $arrPage['url'] = HTTP_URL . substr(P_DETAIL_URLPATH, strlen(ROOT_URLPATH)) . $row['product_id'];
[20098]242            $arrRet[] = $arrPage;
[16385]243        }
244        return $arrRet;
245    }
246
247    /**
248     * ブロック情報を取得する.
249     *
250     * @param string $where WHERE句
251     * @param array  $arrVal WHERE句の値を格納した配列
[20098]252     * @return array $arrPageList ブロック情報
[16385]253     */
[21479]254    function getPageData($where = '', $arrVal = '') {
[20507]255        $objQuery = SC_Query_Ex::getSingletonInstance();     // DB操作オブジェクト
[21514]256        $sql = '';                      // データ取得SQL生成用
[17558]257        $arrRet = array();              // データ取得用
[16385]258
259        // SQL生成(url と update_date 以外は不要?)
[21514]260        $sql .= ' SELECT';
261        $sql .= ' page_id';             // ページID
262        $sql .= ' ,page_name';          // 名称
263        $sql .= ' ,url';                // URL
264        $sql .= ' ,filename';           // ファイル名称
265        $sql .= ' ,header_chk ';        // ヘッダー使用FLG
266        $sql .= ' ,footer_chk ';        // フッター使用FLG
267        $sql .= ' ,author';             // authorタグ
268        $sql .= ' ,description';        // descriptionタグ
269        $sql .= ' ,keyword';            // keywordタグ
270        $sql .= ' ,update_url';         // 更新URL
271        $sql .= ' ,create_date';        // データ作成日
272        $sql .= ' ,update_date';        // データ更新日
273        $sql .= ' FROM ';
274        $sql .= '     dtb_pagelayout';
[16385]275
276        // where句の指定があれば追加
277        if ($where != '') {
[21514]278            $sql .= ' WHERE ' . $where;
[16385]279        }
280
[21514]281        $sql .= ' ORDER BY page_id';
[16385]282
[20098]283        $arrPageList = $objQuery->getAll($sql, $arrVal);
[20540]284
[19802]285        // URL にプロトコルの記載が無い場合、HTTP_URL を前置する。
[21935]286        foreach ($arrPageList as $key => $value) {
[20098]287            $arrPage =& $arrPageList[$key];
288            if (!preg_match('|^https?://|i', $arrPage['url'])) {
289                $arrPage['url'] = HTTP_URL . $arrPage['url'];
[17602]290            }
[20098]291            $arrPage['url'] = preg_replace('|/' . preg_quote(DIR_INDEX_FILE) . '$|', '/' . DIR_INDEX_PATH, $arrPage['url']);
[17602]292        }
[20098]293        unset($arrPage);
[20540]294
[20098]295        return $arrPageList;
[16385]296    }
297
298    /**
299     * date形式の文字列を W3C Datetime 形式に変換して出力する.
300     *
301     * @param date $date 変換する日付
302     * @return void
303     */
304    function date2W3CDatetime($date) {
305        $arr = array();
306        // 正規表現で文字列を抽出
[21527]307        preg_match('/^([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})/', $date, $arr);
[16385]308        // :TODO: time zone も取得するべき...
[21514]309        return sprintf('%04d-%02d-%02dT%02d:%02d:%02d+09:00',
[16385]310                       $arr[1], $arr[2], $arr[3], $arr[4], $arr[5], $arr[6]);
311    }
312
313}
Note: See TracBrowser for help on using the repository browser.