<?php
/**
 * AgileBill - Open Billing Software
 *
 * This body of work is free software; you can redistribute it and/or
 * modify it under the terms of the Open AgileBill License
 * License as published at http://www.agileco.com/agilebill/license1-4.txt
 *
 * Originally authored by Tony Landis, AgileBill LLC
 *
 * Recent modifications by Deon George
 *
 * @author Deon George <deonATleenooksDOTnet>
 * @copyright 2009 Deon George
 * @link http://osb.leenooks.net
 *
 * @link http://www.agileco.com/
 * @copyright 2004-2008 Agileco, LLC.
 * @license http://www.agileco.com/agilebill/license1-4.txt
 * @author Tony Landis <tony@agileco.com>
 * @package AgileBill
 * @subpackage Core
 */

/**
 * The main AgileBill CORE Database SEARCH Method
 *
 * @uses CORE_validate
 * @uses CORE_trigger
 * @uses CORE_search
 */

function CORE_database_search($VAR,$construct,$type) {
	global $C_list;

	include_once(PATH_CORE.'validate.inc.php');
	$validate = new CORE_validate;

	$db = &DB();

	# Set the search criteria array
	$arr = $VAR;

	# Loop through the submitted field_names to get the WHERE statement
	$where_list = '';
	$i=0;
	$pat = sprintf('/^%s_/',$construct->module);
	while (list($key,$value) = each($arr)) {
		if ($value != '') {
			if (preg_match($pat,$key)) {
				$field = preg_replace($pat,'',$key);

				if (! is_array($value) && preg_match('/%/',$value)) {
					# Do any data conversion for this field (date, encrypt, etc...)
					if (isset($construct->field[$field]['convert']))
						$value = $validate->convert($field,$value,$construct->field[$field]['convert']);

					if ($i)
						$where_list .= sprintf(' AND %s LIKE %s ',$field,$db->qstr($value,get_magic_quotes_gpc()));
					else
						$where_list .= sprintf(' WHERE %s LIKE %s',$field,$db->qstr($value,get_magic_quotes_gpc()));

					$i++;

				} else {
					# Check if array
					if (is_array($value)) {
						for ($i_arr=0; $i_arr<count($value); $i_arr++) {
							if ($value[$i_arr] != '') {
								# Determine any field options (=, >, <, etc...)
								$f_opt = '=';
								$pat_field = sprintf('%s_%s',$construct->module,$field);

								if (isset($VAR['field_option'][$pat_field][$i_arr])) {
									$f_opt = $VAR['field_option'][$pat_field][$i_arr];
									# Error checking, safety precaution
									if (! in_array($f_opt,array('=','>','<','>=','<=','!=')))
										$f_opt = '=';
								}

								# Do any data conversion for this field (date, encrypt, etc...)
								if (isset($construct->field[$field]['convert']))
									$value[$i_arr] = $validate->convert($field,$value[$i_arr],$construct->field[$field]['convert']);

								if (($i_arr == 0) && ($i==0))
									$where_list .= sprintf(' WHERE %s %s %s',$field,$f_opt,$db->qstr($value[$i_arr],get_magic_quotes_gpc()));
								else
									$where_list .= sprintf(' AND %s %s %s',$field,$f_opt,$db->qstr($value[$i_arr],get_magic_quotes_gpc()));

								$i++;
							}
						}

					} else {
						if ($i)
							$where_list .= sprintf(' AND %s=%s ',$field,$db->qstr($value,get_magic_quotes_gpc()));
						else
							$where_list .= sprintf(' WHERE %s=%s',$field,$db->qstr($value,get_magic_quotes_gpc()));

						$i++;
					}
				}
			}
		}
	}

	# Some table joins
	$join_table = '';
	if (isset($VAR['join']) && is_array($VAR['join']))
		foreach ($VAR['join'] as $table => $joins)
			if ($C_list->is_installed($table)) {

				include_once(PATH_MODULES.sprintf('%s/%s.inc.php',$table,$table));
				$join = new $table;

				if (method_exists($join,'sql_join')) {
					foreach ($joins as $jointable => $id)
						$q_join .= $join->sql_join($jointable,$id);

					$join_table .= sprintf(',%s%s',AGILE_DB_PREFIX,$jointable);
				}

				if ($where_list)
					$where_list .= sprintf(' AND %s',$q_join);
				else
					$where_list .= sprintf(' WHERE %s',$q_join);
			}

	# Finalize the WHERE statement
	if ($where_list == '')
		$where_list .= ' WHERE ';
	else
		$where_list .= ' AND ';

	# Get limit type
	if (isset($VAR['limit']))
		$limit = $VAR['limit'];
	else
		$limit = $construct->limit;

	# Get order by
	if (isset($VAR['order_by']))
		$order_by = $VAR['order_by'];
	else
		$order_by = $construct->order_by;

	# Get any addition fields to select:
	if (isset($construct->custom_EXP))
		for ($ei=1; $ei<count($construct->custom_EXP); $ei++)
			$field_list = sprintf(',%s',$construct->custom_EXP[$ei]['field']);

	# Get any static vars to search
	$join_list = '';
	$pre = AGILE_DB_PREFIX;
	if (! empty($VAR['static_relation']) && count($VAR['static_relation']>0)) {
		while (list($idx,$value) = each($VAR['static_relation'])) {
			if ($value != '') {
				$join_list .= sprintf(" INNER JOIN %sstatic_var_record AS s%s ON (s%s.record_id=%s%s.id AND s%s.static_var_relation_id='%s' AND s%s.site_id=%s AND",
					$pre,$idx,$idx,$pre,$this->table,$idx,$idx,$idx,$db->qstr(DEFAULT_SITE));

				if(preg_match('/%/',$value))
					$join_list .= sprintf(' s%s.value LIKE %s',$idx,$db->qstr($VAR['static_relation'][$idx]));
				else
					$join_list .= sprintf(' s%s.value = %s',$idx,$db->qstr($VAR['static_relation'][$idx]));

				$join_list .= ') ';
			}
		}
	}

/*
        # standard where list
        $q .= $join_list . $where_list ." ".AGILE_DB_PREFIX."account.site_id = " . $db->qstr(DEFAULT_SITE);

        # Code for member group
        if(!empty($VAR['account_group'])) {
            $q .= " AND ".AGILE_DB_PREFIX."account_group.group_id = " . $db->qstr($VAR['account_group'])."
                    AND ".AGILE_DB_PREFIX."account_group.site_id  = " . $db->qstr(DEFAULT_SITE);
        }
        if(!empty($VAR['account_group'])) {
            $q_save .= " LEFT JOIN ".AGILE_DB_PREFIX."account_group ON ".AGILE_DB_PREFIX."account_group.account_id = ".AGILE_DB_PREFIX."account.id  ";

            if(!empty($join_list))
                $q_save .= $join_list;

            $q_save .= $where_list ." %%whereList%% ";
            $q_save .= AGILE_DB_PREFIX."account_group.group_id = " . $db->qstr($VAR['account_group'])." AND ";
        } else {
            if(!empty($join_list))
                $q_save .= $join_list;

            $q_save .= $where_list ." %%whereList%% ";
        }
*/

	# generate the full query
	$q = sprintf('SELECT %s%s.id AS id%s FROM %s%s %s %s %s%s.site_id=%s',
		AGILE_DB_PREFIX,$construct->table,$field_list,
		AGILE_DB_PREFIX,$construct->table,$join_table,
		$where_list,AGILE_DB_PREFIX,$construct->table,DEFAULT_SITE);
	$q_save = "SELECT %%fieldList%% FROM %%tableList%% $join_table".$where_list." %%whereList%% ";
	$result = $db->Execute($q);

	# Error reporting
	if ($result === false) {
		global $C_debug;
		$C_debug->error(__FILE__,__METHOD__,$db->ErrorMsg());

		if (isset($construct->trigger[$type])) {
			include_once(PATH_CORE.'trigger.inc.php');
			$trigger = new CORE_trigger;
			$trigger->trigger($construct->trigger[$type],0,$VAR);
		}

		return;
	}

	# Get the result count:
	$results = $result->RecordCount();

	# Get the first record id:
	if ($results == 1)
		$record_id = $result->fields['id'];

	# Run any custom validation on this result for this module
	if (isset($construct->custom_EXP)) {
		$results = 0;

		while (! $result->EOF) {
			for ($ei=0; $ei<count($construct->custom_EXP); $ei++) {
				$field = $construct->custom_EXP[$ei]['field'];
				$value = $construct->custom_EXP[$ei]['value'];

				if ($result->fields[$field] == $value) {
					$ei = count($construct->custom_EXP);
					$results++;
				}
			}

			$result->MoveNext();
		}
	}

	# Define the DB vars as a Smarty accessible block
	global $smarty;

	# Create the definition for fast-forwarding to a single record:
	if ($results == 1 && !isset($construct->fast_forward))
		$smarty->assign('record_id',$record_id);

	# create the search record:
	if ($results > 0) {
		# create the search record
		include_once(PATH_CORE.'search.inc.php');
		$search = new CORE_search;
		$arr['module'] = $construct->module;
		$arr['sql']	= $q_save;
		$arr['limit'] = $limit;
		$arr['order_by']= $order_by;
		$arr['results']	= $results;
		$search->add($arr);

		# define the search id and other parameters for Smarty
		$smarty->assign('search_id',$search->id);
		# page:
		$smarty->assign('page','1');
		# limit:
		$smarty->assign('limit',$limit);
		# order_by:
		$smarty->assign('order_by',$order_by);
	}

	# define the result count
	$smarty->assign('results',$results);

	if (isset($construct->trigger[$type])) {
		include_once(PATH_CORE.'trigger.inc.php');
		$trigger = new CORE_trigger;
		$trigger->trigger($construct->trigger[$type],1,$VAR);
	}
}
?>