<?php
/**
 * -----------------------------------------------------------------------------
 *
 * SyL - Web Application Framework for PHP
 *
 * PHP version 4 (>= 4.3.x) or 5
 *
 * Copyright (C) 2006 k.watanabe
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * -----------------------------------------------------------------------------
 * @package   SyL
 * @author    k.watanabe <k.watanabe@syl.jp>
 * @copyright 2006 k.watanabe
 * @license   http://www.opensource.org/licenses/lgpl-license.php
 * @version   CVS: $Id: SyL_FormElement.php,v 1.7 2006/12/23 11:13:09 seasonstream Exp $
 * @link      http://www.syl.jp/
 * -----------------------------------------------------------------------------
 */

/**
 * 検証クラス
 */
require_once 'SyL_Validation.php';

/**
 * フォーム要素の基底クラス
 * 
 * @package   SyL
 * @author    k.watanabe <k.watanabe@syl.jp>
 * @copyright 2006 k.watanabe
 * @license   http://www.opensource.org/licenses/lgpl-license.php
 * @version   CVS: $Id: SyL_FormElement.php,v 1.7 2006/12/23 11:13:09 seasonstream Exp $
 * @link      http://www.syl.jp/
 */
class SyL_FormElement
{
    /**
     * フォーム名
     *
     * @access private
     * @var string
     */
    var $form_name = '';
    /**
     * フォーム要素表示名
     *
     * @access private
     * @var string
     */
    var $display_name = '';
    /**
     * フォーム要素HTMLタグ名
     *
     * @access private
     * @var string
     */
    var $name = '';
    /**
     * フォーム要素の値
     *
     * @access private
     * @var string
     */
    var $value = '';
    /**
     * フォーム要素HTMLタグの型
     *
     * @access private
     * @var string
     */
    var $type = null;
    /**
     * フォーム要素HTMLタグの追加属性
     *
     * @access private
     * @var string
     */
    var $attributes = array();
    /**
     * フォーム要素部品配列
     * ※radio, select, checkboxのみ
     *
     * @access private
     * @var array
     */
    var $options = array();
    /**
     * 検証グループオブジェクト
     *
     * @access private
     * @var object
     */
    var $validators = null;
    /**
     * 読み取り専用フラグ
     *
     * @access private
     * @var bool
     */
    var $read_only = false;
    /**
     * セッション可能判定
     *
     * @access private
     * @var bool
     */
    var $session = false;
    /**
     * エラーメッセージ
     * ※エラーメッセージが''の場合は、エラーが無い
     *
     * @access private
     * @var string
     */
    var $error_message = '';

    /**
     * 個別フォーム要素オブジェクトの取得
     *
     * @access public
     * @param string フォーム要素タイプ
     * @param string フォーム要素HTMLタグ名
     * @param string フォーム要素表示名
     * @param array フォーム要素の部品配列（radio, select, checkboxの場合のみ）
     * @param mixed フォーム要素の値（checkboxの場合は配列、それ以外はstring）
     * @param string フォーム要素の追加属性
     */
    function &create($type, $name, $display_name, $options=array(), $value=null, $attributes=array())
    {
        $type = ucfirst(strtolower($type));
        $class_name = 'SyL_FormElement' . $type;
        include_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'FormElement' . DIRECTORY_SEPARATOR . $class_name . '.php';
        $element_class =& new $class_name($name, $display_name, $options, $value, $attributes);
        return $element_class;
    }

    /**
     * 検証グループオブジェクトを作成する
     *
     * @access public
     * @return object 検証グループオブジェクト
     */
    function &createValidators()
    {
        $validators =& new SyL_Validators();
        return $validators;
    }

    /**
     * リクエストから初期値を取得する
     *
     * @access public
     * @return mixed リクエスト変数値
     */
    function getParameter()
    {
        $value = '';
        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            $value = isset($_POST[$this->name]) ? $_POST[$this->name] : '';
        } else {
            $value = isset($_GET[$this->name]) ? $_GET[$this->name] : '';
        }

        return $value;
    }

    /**
     * 変数に対して再帰的に処理を実行する
     *
     * @access public
     * @param string 関数名
     * @param mixed 関数の引数となる変数
     */
    function parametersFilter($func, &$value)
    {
        if (is_array($value)) {
            foreach ($value as $k => $v) {
                $this->parametersFilter($method, $value[$k]);
            }
        } else {
            $value = call_user_func($func, $value);
        }
    }

    /**
     * フォームの全要素を表示のみ判定
     *
     * @access public
     * @param bool フォームの全要素を表示のみフラグ
     */
    function readOnly($read_only)
    {
        $this->read_only = $read_only;
    }

    /**
     * フォーム名をセット
     *
     * @access public
     * @param string フォーム名
     */
    function setFormName($form_name)
    {
        $this->form_name = $form_name;
    }

    /**
     * 追加属性をセット
     *
     * @access public
     * @param string 追加属性
     */
    function setAttribute($attribute)
    {
        $this->attributes = $attribute;
    }

    /**
     * セッション可能判定をセット
     *
     * @access public
     * @param bool セッション可能判定
     */
    function setFormSession( $session )
    {
        $this->session = $session;
    }

    /**
     * 必須チェック存在判定
     * ※検証グループオブジェクトをセットしてから実行する
     *
     * @access public
     * @return bool true: 必須チェックあり、false: 必須チェック無し
     */
    function isRequire()
    {
        return (is_object($this->validators) ? $this->validators->isRequire() : false);
    }

    /**
     * 要素名を取得する
     *
     * @access public
     * @return string 要素名
     */
    function getName()
    {
        return $this->name;
    }

    /**
     * フォーム要素表示名を取得する
     *
     * @access public
     * @return string 要素名
     */
    function getDisplayName( $group=false )
    {
        return $this->display_name;
    }

    /**
     * 要素名を取得する
     *
     * @access public
     * @return string 要素名
     */
    function getValue()
    {
        return $this->value;
    }

    /**
     * エラーメッセージを取得する
     *
     * @access public
     * @return string エラーメッセージ
     */
    function getErrorMessage()
    {
        return $this->error_message;
    }

    /**
     * その他属性を取得する
     *
     * @access public
     * @return string その他属性
     */
    function getAttribute()
    {
        $attributes = '';
        foreach ($this->attributes as $k => $v) {
            $attributes .= is_numeric($k) ? (' ' . $this->encodeHtml($v) . ' ') : ($k . '="' . $this->encodeHtml($v) . '" ');
        }
        return $attributes;
    }

    /**
     * フォーム要素の表示判定を取得
     *
     * @access public
     * @param bool フォーム要素の表示判定を取得
     */
    function isReadOnly()
    {
        return $this->read_only;
    }

    /**
     * フォーム要素HTML出力
     * 読み取り専用になっているかで、子クラスのメソッドを呼び分ける
     *
     * @access public
     * @return string フォーム要素のHTML
     */
    function getHtml()
    {
        if ($this->read_only) {
            return $this->getHtmlView();
        } else {
            return $this->getHtmlTag();
        }
    }

    /**
     * フォーム要素HTML出力（表示）
     *
     * @access public
     * @return string フォーム要素のHTML
     */
    function getHtmlView()
    {
        trigger_error("[SyL error] 'getHtmlView' method is not implemented in this class (" . get_class($this) . ")");
    }

    /**
     * フォーム要素HTML出力（入力項目）
     *
     * @access public
     * @return string フォーム要素のHTML
     */
    function getHtmlTag()
    {
        trigger_error("[SyL error] 'getHtmlTag' method is not implemented in this class(" . get_class($this) . ")");
    }

    /**
     * フォーム要素をhiddenタグで出力
     *
     * @access public
     * @param bool true: htmlエンコードを行う、false: htmlエンコードを行わない
     * @return string フォーム要素のHTML
     */
    function getHtmlHidden( $name=null, $value=null )
    {
        if (($name === null) || ($value === null)) {
            $name  = $this->name;
            $value = $this->value;
        }
        $html_element  = '';
        $html_element .= '<input type="hidden" ';
        $html_element .=   'name="'  . $name  . '" ';
        $html_element .=   'value="' . $this->encodeHtml($value) . '"';
        $html_element .= '>';

        return $html_element;
    }

    /**
     * HTMLエンコードを行う
     *
     * @access public
     * @param string HTMLエンコード前文字列
     * @return string HTMLエンコード後文字列
     */
    function encodeHtml($value)
    {
        return htmlspecialchars($value);
    }

    /**
     * 検証グループオブジェクトをセット
     *
     * @access public
     * @param object 検証グループオブジェクト
     */
    function setValidators(&$validators)
    {
        $this->validators =& $validators;
    }

    /**
     * 検証を実行する
     * 検証グループオブジェクトがない場合は、常にtrue
     *
     * エラーメッセージ中の{name}文字列は、要素名に変換される
     *
     * @access public
     * @return bool true: エラー無し、false: エラーあり
     */
    function validate()
    {
        if (is_object($this->validators)) {
            if (!$this->validators->execute($this->value)) {
                $this->error_message = $this->validators->getErrorMessage($this->getDisplayName());
                return false;
            } else {
                return true;
            }
        } else {
            return true;
        }
    }

    /**
     * JavaScript入力チェックタグを取得
     *
     * @access public
     * @return string JavaScript入力チェックタグ
     */
    function getJavaScript()
    {
        if (is_object($this->validators)) {
            $js  = '';
            $js .= 'var error_flag = false;' . "\r\n";
            $js .= 'var element_name = "' . $this->getName() . '";' . "\r\n";
            $js .= $this->validators->getJavaScript($this->getDisplayName(), $this->options);
            $js .= "\r\n";
            return $js;
        } else {
            return '';
        }
    }
}

?>
