<?php
/**
 *	Project:	Quicty: Quick application build environment depends on PEAR and Smarty
 *	File:		DataView.class.php
 *
 *	@copyright	Tomoyuki Negishi and ZubaPitaTech, Inc.
 *	@author		Tomoyuki Negishi <tomoyu-n@zubapita.jp>
 *	@license	http://www.opensource.org/licenses/bsd-license.php The BSD License
 *	@package	Quicty
 *	@version	$Id:$
 */


// {{{ DataView
/**
 *	DataView Create, validate and process HTML forms with easy settings class.
 *
 *	@author		Tomoyuki Negishi <tomoyu-n@zubapita.jp>
 *	@access		public
 *	@package	Quicty
 */
class DataView extends HTML_QuickForm {
public $data_view;
public $id_column;
public $validation_place = 'server';
public $error;
public $__page_obj;
public $escape_string_func = 'addslashes';
public $__force_escape_filter = false;
//  constructor
function DataView($formName='', $method='post', $action='', $target='', $attributes=null, $trackSubmit=false) {
	//HTML_QuickForm::HTML_QuickForm($formName, $method, $action, $target, $attributes, $trackSubmit);
	HTML_QuickForm::HTML_QuickForm($formName, $method, $action);
	$this->data_view_config_dir = '/etc/data_view';
	$this->data_set_config_dir = '/etc/data_set';
	$this-> regist_custom_rules();
	$this->data_view_name = $formName;
	$this->log = new QtLog($formName,$display=true);
}

function read_conf_to_array($dir,$file,$type='IniFile') {
	$config = new Config();
	if(is_file($dir.'/'.$file)) {
		$parsed_data = $config->parseConfig($dir.'/'.$file,$type);
	} elseif(is_file($file)) {
		$parsed_data = $config->parseConfig($file,$type);
	} else {
		$this->log->err("file not found '$file' in dir '$dir'  source file:".__FILE__.' line:'.__LINE__);
	}
	if($parsed_data) $data_array = $parsed_data->toArray();
	return $data_array;
}

function bind_data_view($data_view_file,$config_dir='') {
	global $html_quickform_datatype,$html_quickform_datatype_default,$quicksmart_datatype,$validiate_rule;
	if(is_array($data_view_file)) {
		$columns = $data_view_file;
	}
	if(!$columns) {
		if(!$config_dir) $config_dir = $this->__page_obj->home_dir.$this->data_view_config_dir;
		$data_view_array = $this->read_conf_to_array($config_dir,$data_view_file);
		$columns = $data_view_array['root'];
	}
	//echo "data_view_file=$data_view_file<br>";
	//var_check($columns);
	foreach($columns as $column=>$attributes) {
		$method_pram = array();
		if(array_key_exists($attributes['type'],$quicksmart_datatype)===false) {
			$this->log->err('error: data_view='.$data_view_file.': column="'.$column.'" : "'.$attributes['type'].'" is unkown data type.'.__FILE__.' line:'.__LINE__);
			var_check($columns);
			exit;
		}
		if($attributes['type']=='id') $this->id_column = $column;
		$hqf_type = $quicksmart_datatype[$attributes['type']]['hqf_type'];
		$method_pram['type'] = $hqf_type;
		$method_pram['qs_type'] = $attributes['type'];
		$columns_pram = $html_quickform_datatype[$hqf_type];
		$columns_default = $html_quickform_datatype_default[$hqf_type];
		foreach($columns_pram as $property=>$value) {
			if($value=='property_array') {
				$tmp_array = $this->get_array_from_list($attributes,$property);
				if(count($tmp_array)==0) {
					$method_pram[$property] = $columns_default[$property];
				} else {
					$method_pram[$property] = $tmp_array;
				}
			} elseif($property=='name') {
				$method_pram['name'] = $column;
				
			} else {
				$method_pram[$property] = $attributes[$property] ? $attributes[$property]:$columns_default[$property];
			}
		}
		$method_pram['attr']['id'] = str_replace('_','-',$method_pram['name']);
		$current_logic = array($this,$hqf_type.'_element');
		$this->form_element[$column] = call_user_func($current_logic,$method_pram);
		$this->data_view[$column] = $method_pram;
		if(isset($attributes['default'])) {
			$this->__default_values[$column] = $attributes['default'];
			$this->setDefaults(array($column=>$this->__default_values[$column]));
		}
		if($attributes['default_list']=='start') {
			$this->__default_values[$column] = $this->get_array_from_list($attributes,'default_list');
			$this->setDefaults(array($column=>$this->__default_values[$column]));
		}
		if($attributes['force_value_list']=='start') {
			$force_value = $this->get_force_values($attributes,'force_value_list',$column);
			if(isset($force_value[$column])) {
				$this->form_element[$column]->setValue($force_value[$column]);
				$this->__force_values[$column] = $force_value;
			}
			$this->form_element[$column]->freeze();
		}
		if($attributes['reference']=='start') {
			$this->data_view[$column]['reference'] = $this->get_array_from_list($attributes,'reference');
		}
		
		// virtual colum
		if($attributes['virtual']=='1') {
			$this->data_view[$column]['virtual'] = 'yes';
		}
		
		// add rule
		$tmp_array = $this->get_array_from_list($attributes,'rule');
		if(count($tmp_array)) {
			foreach($tmp_array as $rule_name=>$value) {
				if(is_callable(array($this,'add_'.$rule_name.'_rule'))) {
					$result = call_user_func(array($this,'add_'.$rule_name.'_rule'),$column,$rule_name,$value,$this->validation_place);
				} elseif(is_callable(array($this->__page_obj,'add_'.$rule_name.'_rule'))) {
					$result = call_user_func(array($this->__page_obj,'add_'.$rule_name.'_rule'),$column,$rule_name,$value,$this->validation_place,$this);
				} else {
					$this->log->err('error:"add_'.$rule_name.'_rule" is not able to call.'.__FILE__.' line:'.__LINE__);
				}
			}
		}
	}
} // end of function bind_data_view


function get_array_from_list($attributes,$property_name) {
	$tmp_flag = false;$tmp_array=array();
	foreach($attributes as $t_property=>$t_value) {
		if($t_property===$property_name and $t_value=='start') {
			$tmp_flag = true;
		} elseif($t_property==='end_'.$property_name) {
			$tmp_flag = false;
		} elseif($tmp_flag) {
			if(substr($t_value,0,12)=='_THIS_VALUE.') {
				$var_name = substr($t_value,12);
				if(strpos($var_name,'.')!==false) {
					list($array_name,$var_name) = explode('.',$var_name);
					$t_array = $this->__page_obj->$array_name;
					$t_value = $t_array[$var_name];
				} else {
					$t_value = $this->__page_obj->$var_name;
				}
			}
			$tmp_array[$t_property] = $t_value;
		}
	}
	if($tmp_array['_TABLE'] and $property_name!='reference') {
		$tmp_array = $this->get_list_from_table($tmp_array);
	}
	if($property_name=='default_list') {
		if(substr($tmp_array['date'],0,3)=='now') $tmp_array = $this->get_now_date(substr($tmp_array['date'],3));
	}
	return $tmp_array;
}

function get_list_from_table($tmp_array) {
	if($data_set = $tmp_array['_TABLE']) {
		if($tmp_array['_WHERE_COLUMN']) {
			$where = 'where '.$tmp_array['_WHERE_COLUMN'].'=';
			list($var_name,$var_operator) = explode('.',$tmp_array['_WHERE_THIS_VALUE']);
			$where .= "'".$this->__page_obj->{$var_name}[$var_operator]."'";
		}
		if($tmp_array['_ORDER_BY']) $order_by = 'order by '.$tmp_array['_ORDER_BY'];
		$_FORM = $this->__page_obj->new_data_set($data_set);
		$table = $_FORM->select_table("$where $order_by");
/*
		require_once 'Quicty/phplib/easy_db.class.php';
		$dsn = $this->read_dsn($data_set);
		if($dsn['phptype']=='sqlite' OR $dsn['phptype']=='sqlite3') {
			$dsn['phptype'] = 'sqlite';
			$dsn['database'] = $dsn['path'].'/'.$dsn['database'];
		}
		$db = new easy_db($dsn);
		$table = $db->select_all($data_set,"$where $order_by");
*/
		if($tmp_array['_START']=='no_value') {
			$result_array[0] = '指定なし';
		}
		$key_column = $tmp_array['_VALUE'];
		$label_column = $tmp_array['_LABEL'];
		if(is_array($table) and count($table)>0) {
			foreach($table as $key=>$value) {
				$key = $value[$key_column];
				$result_array[$key] = $value[$label_column];
			}
		}
		$this->__page_obj->assign($data_set,$result_array);
	}
	return $result_array;
}

function get_force_values($attributes,$property_name,$column) {
	$tmp_array = $this->get_array_from_list($attributes,$property_name);
	if(substr($tmp_array['date'],0,3)=='now') {
		$result[$column] =  $this->get_now_date(substr($tmp_array['date'],3));
	}
	if($tmp_array['auto_only_1st']) {
		$result['auto_only_1st'] = 'yes';
	}
	if($tag = $tmp_array['_SERVER']) {
		$result[$column] = $_SERVER[$tag];
	} elseif($tag = $tmp_array['_THIS_VALUE']) {
		list($var_name,$var_operator) = explode('.',$tag);
		$result[$column] = $this->__page_obj->{$var_name}[$var_operator];
	}

	if($function = $tmp_array['_USER_FUNCTION']) {
		if($tmp_array['_AT_TIME']=='last') {
			$result['call_function_last'] = 'yes';
		} else {
			$result['call_function'] = 'yes';
		}
		if($source = $tmp_array['_PARAM']) {
			$result[$column] = '$eval_result = call_user_func(array($this->__page_obj,"'.$function.'"),$this->getSubmitValue("'.$source.'"));';
		} else {
			$result[$column] = '$eval_result = call_user_func(array($this->__page_obj,"'.$function.'"));';
		}
	}
	return $result;
}


/*
 * param option string
 *  ex) '+24hours' or '+1day3hours'
 */
function get_now_date($option='') {
	if (($timestamp = strtotime($option))===false) {
		$now = time();
	} else {
		$now = $timestamp;
	}
	$tmp_array['Y'] = date('Y',$now);
	$tmp_array['m'] = date('m',$now);
	$tmp_array['d'] = date('d',$now);
	$tmp_array['H'] = date('H',$now);
	$tmp_array['i'] = date('i',$now);
	$tmp_array['s'] = date('i',$now);
	return $tmp_array;
}

public $can_skip_confirm = true;
public $can_delete = true;
public $use_confirm = true;
public $use_edit = true;
public $use_redo = true;
public $use_restart = true;

function set_button_status($button_kind,$status) {
	if($status) {
		$this->$button_kind = true;
	} else {
		$this->$button_kind = false;
	}
}

function set_button_label($button_name,$label) {
	$button_label = $button_name.'_button_label';
	if($button_name and $label) {
		$this->$button_label = $label;
	}
	return $this->$button_label;
}

function set_base_link_addr($addr='') {
	return $this->base_link_addr = $addr;
}

function set_restart_link_addr($addr='/') {
	return $this->restart_link_addr = $addr;
}

function set_delete_confirm_link($link) {
	return $this->delete_confirm_link = $link;
}

function set_delete_confirm_action($action='/delete') {
	return $this->delete_confirm_action = $action;
}

public $send_button_label = '送信';
public $insert_confirm_button_label = '確認';
public $insert_button_label = '登録';
public $update_confirm_button_label = '確認';
public $update_button_label = '更新';
public $browse_button_label = '表示';
public $edit_button_label = '編集';
public $delete_confirm_button_label = '削除';
public $delete_button_label = '削除実行';
public $redo_button_label = '戻る';
public $reset_button_label = 'リセット';
public $restart_button_label = '戻る';
//
public $send_button_option = array();
public $insert_confirm_button_option = array();
public $insert_button_option = array();
public $update_confirm_button_option = array();
public $update_button_option = array();
public $delete_button_option = array();
public $redo_button_option = array();
public $reset_button_option = array();
//
public $base_link_addr = '';
public $restart_link_addr = '/';
public $delete_confirm_action = '/delete';
//
public $send_button;
public $insert_confirm_button;
public $insert_button;
public $update_confirm_button;
public $update_button;
public $browse_button;
public $edit_button;
public $delete_confirm_button;
public $delete_button;
public $redo_button;
public $reset_button;
public $restart_button;
//
public $START_set;
public $EDIT_set;
public $INSERT_CONFIRM_set;
public $INSERT_set;
public $UPDATE_CONFIRM_set;
public $UPDATE_set;
public $BROWSE_set;
public $DELETE_CONFIRM_set;
public $DELETE_SET;
public $REDO_set;

function bind_button_control ($control='submit') {
	if(substr($this->base_link_addr,-1)=='/') {
		$base_link_addr = substr($this->base_link_addr,0,-1);
	} else {
		$base_link_addr = $this->base_link_addr;
	}
	//
	$this->send_button_option['id'] = 'submit-send';
	$this->insert_confirm_button_option['id'] = 'submit-insert_confirm';
	$this->insert_button_option['id'] = 'submit-insert';
	$this->update_confirm_button_option['id'] = 'submit-update_confirm';
	$this->update_button_option['id'] = 'submit-update';
	$this->delete_button_option['id'] = 'submit-delete';
	$this->redo_button_option['id'] = 'submit-redo';
	$this->redo_button_option['onclick'] = 'javascript:history.back()';
	$this->reset_button_option['id'] = 'submit-reset';
	//
	$this->send_button = $this->createElement('submit', 'SEND',$this->send_button_label,$this->send_button_option);
	$this->insert_confirm_button = $this->createElement('submit', 'INSERT_CONFIRM',$this->insert_confirm_button_label,$this->insert_confirm_button_option);
	$this->insert_button = $this->createElement('submit', 'INSERT',$this->insert_button_label,$this->insert_button_option);
	$this->update_confirm_button = $this->createElement('submit', 'UPDATE_CONFIRM',$this->update_confirm_button_label,$this->update_confirm_button_option);
	$this->update_button = $this->createElement('submit', 'UPDATE',$this->update_button_label,$this->update_button_option);
	$id_column = $this->id_column;
	if($_REQUEST[$id_column]) $id_query = "?$id_column=".$_REQUEST[$id_column];
	$add_query = $this->add_query;
	if($_REQUEST[$add_query]) $id_query .= "&$add_query=".$_REQUEST[$add_query];
	$this->browse_button = $this->createElement('link', 'BROWSE',$this->browse_button_label,$base_link_addr."/info$id_query",$this->browse_button_label,NULL);
	$this->edit_button = $this->createElement('link', 'EDIT',$this->edit_button_label,$base_link_addr."/edit$id_query",$this->edit_button_label,NULL);
	$delete_confirm_link = $this->delete_confirm_link ? $this->delete_confirm_link : $base_link_addr.$this->delete_confirm_action.$id_query;
	$this->delete_confirm_button = $this->createElement('link', 'DELETE_CONFIRM',$this->delete_confirm_button_label,$delete_confirm_link,$this->delete_confirm_button_label,NULL);
	$this->delete_button = $this->createElement('submit', 'DELETE',$this->delete_button_label,$this->delete_button_option);
	$this->redo_button = $this->createElement('button', 'REDO',$this->redo_button_label,$this->redo_button_option);
	$this->reset_button = $this->createElement('reset', 'RESET',$this->reset_button_label,$this->reset_button_option);
	$this->restart_button = $this->createElement('link', 'RESTART',$this->restart_button_label,"$this->restart_link_addr",$this->restart_button_label,NULL);

	// SEND
	$this->SEND_set[] = $this->send_button;
	
	// START
	if($this->use_confirm) $this->START_set[] = $this->insert_confirm_button;
	if($this->can_skip_confirm) $this->START_set[] = $this->insert_button;

	// EDIT
	if($this->use_redo) $this->EDIT_set[] = $this->redo_button;
	if($this->use_confirm) $this->EDIT_set[] = $this->update_confirm_button;
	if($this->can_skip_confirm) $this->EDIT_set[] = $this->update_button;
	if($this->can_delete) $this->EDIT_set[] = $this->delete_confirm_button;

	// INSERT_CONFIRM
	if($this->use_redo) $this->INSERT_CONFIRM_set[] = $this->redo_button;
	$this->INSERT_CONFIRM_set[] = $this->insert_button;
	// INSERT
	if($this->use_restart) $this->INSERT_set[] = $this->restart_button;

	// UPDATE_CONFIRM
	if($this->use_redo) $this->UPDATE_CONFIRM_set[] = $this->redo_button;
	$this->UPDATE_CONFIRM_set[] = $this->update_button;
	// UPDATE_CONFIRM
	if($this->use_restart) $this->UPDATE_set[] = $this->restart_button;
	
	// BROWSE
	if($this->use_restart) $this->BROWSE_set[] = $this->restart_button;
	if($this->use_edit) $this->BROWSE_set[] = $this->edit_button;
	
	// DELETE_CONFIRM
	if($this->use_redo) $this->DELETE_CONFIRM_set[] = $this->redo_button;
	$this->DELETE_CONFIRM_set[] = $this->delete_button;
	// DELETE
	if($this->use_restart) $this->DELETE_set[] = $this->restart_button;
	
	// REDO
	if($this->use_redo) $this->REDO_set[] = $this->redo_button;
	$this->REDO_set[] = $this->save_button;

	//
	$status = $this->__page_obj->QuictyStatus;
	$result = $this->addGroup($this->{$status.'_set'},$control,NULL,'&nbsp;');
	return $result;
}

function validate_and_freeze() {
	$result = NULL;
	switch($this->__page_obj->QuictyStatus) {
		case Quicty::BROWSE :
		case Quicty::DELETE_CONFIRM :
		case Quicty::DELETE :
			$this->freeze();
			break;
		case Quicty::INSERT_CONFIRM :
		case Quicty::INSERT :
			if($result = $this->validate()) {
				if($this->__CAPTCHA_question)
					$this->__CAPTCHA_question->destroy();
				$this->freeze();
			} else {
				$this->__page_obj->QuictyStatus = Quicty::START;
			}
			break;
		case Quicty::UPDATE_CONFIRM :
		case Quicty::UPDATE :
			if($result = $this->validate()) {
				if($this->__CAPTCHA_question)
					$this->__CAPTCHA_question->destroy();
				$this->freeze();
			} else {
				$this->__page_obj->QuictyStatus = Quicty::EDIT;
			}
			break;
	}
	return $result;
}

function advcheckbox_element($p) {
	return $this->addElement($p['type'],$p['name'],$p['label'],$p['text'],$p['attr'],$p['values']);
}

function captcha_element($p) {
	$p['type'] = 'text';
	$element = $this->text_element($p);
	$require_message = $p['require_message'] ? $p['require_message'] : '画像内の文字列を入力してください';
	$this->addRule($p['name'], $require_message,'required', null, 'client');
	//$error_message = $p['error_message'] ? $p['error_message'] : '画像内の文字列と一致しません';
	//$this->addRule($p['name'], $error_message ,'CAPTCHA', $this->__CAPTCHA_question);
	return $element;
}

function captcha_image_element($p) {
	require_once 'HTML/QuickForm/CAPTCHA/Image.php';
	//session_start();
	$sessionVar = get_uri_id();
	//$sessionVar = 'zubapita';
	$_SESSION[$sessionVar] = NULL;
	$options = array(
		'width'        => 200,
		'height'       => 80,
		'callback'     => '/qfcaptcha_image.php?var='.$sessionVar,
		'sessionVar'   => $sessionVar,
		'imageOptions' => array(
			'font_size' => 20,
			'font_path' => '/usr/local/php/lib/php/Image/Canvas/Fonts/',
			'font_file' => 'Vera.ttf',
			)
		);
	if(is_array($p['opt'])) $options = array_merge($options,$p['opt']);
	$this->__CAPTCHA_question = $this->addElement('CAPTCHA_Image',$p['name'],$p['label'],$options);
	return $this->__CAPTCHA_question;
}


function checkbox_element($p) {
	return $this->addElement($p['type'],$p['name'],$p['label'],$p['text'],$p['attr']);
}

function date_element($p) {
	$element = $this->addElement($p['type'],$p['name'],$p['label'],$p['opt'],$p['attr']);
	return $element;
}

function file_element($p) {
	return $this->addElement($p['type'],$p['name'],$p['label'],$p['attr']);
}

function header_element($p) {
	return $this->addElement($p['type'],$p['name'],$p['label'],$p['opt'],$p['attr']);
}

function hidden_element($p) {
	return $this->addElement($p['type'],$p['name'],$p['value'],$p['attr']);
}

function hireselect_element($p) {
	return $this->addElement($p['type'],$p['name'],$p['label'],$p['attr']);
}

function html_element($p) {
	return $this->addElement($p['type'],$p['html']);
}

function image_element($p) {
	return $this->addElement($p['type'],$p['name'],$p['src'],$p['attr']);
}

function link_element($p) {
	return $this->addElement($p['type'],$p['name'],$p['label'],$p['href'],$p['value'],$p['attr']);
}

function password_element($p) {
	$element = $this->addElement($p['type'],$p['name'],$p['label'],$p['attr']);
	//$element->unfreeze();
	//$password = $element->getValue();
	//$md5pass = md5($password);
	//echo "md5pass=$md5pass<br>\n";
	//$element->setValue($md5pass);
	$element->setPersistantFreeze(true);
	return $element;
}

function password_plain_element($p) {
	$element = $this->addElement("password",$p['name'],$p['label'],$p['attr']);
	//$element->setPersistantFreeze(true);
	return $element;
}


function radio_element($p) {
	$radios = array();
	foreach ($p['list'] as $key=>$value) {
		$radios[] = $this->createElement($p['type'],$p['name'],NULL,$value,$key);
	}
	return $this->addGroup($radios,$p['name'],$p['label']);
}

function select_element($p) {
	return $this->addElement($p['type'],$p['name'],$p['label'],$p['value'],$p['attr']);
}

function static_element($p) {
	return $this->addElement($p['type'],$p['label'],$p['text']);

}

function text_element($p) {
	$element = $this->addElement($p['type'],$p['name'],$p['label'],$p['attr']);
	$this->applyFilter($p['name'],'unify_newline');
	$this->applyFilter($p['name'],'trim');
	if(!get_magic_quotes_gpc) 
		$this->applyFilter($p['name'],$this->escape_string_func);
	return $element;
}

function textarea_element($p) {
	$element = $this->addElement($p['type'],$p['name'],$p['label'],$p['attr']);
	$this->applyFilter($p['name'],'unify_newline');
	$this->applyFilter($p['name'],'trim');
	if(!get_magic_quotes_gpc) 
		$this->applyFilter($p['name'],$this->escape_string_func);
	return $element;
}

//-----------------------------------
// add rule functions
//-----------------------------------

function add_required_rule($column,$rule_name,$value,$validation_place) {
	if($value=='only_1st' and substr($this->__page_obj->QuictyStatus,0,6)!='INSERT') {
		return NULL;
	} else {
		$message = $this->data_view[$column]['label'].'は必ず入力してください。';
		return $this->addRule($column,$message,$rule_name,NULL,$validation_place);
	}
}

function add_maxlength_rule($column,$rule_name,$value,$validation_place) {
	$zennum = (int) round($value/2);
	$message = $this->data_view[$column]['label'].'は'.$value.'文字（全角'.$zennum.'文字）以下で入力してください。';
	return $this->addRule($column,$message,$rule_name,$value,$validation_place);
}

function add_minlength_rule($column,$rule_name,$value,$validation_place) {
	$zennum = (int) round($value/2);
	$message = $this->data_view[$column]['label'].'は半角'.$value.'文字（全角'.$zennum.'文字）以上で入力してください。';
	return $this->addRule($column,$message,$rule_name,$value,$validation_place);
}

function add_email_rule($column,$rule_name,$value,$validation_place) {
	$message = $this->data_view[$column]['label'].'は正しいemailアドレスではありません。';
	return $this->addRule($column,$message,$rule_name,NULL,$validation_place);
}

function add_lettersonly_rule($column,$rule_name,$value,$validation_place) {
	$message = $this->data_view[$column]['label'].'は半角アルファベットのみ入力できます。';
	return $this->addRule($column,$message,$rule_name,NULL,$validation_place);
}

function add_alphanumeric_rule($column,$rule_name,$value,$validation_place) {
	$message = $this->data_view[$column]['label'].'は半角英数字のみ入力できます。';
	return $this->addRule($column,$message,$rule_name,NULL,$validation_place);
}

function add_numeric_rule($column,$rule_name,$value,$validation_place) {
	$message = $this->data_view[$column]['label'].'は半角数字のみ入力できます。';
	// $this->addRule($column,$message,$rule_name,NULL,$validation_place);
	return $this->addRule($column,$message,'regex','/^[0-9A-Za-z.\- ]+$/',$validation_place);
}

function add_nonzero_rule($column,$rule_name,$value,$validation_place) {
	$message = $this->data_view[$column]['label'].'はゼロ(0)は入力できません。';
	return $this->addRule($column,$message,$rule_name,NULL,$validation_place);
}

function add_uploadedfile_rule($column,$rule_name,$value,$validation_place) {
	$message = $this->data_view[$column]['label'].'は必ずファイルを選択してください。';
	return $this->addRule($column,$message,$rule_name,NULL,$validation_place);
}

function add_maxfilesize_rule($column,$rule_name,$value,$validation_place) {
	$message = $this->data_view[$column]['label'].'はファイルが大きすぎます。'.$value.'バイト以下にしてください。';
	return $this->addRule($column,$message,$rule_name,$value,$validation_place);
}

function add_compare_rule($column,$rule_name,$value,$validation_place) {
	$message = $this->data_view[$column]['label'].'と'. $this->data_view[$value]['label'].'が一致しません。';
	return $this->addRule(array($column,$value),$message,$rule_name,NULL,$validation_place);
}

function add_zipcode_rule($column,$rule_name,$value,$validation_place) {
	$message = $this->data_view[$column]['label'].'は正しい郵便番号ではありません。';
	return $this->addRule($column,$message,'regex','/^[0-9]{3}\-[0-9]{4}$/',$validation_place);
}

function add_regex_rule($column,$rule_name,$value,$validation_place) {
	$message = $this->data_view[$column]['label'].'は正しい入力ではありません。';
	return $this->addRule($column,$message,'regex',$value,$validation_place);
}

function add_alphanumsymbol_rule($column,$rule_name,$value,$validation_place) {
	$message = $this->data_view[$column]['label'].'は半角英数字と一部の記号のみ入力できます。';
	return $this->addRule($column,$message,'regex','/^[0-9A-Za-z._=|+\- ]+$/',$validation_place);
}

function add_captcha_rule($column,$rule_name,$value,$validation_place) {
	$message = $this->data_view[$column]['label'].'は認証画像と文字列が一致しません。';
	return $this->addRule($column,$message,'CAPTCHA',$this->__CAPTCHA_question);
}


//------------------------------------------------------------------------------------------------
// add validate rules
//

function regist_custom_rules() {
	$this->registerRule('checksame','callback','checksame',$this);
	$this->registerRule('checkmd5pass','callback','checkmd5pass',$this);
	$this->registerRule('checkmd5key','callback','checkmd5key',$this);
	$this->registerRule('checkuniq','callback','checkuniq',$this);
	$this->registerRule('checkemaildomain','callback','checkemaildomain',$this);
	$this->registerRule('check_hiragana','callback','check_hiragana',$this);
}

// same

function add_checksame_rule($column,$rule_name,$value,$validation_place) {
	$message = $this->data_view[$column]['label'].'が正しくありません。';
	return $this->addRule($column,$message,'checksame',$value);
}

function checksame($data,$column) {
	$id = $_REQUEST[$this->id_column];
	$row = $this->select("where $this->id_column=$id and $column='$data'");
	if(count($row)==1) {
		return true;
	} else {
		return false;
	}
}

// md5 password

function add_checkmd5pass_rule($column,$rule_name,$value,$validation_place) {
	$message = $this->data_view[$column]['label'].'が正しくありません。';
	return $this->addRule($column,$message,'checkmd5pass',$value);
}

function checkmd5pass($data,$column) {
	$md5pass = md5($data);
	$id = $_REQUEST[$this->id_column];
	if($id) {
		$row = $this->select("where $this->id_column=$id and $column='$md5pass'");
		if(count($row)==1) {
			$result = true;
		} else {
			$result = false;
		}
	} else {
		$result = true;
	}
	return $result;
}

// md5key

function add_checkmd5key_rule($column,$rule_name,$value,$validation_place) {
	$message = $this->data_view[$value]['label'].'が正しくありません。';
	return $this->addRule(array($column,$value),$message,'checkmd5key',$column);
}

function checkmd5key($data_array,$column) {
	list($mydata,$keydata) = $data_array;
	$md5pass = md5($keydata);
	$id = $_REQUEST[$this->id_column];
	if($id) {
		$row = $this->select("where $this->id_column=$id and $column='$md5pass'");
		if(count($row)==1) {
			$result = true;
		} else {
			$result = false;
		}
	} else {
		$result = true;
	}
	return $result;
}

// uniq

function add_checkuniq_rule($column,$rule_name,$value,$validation_place) {
	$message = $this->data_view[$column]['label'].'はすでに登録されています。';
	return $this->addRule($column,$message,'checkuniq',$column);
}

function checkuniq($data,$column) {
	$id = $_REQUEST[$this->id_column];
	if($id) {
		$condition = "where $this->id_column=$id and $column='$data'";
		$num = $this->count_rows($condition);
		if($num==1 or $num==0) {
			$result = true;
		} else {
			$result = false;
		}
	} else {
		$condition = "where $column='$data'";
		$num = $this->count_rows($condition);
		if($num==0) {
			$result = true;
		} else {
			$result = false;
		}
	}
	return $result;
}

// entry only 1st

function add_entry_only_1st_rule($column,$rule_name,$value,$validation_place) {
	if($this->__page_obj->QuictyStatus=='EDIT') {
		$this->form_element[$column]->freeze();
	}
	return NULL;
}

// email

function add_checkemaildomain_rule($column,$rule_name,$value,$validation_place) {
	$message = 'ドメインを確認できません。入力に間違いがないなら管理者に問い合わせてください。';
	return $this->addRule($column,$message,'checkemaildomain',$column);
}

function checkemaildomain($data,$column) {
	$p = strpos($data,"@");
	$dn = substr($data,$p+1);
	$chkMx = checkdnsrr($dn, "MX");
	$chkA = checkdnsrr($dn, "A");
	$chkCn = checkdnsrr($dn, "CNAME");
	if(!$chkMx and !$chkA and !$chkCn) {
		$result = false;
	} else {
		$result = true;
	}
	return $result;
}


// hiragana

function add_check_hiragana_rule($column,$rule_name,$value,$validation_place) {
	$message = 'ひらがなで入力してください。';
	return $this->addRule($column,$message,'check_hiragana',$column);
}


function check_hiragana($data,$column) {
	if($this->__page_obj->C['ENCODING']) 
		mb_internal_encoding($this->__page_obj->C['ENCODING']);
	$this->applyFilter($column,array($this,'convert_hiragana'));
	$data = $this->convert_hiragana($data);
	$data_max = mb_strlen($data);
	$result = true;
	for($i=0;$i<$data_max;++$i) {
		$chkC = mb_substr($data, $i,1);
		//echo "chkC = $chkC<br>\n";
		if(!mb_ereg("[あ-んぁー]",$chkC)) {
			$result = false;
			break;
		}
	}
	return $result;
}


//------------------------------------------------------------------------------------------------
// filters
//
function convert_hiragana($data) {
	if($this->__page_obj->C['ENCODING']) 
		mb_internal_encoding($this->__page_obj->C['ENCODING']);
	$conv = "aHVc";
	$data = mb_convert_kana($data,$conv);
	$search = array('　',' ','・','：',':','。','、',',','.','_',);
	$replace = '';
	$data = str_replace($search,$replace,$data);
	$search = array('う゛ぁ','う゛ぃ','う゛ぅ','う゛ぇ','う゛ぉ','う゛','ヴぁ','ヴぃ','ヴぅ','ヴぇ','ヴぉ','ヴ',);
	$replace = array('ば','び','ぶ','べ','ぼ','ぶ','ば','び','ぶ','べ','ぼ','ぶ',);
	$data = str_replace($search,$replace,$data);
	return $data;
}


// Accsesor Method

function get_form_element($column) {
	return $this->form_element[$column];
}



/**
 *	Quick build sql select fields
 *
 *	@access	public
 *	@param	array $select_system parameters for conditions.
 *			example: array(
 *						'table_name1'=>array('column_name1','column_name2),
 *						'table_name2'=>array(
 *									'column_name'=>'other_column_name')),
 *						'table_name3'=>'*'
 *	@return	string select fields phrase for sql parameter.
 */
public function make_select_fields($select_system=array()) {
	foreach($select_system as $table_name=>$fields) {
		if(is_array($fields)) {
			foreach($fields as $key=>$column) {
				if(preg_match("/^(.*?)\((.*?)\)$/",$key,$matches)) {
					$func_name = $matches[1];
					$column_name = $matches[2];
					$fields_array[] = "$func_name($table_name.$column_name) as $column";
				} elseif(preg_match("/^(.*?)\((.*?)\)$/",$column,$matches)) {
					$func_name = $matches[1];
					$column_name = $matches[2];
					$fields_array[] = "$func_name($table_name.$column)";
				} elseif(!is_numeric($key)) {
					$fields_array[] = "$table_name.$key as $column";
				} else {
					$fields_array[] = "$table_name.$column as $column";
				}
			}
		} elseif($fields=='*') {
			foreach($this->data_view as $column=>$attributes) {
				//var_check($attributes);
				if($attributes['virtual']=='yes') continue;
				$fields_array[] = "$table_name.$column";
				/*
				if($this->data_view_name==$table_name AND $column!='id') {
					$fields_array[] = "$column";
				} else {
					$fields_array[] = "$table_name.$column";
				}
				*/
			}
		} else {
			$fields_array[] = "$table_name.$fields";
		}
	}
	return implode(',',$fields_array);
}

/**
 *	Quick build sql GROUP BY fields
 *
 *	@access	public
 *	@param	array $grouping_system parameters for conditions.
 *			example: array(
 *						'table_name1'=>array('column_name1','column_name2),
 *						'table_name2'=>'*'
 *	@return	string select fields phrase for sql parameter.
 */
public function make_grouping_fields($grouping_system=array()) {
	foreach($grouping_system as $table_name=>$fields) {
		if(is_array($fields)) {
			foreach($fields as $key=>$column) {
				if(preg_match("/^(.*?)\((.*?)\)$/",$key,$matches)) {
					continue;
				} elseif(preg_match("/^(.*?)\((.*?)\)$/",$column,$matches)) {
					continue;
				} elseif(!is_numeric($key)) {
					$fields_array[] = "$table_name.$key";
				} else {
					$fields_array[] = "$table_name.$column";
				}
			}
		} elseif($fields=='*') {
			foreach($this->data_view as $column=>$attributes) {
				$fields_array[] = "$table_name.$column";
			}
		} else {
			$fields_array[] = "$table_name.$fields";
		}
	}
	return implode(',',$fields_array);
}

/**
 *	Quick build sql condition for Search form.
 *
 *	@access	public
 *	@param	array $search_system parameters for conditions.
 *			example: array(
 *						'keyword'=>array(
 *									'url_parameter_name'=>'$tablename.coumnname'),
 *						'condition'=>array(
 *									'url_parameter_name'=>'tablename.coumnname'))
 *	@return	string where condition phrase for sql parameter.
 */
public function make_condition($search_system=array(),$add_condition='',$cond='AND') {
	if($_REQUEST['keyword'] and isset($_REQUEST['kind'])) {
		$keyword = $this->esfd($_REQUEST['keyword']);
		$kind = $this->esfd($_REQUEST['kind']);
		if(is_array($search_system['keyword'])
			and array_key_exists($kind,$search_system['keyword'])) {
				$search_column = $search_system['keyword'][$kind];
				if(is_array($search_column)) {
					foreach($search_column as $each_column) {
						$condition_filter[] = "$each_column like '%$keyword%'";
					}
					if(count($search_column)>1) {
						$cond='OR';
					}
				} else {
					$condition_filter[] = "$search_column like '%$keyword%'";
				}
		} elseif(is_array($this->data_view[$kind])) {
			$condition_filter[] = "$kind like '%$keyword%'";
		}
	}
	if(is_array($search_system['condition'])) {
		foreach($search_system['condition'] as $param=>$column) {
			if($_REQUEST[$param]) {
				if(is_numeric($_REQUEST[$param])) {
					$value = $_REQUEST[$param];
				} else {
					$value = "'".$this->esfd($_REQUEST[$param])."'";
				}
				$condition_filter[] = "$column=$value";
			}
		}
	}
	if(is_array($search_system['period'])) {
		foreach($search_system['period'] as $param=>$attributes) {
			$start = $param;
			$end = $attributes['end'];
			$column = $attributes['column'];
			if($_REQUEST[$start] and $_REQUEST[$end]) {
				$start_c = sprintf("%04d-%02d-%02d",$_REQUEST[$start]['Y'],$_REQUEST[$start]['m'],$_REQUEST[$start]['d']);
				$end_c = sprintf("%04d-%02d-%02d",$_REQUEST[$end]['Y'],$_REQUEST[$end]['m'],$_REQUEST[$end]['d']);
				$condition_filter[] = "$column>='$start_c' and $column<='$end_c'";
			}
		}
	}
	if(count($condition_filter)>0) {
		$where_condition = 'WHERE '.implode(' '.$cond.' ',$condition_filter);
		if($add_condition) $where_condition .= ' '.$cond.' '.$add_condition;
	} else {
		if($add_condition) {
			$where_condition = 'WHERE '.$add_condition;
		} else {
			$where_condition = '';
		}
	}
	return $where_condition;
}

public function search_condition($search_system=array()) {
	return $this->make_condition($search_system);
}

// make sort order

public function set_sort_option($sort,$order) {
	$this->sort_option = $sort;
	$this->order_option = $order;
	return $this->sort_option.' '.$this->order_option;
}

public function make_order($sort_system=array(),$null=true) {
	// sort column
	if($this->sort_option) {
		$sort = $this->esfd($this->sort_option);
	} else {
		$sort = $this->esfd($_REQUEST['sort']);
	}

	// ASC or DESC
	if($this->order_option) {
		$order = $this->esfd($this->order_option);
		if($order=='desc') $order = 'DESC';
	} else {
		if($_REQUEST['order']=='desc' OR $_REQUEST['order']=='DESC') {
			$order = 'DESC';
		} else {
			$order = '';
		}
	}
	
	// for fix bug
	if(is_array($sort_system['colums'])) {
		$sort_system['columns'] = $sort_system['colums'];
	}

	// set default
	if($sort_system['default']) {
		$sort_default = $sort_system['default'];
	} else {
		$sort_default = 'ORDER BY id';
	}
	
	
	if($sort) {
		if(is_array($sort_system['columns']) AND count($sort_system['columns'])>0) {
			foreach($sort_system['columns'] as $key=>$column) {
				if($key==$sort) {
					$sort = $column;
					if($null==true AND $order=='DESC') {
						$null_option = "$sort is null,";
					}
					$sort_condition = "ORDER BY $null_option$sort $order";
					break;
				} elseif($column==$sort) {
					if($null==true AND $order=='DESC') {
						$null_option = "$sort is null,";
					}
					$sort_condition = "ORDER BY $null_option$sort $order";
					break;
				}
			}
			if(!$sort_condition) {
				$sort_condition = $sort_default;
			}
		} else {
			$sort_condition = "ORDER BY $null_option$sort $order";
		}
	} else {
		$sort_condition = $sort_default;
	}
	//$sort_condition .= ' '.$order;
	//echo "sort_condition=$sort_condition<br>";
	return $sort_condition;
}

/**
 *	Move uploaded file to dir and get name,type,path
 *
 *	@access	public
 *	@param	dir string directrory path
 *			file_name string
 *			element string element name of HTML_QuickForm file object
 *	@return	array
 */
public function move_upload_file2dir($dir='../var/upload',$base_name='',$element='file') {
	$_POSTED_FILE = $this->get_form_element($element);
	if($_POSTED_FILE->isUploadedFile()) {
		$file_type = substr($_FILES[$element]['name'],strrpos($_FILES[$element]['name'],'.')+1);
		if($base_name=='') {
			$file_name = $_FILES[$element]['name'];
		} else {
			$file_name = $base_name.'.'.$file_type;
		}
		$_POSTED_FILE->moveUploadedFile($dir,$file_name);
		chmod("$dir/$file_name",0666);
		$file['result'] = true;
		$file['dir'] = $dir;
		$file['name'] = $file_name;
		$file['path'] = $dir.'/'.$file_name;
		$file['type'] = $file_type;
		$file['size'] = $_POSTED_FILE->_value['size'];
		$file['mime_type'] = $_POSTED_FILE->_value['type'];
		list($kind,$ext) = explode('/',$file['mime_type']);
		$IMGMGK_BIN = $this->__page_obj->C['IMGMGK_BIN'];
		if($IMGMGK_BIN and $kind=='image') {
			$identify = explode(' ',exec("$IMGMGK_BIN/identify ".$file['path']));
			list($file['width'],$file['height']) = explode('x',$identify[2]);
		}
	} else {
		$file['result'] = false;
	}
	return $file;
}

public function resize_image($file,$new_width,$new_height,$new_dir='',$new_name='',$type_name='small') {
	$IMGMGK_BIN = $this->__page_obj->C['IMGMGK_BIN'];
	$geometry = $new_width.'x'.$new_height;
	if(!$new_dir) $new_dir = $file['dir'];
	if(!$new_name) $new_name = substr($file['name'],0,strrpos($file['name'],'.')).'_s'.'.'.$file['type'];
	$file[$type_name.'_dir'] = $new_dir;
	$file[$type_name.'_name'] = $new_name;
	$file[$type_name.'_path'] = $new_dir.'/'.$new_name;
	exec("$IMGMGK_BIN/convert -geometry $geometry ".$file['path'].' '.$file[$type_name.'_path']);
	$identify = explode(' ',exec("$IMGMGK_BIN/identify ".$file[$type_name.'_path']));
	list($file[$type_name.'_width'],$file[$type_name.'_height']) = explode('x',$identify[2]);
	return $file;
}

public function make_thumbnail($file,$new_width,$new_height,$new_dir='',$new_name='') {
/*
	$IMGMGK_BIN = $this->__page_obj->C['IMGMGK_BIN'];
	$geometry = $new_width.'x'.$new_height;
	if(!$new_dir) $new_dir = $file['dir'];
	if(!$new_name) $new_name = substr($file['name'],0,strrpos($file['name'],'.')).'_s'.'.'.$file['type'];
	$file['thumbnail_dir'] = $new_dir;
	$file['thumbnail_name'] = $new_name;
	$file['thumbnail_path'] = $new_dir.'/'.$new_name;
	exec("$IMGMGK_BIN/convert -geometry $geometry ".$file['path'].' '.$file['thumbnail_path']);
	$identify = explode(' ',exec("$IMGMGK_BIN/identify ".$file['thumbnail_path']));
	list($file['thumbnail_width'],$file['thumbnail_height']) = explode('x',$identify[2]);
*/
	$file = $this->resize_image($file,$new_width,$new_height,$new_dir='',$new_name='',$type_name='thumbnail');
	return $file;
}

public function abstruct_get_query($search_system=array()) {
	if(isset($_REQUEST['keyword']) and isset($_REQUEST['kind'])) {
		$keyword = $_REQUEST['keyword'];
		$kind = $_REQUEST['kind'];
		if(is_array($search_system['keyword'])
			and array_key_exists($kind,$search_system['keyword'])) {
			$get_query['keyword'] = rawurlencode($keyword);
			$get_query['kind'] = $kind;
		} elseif(is_array($this->data_view[$kind])) {
			$get_query['keyword'] = rawurlencode($keyword);
			$get_query['kind'] = $kind;
		}
	}
	if(is_array($search_system['condition'])) {
		foreach($search_system['condition'] as $param=>$column) {
			if(isset($_REQUEST[$param])) {
				$get_query[$param] = rawurlencode($_REQUEST[$param]);
			}
		}
	}
	return $get_query;
}

// read dsn for PEAR::DB
function read_dsn($data_set_file) {
	//if(function_exists(apc_fetch)) {
	//	$data_set = unserialize(apc_fetch('CONFIG_SET_'.$data_set_file));
	//}
	if(!$data_set) {
		$config_dir = $this->__page_obj->home_dir.$this->data_set_config_dir;
		$data_set_array = $this->read_conf_to_array($config_dir,$data_set_file.".set.conf");
		$data_set = $data_set_array['root'];
		//if(function_exists(apc_store)) {
		//	$result = apc_store('CONFIG_SET_'.$data_set_file,serialize($data_set));
		//}
	}
	foreach($data_set as $data_set_name=>$attributes) {
		if($data_set_name=='dsn') {
			$dsn = array(
			'phptype'=>$attributes['system'],
			'database'=>$attributes['dbname'],
			'hostspec'=>$attributes['host'],
			'port'=>$attributes['port'],
			'username'=>$attributes['user'],
			'password'=>$attributes['password'],
			);
			if($path = $attributes['path']) {
				if(substr($path,0,1)!='/') $path = $this->__page_obj->home_dir.'/'.$path;
				$dsn['path'] = $path;
			}
			$persistent = (bool) $attributes['persistent'];
		}
	}
	return $dsn;
}



} // end of DataView class
// }}}
?>
