3 * Ethna_SmartyPlugin.php
5 * @author Masaki Fujimoto <fujimoto@php.net>
6 * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
11 // {{{ smarty_modifier_number_format
13 * smarty modifier:number_format()
15 * number_format()関数のwrapper
19 * {"12345"|number_format}
25 * @param string $string フォーマット対象文字列
26 * @return string フォーマット済み文字列
28 function smarty_modifier_number_format($string)
30 if ($string === "" || $string == null) {
33 return number_format($string);
37 // {{{ smarty_modifier_strftime
39 * smarty modifier:strftime()
41 * strftime()関数のwrapper
45 * {"2004/01/01 01:01:01"|strftime:"%Y年%m月%d日"}
51 * @param string $string フォーマット対象文字列
52 * @param string $format 書式指定文字列(strftime()関数参照)
53 * @return string フォーマット済み文字列
55 function smarty_modifier_strftime($string, $format)
57 if ($string === "" || $string == null) {
60 return strftime($format, strtotime($string));
64 // {{{ smarty_modifier_count
66 * smarty modifier:count()
72 * $smarty->assign("array", array(1, 2, 3));
80 * @param array $array 対象となる配列
83 function smarty_modifier_count($array)
89 // {{{ smarty_modifier_join
91 * smarty modifier:join()
97 * $smarty->assign("array", array(1, 2, 3));
105 * @param array $array join対象の配列
106 * @param string $glue 連結文字列
107 * @return string 連結後の文字列
109 function smarty_modifier_join($array, $glue)
111 if (is_array($array) == false) {
114 return implode($glue, $array);
118 // {{{ smarty_modifier_filter
120 * smarty modifier:filter()
122 * 指定された連想配列のうち$keyで指定された要素のみを配列に再構成する
126 * $smarty->assign("array", array(
127 * array("foo" => 1, "bar" => 4),
128 * array("foo" => 2, "bar" => 5),
129 * array("foo" => 3, "bar" => 6),
132 * {$array|@filter:"foo"|@join:","}
138 * @param array $array filter対象となる配列
139 * @param string $key 抜き出して配列を構成する連想配列のキー
140 * @return array 再構成された配列
142 function smarty_modifier_filter($array, $key)
144 if (is_array($array) == false) {
148 foreach ($array as $v) {
149 if (isset($v[$key]) == false) {
158 // {{{ smarty_modifier_unique
160 * smarty modifier:unique()
166 * $smarty->assign("array1", array("a", "a", "b", "a", "b", "c"));
167 * $smarty->assign("array2", array(
168 * array("foo" => 1, "bar" => 4),
169 * array("foo" => 1, "bar" => 4),
170 * array("foo" => 1, "bar" => 4),
171 * array("foo" => 2, "bar" => 5),
172 * array("foo" => 3, "bar" => 6),
173 * array("foo" => 2, "bar" => 5),
177 * {$array2|@unique:"foo"}
184 * @param array $array 処理対象となる配列
185 * @param key $key 処理対象となるキー(nullなら配列要素)
186 * @return array 再構成された配列
188 function smarty_modifier_unique($array, $key = null)
190 if (is_array($array) == false) {
195 foreach ($array as $v) {
196 if (isset($v[$key]) == false) {
203 return array_unique($array);
208 // {{{ smarty_modifier_wordwrap_i18n
210 * smarty modifier:文字列のwordwrap処理
212 * [現在EUC-JP対応はEUC-JPのみ対応]
216 * {"あいうaえaおaかきaaaくけこ"|wordrap_i18n:8}
225 * @param string $string wordwrapする文字列
226 * @param string $break 改行文字
227 * @param int $width wordwrap幅(半角$width文字でwordwrapする)
228 * @param int $indent インデント幅(半角$indent文字)
229 * @return string wordwrap処理された文字列
231 function smarty_modifier_wordwrap_i18n($string, $width, $break = "\n", $indent = 0)
234 $i = "$break" . str_repeat(" ", $indent);
237 $n = strpos($tmp, $break);
238 if ($n !== false && $n < $width) {
239 $s = substr($tmp, 0, $n);
241 $tmp = substr($tmp, strlen($s) + strlen($break));
245 $s = mb_strimwidth($tmp, 0, $width, "", "EUC-JP");
249 if ($n >= $width && $tmp{$n} != "" && $tmp{$n} != " ") {
250 while ((ord($s{$n-1}) & 0x80) == 0) {
251 if ($s{$n-1} == " " || $n == 0) {
257 $s = substr($s, 0, $n);
260 $tmp = substr($tmp, strlen($s));
261 } while (strlen($s) > 0);
263 $r = preg_replace('/\s+$/', '', $r);
269 // {{{ smarty_modifier_truncate_i18n
271 * smarty modifier:文字列切り詰め処理(i18n対応)
275 * {"日本語です"|truncate_i18n:5:"..."}
281 * @param int $len 最大文字幅
282 * @param string $postfix 末尾に付加する文字列
284 function smarty_modifier_truncate_i18n($string, $len = 80, $postfix = "...")
286 return mb_strimwidth($string, 0, $len, $postfix);
290 // {{{ smarty_modifier_i18n
292 * smarty modifier:i18nフィルタ
302 * @param string $string i18n処理対象の文字列
303 * @return string ロケールに対応したメッセージ
305 function smarty_modifier_i18n($string)
307 $c =& Ethna_Controller::getInstance();
309 $i18n =& $c->getI18N();
311 return $i18n->get($string);
315 // {{{ smarty_modifier_checkbox
317 * smarty modifier:チェックボックス用フィルタ
321 * <input type="checkbox" name="test" {""|checkbox}>
322 * <input type="checkbox" name="test" {"1"|checkbox}>
325 * <input type="checkbox" name="test">
326 * <input type="checkbox" name="test" checkbox>
329 * @param string $string チェックボックスに渡されたフォーム値
330 * @return string $stringが空文字列あるいは0以外の場合は"checked"
332 function smarty_modifier_checkbox($string)
334 if ($string != "" && $string != 0) {
340 // {{{ smarty_modifier_select
342 * smarty modifier:セレクトボックス用フィルタ
344 * 単純なセレクトボックスの場合はsmarty関数"select"を利用することで
349 * $smarty->assign("form", 1);
351 * <option value="1" {$form|select:"1"}>foo</option>
352 * <option value="2" {$form|select:"2"}>bar</option>
355 * <option value="1" selected>foo</option>
356 * <option value="2" >bar</option>
359 * @param string $string セレクトボックスに渡されたフォーム値
360 * @param string $value <option>タグに指定されている値
361 * @return string $stringが$valueにマッチする場合は"selected"
363 function smarty_modifier_select($string, $value)
365 if ($string == $value) {
366 return 'selected="true"';
371 // {{{ smarty_modifier_form_value
373 * smarty modifier:フォーム値出力フィルタ
375 * フォーム名を変数で指定してフォーム値を取得したい場合に使用する
379 * $this->af->set('foo', 'bar);
380 * $smarty->assign('key', 'foo');
387 * @param string $string フォーム項目名
388 * @return string フォーム値
390 function smarty_modifier_form_value($string)
392 $c =& Ethna_Controller::getInstance();
393 $af =& $c->getActionForm();
395 $elts = explode(".", $string);
396 $r = $af->get($elts[0]);
397 for ($i = 1; $i < count($elts); $i++) {
401 return htmlspecialchars($r, ENT_QUOTES);
405 // {{{ smarty_function_is_error
407 * smarty function:指定されたフォーム項目でエラーが発生しているかどうかを返す
408 * NOTE: {if is_error('name')} は Ethna_Util.php の is_error() であって、
409 * smarty_function_is_error() ではないことに注意
411 * @param string $name フォーム項目名
413 function smarty_function_is_error($params, &$smarty)
415 $name = isset($params['name']) ? $params['name'] : null;
416 return is_error($name);
420 // {{{ smarty_function_message
422 * smarty function:指定されたフォーム項目に対応するエラーメッセージを出力する
426 * <input type="text" name="foo">{message name="foo"}
429 * <input type="text" name="foo">fooを入力してください
432 * @param string $name フォーム項目名
434 function smarty_function_message($params, &$smarty)
436 if (isset($params['name']) === false) {
440 $c =& Ethna_Controller::getInstance();
441 $action_error =& $c->getActionError();
443 $message = $action_error->getMessage($params['name']);
444 if ($message === null) {
448 $id = isset($params['id']) ? $params['id']
449 : str_replace("_", "-", "ethna-error-" . $params['name']);
450 $class = isset($params['class']) ? $params['class'] : "ethna-error";
451 return sprintf('<span class="%s" id="%s">%s</span>',
452 $class, $id, htmlspecialchars($message));
456 // {{{ smarty_function_uniqid
458 * smarty function:ユニークIDを生成する(double postチェック用)
465 * <input type="hidden" name="uniqid" value="a0f24f75e...e48864d3e">
468 * @param string $type 表示タイプ("get" or "post"−デフォルト="post")
469 * @see isDuplicatePost
471 function smarty_function_uniqid($params, &$smarty)
473 $uniqid = Ethna_Util::getRandom();
474 if (isset($params['type']) && $params['type'] == 'get') {
475 return "uniqid=$uniqid";
477 return "<input type=\"hidden\" name=\"uniqid\" value=\"$uniqid\" />\n";
482 // {{{ smarty_function_select
484 * smarty function:セレクトフィールド生成
486 * @param array $list 選択肢一覧
487 * @param string $name フォーム項目名
488 * @param string $value セレクトボックスに渡されたフォーム値
489 * @param string $empty 空エントリ(「---選択して下さい---」等)
492 function smarty_function_select($params, &$smarty)
496 print "<select name=\"$name\">\n";
498 printf("<option value=\"\">%s</option>\n", $empty);
500 foreach ($list as $id => $elt) {
501 printf("<option value=\"%s\" %s>%s</option>\n", $id, $id == $value ? 'selected="true"' : '', $elt['name']);
507 // {{{ smarty_function_checkbox_list
509 * smarty function:チェックボックスフィルタ関数(配列対応)
511 * @param string $form チェックボックスに渡されたフォーム値
512 * @param string $key 評価対象の配列インデックス
513 * @param string $value 評価値
516 function smarty_function_checkbox_list($params, &$smarty)
520 if (isset($key) == false) {
523 if (isset($value) == false) {
526 if (isset($checked) == false) {
527 $checked = "checked";
530 if (is_null($key) == false) {
531 if (isset($form[$key])) {
532 if (is_null($value)) {
535 if (strcmp($form[$key], $value) == 0) {
540 } else if (is_null($value) == false) {
541 if (is_array($form)) {
542 if (in_array($value, $form)) {
546 if (strcmp($value, $form) == 0) {
554 // {{{ smarty_function_url
556 * smarty function:url生成
558 function smarty_function_url($params, &$smarty)
560 $action = $path = $path_key = null;
563 foreach (array('action', 'anchor', 'scheme') as $key) {
564 if (isset($params[$key])) {
565 ${$key} = $params[$key];
572 $c =& Ethna_Controller::getInstance();
573 $config =& $c->getConfig();
574 $url_handler =& $c->getUrlHandler();
575 list($path, $path_key) = $url_handler->actionToRequest($action, $query);
578 if (is_array($path_key)) {
579 foreach ($path_key as $key) {
584 $query = $url_handler->buildActionParameter($query, $action);
586 $query = $url_handler->buildQueryParameter($query);
588 $url = sprintf('%s%s', $config->get('url'), $path);
590 if (preg_match('|^(\w+)://(.*)$|', $url, $match)) {
594 $match[2] = preg_replace('|/+|', '/', $match[2]);
595 $url = $match[1] . '://' . $match[2];
598 $url .= $query ? "?$query" : "";
599 $url .= $anchor ? "#$anchor" : "";
605 // {{{ smarty_function_form_name
607 * smarty function:フォーム表示名生成
609 * @param string $name フォーム項目名
611 function smarty_function_form_name($params, &$smarty)
614 if (isset($params['name'])) {
615 $name = $params['name'];
616 unset($params['name']);
622 $c =& Ethna_Controller::getInstance();
623 $view =& $c->getView();
624 if ($view === null) {
630 if (isset($params['action'])) {
631 $action = $params['action'];
632 unset($params['action']);
634 for ($i = count($smarty->_tag_stack); $i >= 0; --$i) {
635 if ($smarty->_tag_stack[$i][0] === 'form') {
636 if (isset($smarty->_tag_stack[$i][1]['ethna_action'])) {
637 $action = $smarty->_tag_stack[$i][1]['ethna_action'];
643 if ($action !== null) {
644 $view->addActionFormHelper($action);
647 return $view->getFormName($name, $action, $params);
651 // {{{ smarty_function_form_submit
653 * smarty function:フォームのsubmitボタン生成
655 * @param string $submit フォーム項目名
657 function smarty_function_form_submit($params, &$smarty)
659 $c =& Ethna_Controller::getInstance();
660 $view =& $c->getView();
661 if ($view === null) {
664 return $view->getFormSubmit($params);
668 // {{{ smarty_function_form_input
670 * smarty function:フォームタグ生成
672 * @param string $name フォーム項目名
674 function smarty_function_form_input($params, &$smarty)
677 if (isset($params['name'])) {
678 $name = $params['name'];
679 unset($params['name']);
685 $c =& Ethna_Controller::getInstance();
686 $view =& $c->getView();
687 if ($view === null) {
691 // 現在の{form_input}を囲むform blockがあればパラメータを取得しておく
692 $block_params = null;
693 for ($i = count($smarty->_tag_stack); $i >= 0; --$i) {
694 if ($smarty->_tag_stack[$i][0] === 'form') {
695 $block_params = $smarty->_tag_stack[$i][1];
702 if (isset($params['action'])) {
703 $action = $params['action'];
704 unset($params['action']);
705 } else if (isset($block_params['ethna_action'])) {
706 $action = $block_params['ethna_action'];
708 if ($action !== null) {
709 $view->addActionFormHelper($action);
713 if (isset($params['default'])) {
714 // {form_input default=...}が指定されていればそのまま
716 } else if (isset($block_params['default'])) {
717 // 外側の {form default=...} ブロック
718 if (isset($block_params['default'][$name])) {
719 $params['default'] = $block_params['default'][$name];
723 // 現在のアクションで受け取ったフォーム値
724 $af =& $c->getActionForm();
725 $val = $af->get($name);
727 $params['default'] = $val;
730 return $view->getFormInput($name, $action, $params);
734 // {{{ smarty_block_form
736 * smarty block:フォームタグ出力プラグイン
738 function smarty_block_form($params, $content, &$smarty, &$repeat)
741 // {form}: ブロック内部に進む前の処理
744 if (isset($params['default']) === false) {
745 // 指定なしのときは $form を使う
746 $c =& Ethna_Controller::getInstance();
747 $af =& $c->getActionForm();
749 // c.f. http://smarty.php.net/manual/en/plugins.block.functions.php
750 $smarty->_tag_stack[count($smarty->_tag_stack)-1][1]['default']
751 =& $af->getArray(false);
758 // {/form}: ブロック全体を出力
760 $c =& Ethna_Controller::getInstance();
761 $view =& $c->getView();
762 if ($view === null) {
767 if (isset($params['ethna_action'])) {
768 $ethna_action = $params['ethna_action'];
769 unset($params['ethna_action']);
771 $view->addActionFormHelper($ethna_action);
772 $hidden = $c->getActionRequest($ethna_action, 'hidden');
773 $content = $hidden . $content;
777 if (isset($params['enctype'])) {
778 if ($params['enctype'] == 'file'
779 || $params['enctype'] == 'multipart') {
780 $params['enctype'] = 'multipart/form-data';
781 } else if ($params['enctype'] == 'url') {
782 $params['enctype'] = 'application/x-www-form-urlencoded';
787 if (isset($params['default'])) {
788 unset($params['default']);
791 // $contentを囲む<form>ブロック全体を出力
792 return $view->getFormBlock($content, $params);
797 // {{{ smarty_function_csrfid
799 * smarty function: 正当なポストであることを保証するIDを出力する
806 * <input type="hidden" name="csrfid" value="a0f24f75e...e48864d3e">
809 * @param string $type 表示タイプ("get" or "post"−デフォルト="post")
810 * @see isRequestValid
812 function smarty_function_csrfid($params, &$smarty)
814 $c =& Ethna_Controller::getInstance();
815 $name = $c->config->get('csrf');
816 if (is_null($name)) {
819 $plugin =& $c->getPlugin();
820 $csrf = $plugin->getPlugin('Csrf', $name);
821 $csrfid = $csrf->get();
822 $token_name = $csrf->getName();
823 if (isset($params['type']) && $params['type'] == 'get') {
824 return sprintf("%s=%s", $token_name, $csrfid);
826 return sprintf("<input type=\"hidden\" name=\"%s\" value=\"%s\" />\n", $token_name, $csrfid);