EC-CUBE2.12:メッセージが流れるティッカー

1 管理画面でメッセージを登録できるようにする。

(1)データベースへテーブル(dtb_ticker)の追加

【MySQL・PostgreSQL】

CREATE TABLE dtb_ticker (
ticker_id int NOT NULL,
disp smallint NOT NULL DEFAULT 1,
message text,
url text,
rank int NOT NULL DEFAULT 0,
creator_id int NOT NULL,
create_date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
update_date timestamp NOT NULL,
del_flg smallint NOT NULL DEFAULT 0,
PRIMARY KEY (ticker_id)
);


(2)管理画面用ファイルの作成

 ■html/admin/contents/ticker.php

<?php
// {{{ requires
require_once '../require.php';
require_once CLASS_EX_REALDIR . 'page_extends/admin/contents/LC_Page_Admin_Contents_Ticker_Ex.php';

// }}}
// {{{ generate page

$objPage = new LC_Page_Admin_Contents_Ticker_Ex();
register_shutdown_function(array($objPage, 'destroy'));
$objPage->init();
$objPage->process();
?>

 ■data/class_extends/page_extends/admin/contents/LC_Page_Admin_Contents_Ticker_Ex.php

<?php
// {{{ requires
require_once CLASS_REALDIR . 'pages/admin/contents/LC_Page_Admin_Contents_Ticker.php';

class LC_Page_Admin_Contents_Ticker_Ex extends LC_Page_Admin_Contents_Ticker {

// }}}
// {{{ functions

/**
* Page を初期化する.
*
* @return void
*/
function init() {
parent::init();
}

/**
* Page のプロセス.
*
* @return void
*/
function process() {
parent::process();
}

/**
* デストラクタ.
*
* @return void
*/
function destroy() {
parent::destroy();
}
}
?>

 ■data/class/pages/admin/contents/LC_Page_Admin_Contents_Ticker.php

<?php

// {{{ requires
require_once CLASS_EX_REALDIR . 'page_extends/admin/LC_Page_Admin_Ex.php';

/**
* ティッカー のページクラス.
*
* @package Page
* @author LOCKON CO.,LTD.
* @version $Id: LC_Page_Admin_Basis_Ticker.php 21185 2011-08-11 10:37:10Z shutta $
*/
class LC_Page_Admin_Contents_Ticker extends LC_Page_Admin_Ex {

// }}}
// {{{ functions

/**
* Page を初期化する.
*
* @return void
*/
function init() {
parent::init();
$this->tpl_mainpage = 'contents/ticker.tpl';
$this->tpl_subno = 'ticker';
$masterData = new SC_DB_MasterData_Ex();
$this->arrDISP = $masterData->getMasterData('mtb_disp');
$this->tpl_maintitle = 'コンテンツ管理';
$this->tpl_subtitle = '流れるメッセージ編集';
$this->tpl_mainno = 'contents';
}

/**
* Page のプロセス.
*
* @return void
*/
function process() {
$this->action();
$this->sendResponse();
}

/**
* Page のアクション.
*
* @return void
*/
function action() {
$objDb = new SC_Helper_DB_Ex();

$mode = $this->getMode();

if (!empty($_POST)) {
$objFormParam = new SC_FormParam_Ex();
$this->lfInitParam($mode, $objFormParam);
$objFormParam->setParam($_POST);
$objFormParam->convParam();
$ticker_id = $objFormParam->getValue('ticker_id');

$this->arrErr = $this->lfCheckError($mode, $objFormParam);
if (!empty($this->arrErr['ticker_id'])) {
SC_Utils_Ex::sfDispException();
return;
}
$post = $objFormParam->getHashArray();
}

// 要求判定
switch($mode) {
// 編集処理
case 'edit':
// POST値の引き継ぎ
$this->arrForm = $_POST;

if(count($this->arrErr) <= 0) {
if($post['ticker_id'] == '') {
$this->lfInsertClass($this->arrForm, $_SESSION['member_id']);    // 新規作成
} else {
$this->lfUpdateClass($this->arrForm, $post['ticker_id']);    // 既存編集
}
// 再表示
$this->objDisplay->reload();
} else {
// POSTデータを引き継ぐ
$this->tpl_ticker_id = $post['ticker_id'];
}
break;
// 削除
case 'delete':
$objDb->sfDeleteRankRecord('dtb_ticker', 'ticker_id', $post['ticker_id'], '', true);
// 再表示
$this->objDisplay->reload();
break;
// 編集前処理
case 'pre_edit':
// 編集項目を取得する。
$arrTickerData = $this->lfGetTickerDataByTickerID($post['ticker_id']);

// 入力項目にカテゴリ名を入力する。
$this->arrForm['disp'] = $arrTickerData[0]['disp'];
$this->arrForm['area'] = $arrTickerData[0]['area'];
$this->arrForm['message'] = $arrTickerData[0]['message'];
$this->arrForm['url'] = $arrTickerData[0]['url'];
// POSTデータを引き継ぐ
$this->tpl_ticker_id = $post['ticker_id'];
break;
case 'down':
$objDb->sfRankDown('dtb_ticker', 'ticker_id', $post['ticker_id']);
// 再表示
$this->objDisplay->reload();
break;
case 'up':
$objDb->sfRankUp('dtb_ticker', 'ticker_id', $post['ticker_id']);
// 再表示
$this->objDisplay->reload();
break;
default:
break;
}

$this->arrTicker = $this->lfGetTickerList();
// POSTデータを引き継ぐ
$this->tpl_ticker_id = $ticker_id;
}

/**
* デストラクタ.
*
* @return void
*/
function destroy() {
parent::destroy();
}

/* DBへの挿入 */
function lfInsertClass($arrData, $member_id) {
$objQuery =& SC_Query_Ex::getSingletonInstance();
// INSERTする値を作成する。
$sqlval['disp'] = $arrData['disp'];
$sqlval['message'] = $arrData['message'];
$sqlval['url'] = $arrData['url'];
$sqlval['creator_id'] = $member_id;
$sqlval['rank'] = $objQuery->max('rank', 'dtb_ticker') + 1;
$sqlval['update_date'] = 'CURRENT_TIMESTAMP';
$sqlval['create_date'] = 'CURRENT_TIMESTAMP';
// INSERTの実行
$sqlval['ticker_id'] = $objQuery->nextVal('dtb_ticker_ticker_id');
$ret = $objQuery->insert('dtb_ticker', $sqlval);
return $ret;
}

function lfGetTickerDataByTickerID($ticker_id) {
$objQuery =& SC_Query_Ex::getSingletonInstance();

$where = 'ticker_id = ?';
return $objQuery->select('url, message, disp', 'dtb_ticker', $where, array($ticker_id));
}

function lfGetTickerList() {
$objQuery =& SC_Query_Ex::getSingletonInstance();

$where = 'del_flg <> 1';
$objQuery->setOrder('rank DESC');
return $objQuery->select('message, url, ticker_id, disp', 'dtb_ticker', $where);
}

/* DBへの更新 */
function lfUpdateClass($arrData, $ticker_id) {
$objQuery =& SC_Query_Ex::getSingletonInstance();
// UPDATEする値を作成する。
$sqlval['disp'] = $arrData['disp'];
$sqlval['message'] = $arrData['message'];
$sqlval['url'] = $arrData['url'];
$sqlval['update_date'] = 'CURRENT_TIMESTAMP';
$where = 'ticker_id = ?';
// UPDATEの実行
$ret = $objQuery->update('dtb_ticker', $sqlval, $where, array($ticker_id));
return $ret;
}

function lfInitParam($mode, &$objFormParam) {
switch ($mode) {
case 'edit':
$objFormParam->addParam('公開・非公開', 'disp', INT_LEN, 'n', array('NUM_CHECK','MAX_LENGTH_CHECK'));
$objFormParam->addParam('メッセージ', 'message', MLTEXT_LEN, 'KVa', array('EXIST_CHECK','MAX_LENGTH_CHECK'));
$objFormParam->addParam('リンク先', 'url', MLTEXT_LEN, 'KVa', array('SPTAB_CHECK','MAX_LENGTH_CHECK'));
case 'delete':
case 'pre_edit':
case 'down':
case 'up':
$objFormParam->addParam('ID', 'ticker_id', INT_LEN, 'n', array('NUM_CHECK', 'MAX_LENGTH_CHECK'));
break;
default:
break;
}
}

/**
* 入力エラーチェック
*
* @param string $mode
* @return array
*/
function lfCheckError($mode, $objFormParam) {
$arrErr = $objFormParam->checkError();
if(!isset($arrErr['name']) && $mode == 'edit') {
$post = $objFormParam->getHashArray();
$objQuery =& SC_Query_Ex::getSingletonInstance();
$arrRet = $objQuery->select('ticker_id, message', 'dtb_ticker', 'del_flg = 0 AND message = ?', array($post['message']));
// 編集中のレコード以外に同じ名称が存在する場合
if ($arrRet[0]['ticker_id'] != $post['ticker_id'] && $arrRet[0]['message'] == $post['message']) {
$arrErr['name'] = '';
}
}
}
}
?>

 ■data/Smarty/templates/admin/contents/ticker.tpl

<form name="form1" id="form1" method="post" action="?">
<input type="hidden" name="<!--{$smarty.const.TRANSACTION_ID_NAME}-->" value="<!--{$transactionid}-->" />
<input type="hidden" name="mode" value="edit" />
<input type="hidden" name="ticker_id" value="<!--{$tpl_ticker_id}-->" />
<div id="contents"  class="contents-main">
<table class="form">
<col width="16%" />
<col width="42%" />
<col width="42%" />
<tr>
<th>表示・非表示</th>
<th>メッセージ<span class="attention"> *</span></th>
<th>リンクURL</th>
</tr>
<tr>
<td class="radio">
<!--{html_radios name="disp" options=$arrDISP selected=$arrForm.disp separator='&nbsp;&nbsp;'}-->
</td>
<td>
<span class="attention"><!--{$arrErr.message}--></span>
<input type="text" name="message" value="<!--{$arrForm.message|h}-->" maxlength="<!--{$smarty.const.SMTEXT_LEN}-->" size="50" class="box50" style="<!--{if $arrErr.message != "" || $arrErr.name != ""}-->background-color: <!--{$smarty.const.ERR_COLOR}-->;<!--{/if}-->" />
</td>
<td>
<span class="attention"><!--{$arrErr.url}--></span>
<input type="text" name="url" value="<!--{$arrForm.url|h}-->" maxlength="<!--{$smarty.const.MTEXT_LEN}-->" size="50" class="box50">
</td>
</tr>
</table>

<div class="btn-area">
<ul>
<li><a class="btn-action" href="javascript:;" onclick="fnFormModeSubmit('form1', 'edit', '', ''); return false;"><span class="btn-next">この内容で登録する</span></a></li>
</ul>
</div>

<table class="list">
<col width="16%">
<col width="31%">
<col width="31%">
<col width="6%">
<col width="6%">
<colg width="10%">
<tr>
<th>表示・非表示</th>
<th>メッセージ<span class="attention"> *</span></th>
<th>リンクURL</th>
<th>編集</th>
<th>削除</th>
<th>移動</th>
</tr>
<!--{section name=cnt loop=$arrTicker}-->
<tr <!--{if $arrTicker[cnt].disp == 2}-->style="background-color:#ddd;"<!--{/if}-->>
<!--{assign var=ticker_id value=$arrTicker[cnt].ticker_id}-->
<!--{if $arrTicker[cnt].disp == 1}--><td class="center">公開</td><!--{elseif $arrTicker[cnt].disp == 2}--><td class="center">非公開</td><!--{else}--><td class="center attention">選択されていません</td><!--{/if}-->
<td style="text-align:left;"><!--{$arrTicker[cnt].message|h|nl2br}--></td>
<td style="text-align:left;"><!--{$arrTicker[cnt].url|h}--></td>
<td class="center">
<!--{if $tpl_ticker_id != $arrTicker[cnt].ticker_id}-->
<a href="?" onclick="fnModeSubmit('pre_edit', 'ticker_id', <!--{$arrTicker[cnt].ticker_id}-->); return false;">編集</a>
<!--{else}-->
編集中
<!--{/if}-->
</td>
<td class="center">
<!--{if $arrClassCatCount[$class_id] > 0}-->
-
<!--{else}-->
<a href="?" onclick="fnModeSubmit('delete', 'ticker_id', <!--{$arrTicker[cnt].ticker_id}-->); return false;">削除</a>
<!--{/if}-->
</td>
<td class="center">
<!--{if $smarty.section.cnt.iteration != 1}-->
<a href="?" onclick="fnModeSubmit('up', 'ticker_id', <!--{$arrTicker[cnt].ticker_id}-->); return false;">上へ</a>
<!--{/if}-->
<!--{if $smarty.section.cnt.iteration != $smarty.section.cnt.last}-->
<a href="?" onclick="fnModeSubmit('down', 'ticker_id', <!--{$arrTicker[cnt].ticker_id}-->); return false;">下へ</a>
<!--{/if}-->
</td>
</tr>
<!--{/section}-->
</table>

</div>
</form>

 ■data/Smarty/templates/admin/contents/subnavi.tpl 下記追加

<li<!--{if $tpl_subno == 'ticker'}--> class="on"<!--{/if}--> id="navi-contents-ticker"><a href="<!--{$smarty.const.ROOT_URLPATH}--><!--{$smarty.const.ADMIN_DIR}-->contents/ticker.php"><span>ティッカー管理</span></a></li>

2 フロント画面に表示する

(1)下記より、jQueryプラグイン「carouFredSel」をダウンロードし、■html/js/jquery.caroufredselフォルダに置く。

http://caroufredsel.frebsite.nl/

(2)■data/Smarty/templates/default/site_frame.tpl 追加

<!--caroufredsel-->
<script type="text/javascript" src="<!--{$smarty.const.ROOT_URLPATH}-->js/jquery.caroufredsel/jquery.carouFredSel-5.6.4.js"></script>

(3)ブロックを新規作成する

 ■html/frontparts/bloc/ticker.php

<?php

// {{{ requires
require_once realpath(dirname(__FILE__)) . '/../../require.php';
require_once CLASS_EX_REALDIR . 'page_extends/frontparts/bloc/LC_Page_FrontParts_Bloc_Ticker_Ex.php';

// }}}
// {{{ generate page

$objPage = new LC_Page_FrontParts_BLoc_Ticker_Ex();
$objPage->blocItems = $params['items'];
register_shutdown_function(array($objPage, "destroy"));
$objPage->init();
$objPage->process();
?>

 ■data/class_extends/page_extends/frontparts/bloc/LC_Page_FrontParts_Bloc_Ticker_Ex.php

<?php

// {{{ requires
require_once CLASS_REALDIR . 'pages/frontparts/bloc/LC_Page_FrontParts_Bloc_Ticker.php';

class LC_Page_FrontParts_Bloc_Ticker_Ex extends LC_Page_FrontParts_Bloc_Ticker {

// }}}
// {{{ functions

/**
* Page を初期化する.
*
* @return void
*/
function init() {
parent::init();
}

/**
* Page のプロセス.
*
* @return void
*/
function process() {
parent::process();
}

/**
* デストラクタ.
*
* @return void
*/
function destroy() {
parent::destroy();
}
}
?>

 ■data/class/pages/frontparts/bloc/LC_Page_FrontParts_Bloc_Ticker.php

<?php

// {{{ requires
require_once CLASS_REALDIR . 'pages/frontparts/bloc/LC_Page_FrontParts_Bloc.php';

class LC_Page_FrontParts_Bloc_Ticker extends LC_Page_FrontParts_Bloc {

// }}}
// {{{ functions

/**
* Page を初期化する.
*
* @return void
*/
function init() {
parent::init();
$this->setTplMainpage('ticker.tpl'); //include_phpを可能にする。
}

/**
* Page のプロセス.
*
* @return void
*/
function process() {
$this->action();
$this->sendResponse();
}

/**
* Page のアクション.
*
* @return void
*/
function action() {

// データベースから取得
$objQuery =& SC_Query_Ex::getSingletonInstance();
$this->arrRet = array();

//ティッカーを取得
$arrRet = $objQuery->select('*','dtb_ticker','del_flg = 0 and disp = 1 order by rank');

//データベースから取得できたか
if(isset($arrRet)){
$this->arrRet = $arrRet;
}
}

/**
* デストラクタ.
*
* @return void
*/
function destroy() {
parent::destroy();
}
}
?>

 ■data/Smarty/templates/default/frontparts/bloc/ticker.tpl

<!--▼ティッカー-->
<!--{if count($arrRet) > 0}-->
<script type="text/javascript">
$(function() {
var _scroll = {
delay: 1000,
easing: 'linear',
items: 1,
duration: 0.07,
timeoutDuration: 0,
pauseOnHover: 'immediate'
};
$('#ticker-1').carouFredSel({
width: 578, //pxで指定。ブロックを配置するカラムの幅に合わせます。ここで幅を指定しないときは、文の長さによって幅が決まります。
align: false,
items: {
width: 'variable',
height:20,
visible: 1
},
scroll: _scroll
});

});
</script>
<div id="ticker">
<div class="block_outer">
<div id="ticker_area">
<div id="ticker-1" class="block_body>
<!--{section name=cnt loop=$arrRet}-->
<div class="message"><!--{if $arrRet[cnt].url}--><a href="<!--{$arrRet[cnt].url|h}-->"><!--{/if}--><!--{$arrRet[cnt].message|h}--><!--{if $arrRet[cnt].url}--></a><!--{/if}--></div>
<!--{/section}-->
</div>
</div>
</div>
</div>
<!--{/if}-->

 ■html/user_data/packages/default/css/bloc.css

/* ===============================================
▼ティッカー(流れるメッセージ)
=============================================== */
#ticker .block_outer {
margin-bottom:0;
}
#ticker_area .block_body {
overflow:hidden;
border:none;
height:20px;
}
#ticker_area .message {
float:left;
display:inline;
margin-right:20px;
background:url(../img/icon/ico_arrow_03.gif) 0 4px no-repeat;
padding-left:12px;
}

(4)データベースにブロックを登録し、管理画面で配置できるようにする。
(下記の「20」は、環境に応じて)

INSERT INTO dtb_bloc (device_type_id, bloc_id, bloc_name, tpl_path, filename, create_date, update_date, php_path, deletable_flg, plugin_id) VALUES (10, 20, 'ティッカー', 'ticker.tpl', 'ticker', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'frontparts/bloc/ticker.php', 0, NULL);