<?php
defined('_JEXEC') or die('Direct Access to this location is not allowed.');
/**
* BreezingForms - A Joomla Forms Application
* @version 1.8
* @package BreezingForms
* @copyright (C) 2008-2012 by Markus Bopp
* @license Released under the terms of the GNU General Public License
**/
define("M_SEP", ", ");

class BFIntegrate{
	
	/**
	 * JDatabase
	 */
	private $db = null;
	
	private $rules = array();
	
	private $formId = -1;
	
	private $data = array();
	
	function __construct($formId){
		$this->db = JFactory::getDBO();
		$this->rules = $this->getRules($formId);
		$this->formId = $formId;
	}
	
	public function getRules($formId){
		
		$this->db->setQuery("
			Select 
				rules.*, 
				rules.id As id, 
				concat('".$this->db->getPrefix()."', rules.reference_table) As reference_table, 
				forms.name As form_name,
				forms.id As form_id
			From 
				#__facileforms_integrator_rules As rules,
				#__facileforms_forms As forms
			Where
				rules.form_id = forms.id
			And 
				rules.form_id = ".$this->db->Quote($formId)."
			And
				forms.id = ".$this->db->Quote($formId)."
			And
				rules.published = 1
			Group By 
				rules.id
			Order By 
				rules.id
			");
		
		$out = array();
		$rules = $this->db->loadObjectList();
		$i = 0;
                if($rules){
                    foreach ($rules As $rule){

                            $out[$i]['rule'] = $rule;
                            $out[$i]['items'] = array();

                            $i++;
                    }
                }
		return $out;
	}
	
	public function getItems($ruleId){
		
		$this->db->setQuery("
		
			Select 
				items.*,
				elements.name As element_name,
				elements.type As element_type
			From 
				#__facileforms_integrator_items As items,
				#__facileforms_elements As elements
			Where
				items.rule_id = ".$this->db->Quote($ruleId)."
			And
				elements.id = items.element_id
			And 
				items.published = 1
			Group By items.id
			Order By items.id Desc
		");
		
		$out = array();
		$items = $this->db->loadObjectList();
		$i = 0;
		foreach ($items As $item){
			
			$out[$i] = $item;
			$i++;
		}
		return $out;
	}
	
	public function getCriteria($ruleId){
		
		$this->db->setQuery("
		
			Select 
				crit.*,
				elements.name As element_name,
				elements.type As element_type
			From 
				#__facileforms_integrator_criteria_form As crit,
				#__facileforms_elements As elements
			Where
				crit.rule_id = ".$this->db->Quote($ruleId)."
			And
				elements.id = crit.element_id
			Group By crit.id
			Order By crit.id Desc
		");
		
		$ret = $this->db->loadObjectList();
		echo $this->db->getErrorMsg();
		return $ret;
	}
	
	public function getCriteriaJoomla($ruleId){
		
		$this->db->setQuery("
		
			Select 
				crit.*
			From 
				#__facileforms_integrator_criteria_joomla As crit
			Where
				crit.rule_id = ".$this->db->Quote($ruleId)."
			Group By crit.id
			Order By crit.id Desc
		");
		
		$ret = $this->db->loadObjectList();
		return $ret;
	}

	public function getCriteriaFixed($ruleId){
		
		$this->db->setQuery("
		
			Select 
				crit.*
			From 
				#__facileforms_integrator_criteria_fixed As crit
			Where
				crit.rule_id = ".$this->db->Quote($ruleId)."
			Group By crit.id
			Order By crit.id Desc
		");
		
		$ret = $this->db->loadObjectList();
		return $ret;
	}
	
	public function field(array $data){
		$this->data['data'.$data[_FF_DATA_ID]] = $data;
		$i = 0;
		foreach($this->rules As $rule){
			$items = $this->getItems($rule['rule']->id);
			$j = 0;
			foreach($items As $item){
				if($item->element_id == $data[_FF_DATA_ID]){
					$k = 0;
					while (isset($this->rules[$i]['items'][$j]['data'][$k])) { $k++; }	

					$this->rules[$i]['items'][$j]['item'] = $item;
					$this->rules[$i]['items'][$j]['data'][$k] = $data;
				}
				$j++;
			}
			$i++;
		}
	}
	
	public function handleCode($value, $code){
		if(trim($code) != ''){
			@eval($code);
		}
		return $value;
	}
	
	public function handleFinalizeCode($code){
		if(trim($code) != ''){
			@eval($code);
		}
	}
	
	public function commit(){

		foreach($this->rules As $rule){
			
			$valOk = true;
			$sql = '';
		
			if($rule['rule']->type == 'insert'){
				$sql = 'Insert Into '.$rule['rule']->reference_table.' (<keys>) Values (<values>)';	

				$keys = '';
				$values = '';
				foreach($rule['items'] As $item){
					$combinedValues = '';
					$keys .= '`'.$item['item']->reference_column . '`,';
					foreach($item['data'] as $data) {
						$value = $data[_FF_DATA_VALUE];

						try{
							$value = $this->handleCode($value, $item['item']->code);
						} catch(Exception $e){
							$valOk = false;
							break;
						}
						$combinedValues .= $value.M_SEP;
					}
					$combinedValues = rtrim($combinedValues, M_SEP);
					$values .= $this->db->Quote( $combinedValues ) . ',';
				}
				$keys = rtrim($keys,',');
				$values = rtrim($values,',');
				
				$sql = str_replace('<keys>',$keys,$sql);
				$sql = str_replace('<values>',$values,$sql);
					
				if($valOk && count($rule['items']) != 0){
                                    
                                        try{
                                    
                                            $this->db->setQuery($sql);
                                            $this->db->query();

                                            if(trim($rule['rule']->finalize_code) != ''){
                                                    $this->handleFinalizeCode($rule['rule']->finalize_code);
                                            }
                                        } catch(Exception $e){
                                            
                                        }
					
				}
			}
			else if($rule['rule']->type == 'update'){

				$sql = 'Update '.$rule['rule']->reference_table.' Set <keysvals> ';

				$criteria = $this->collectCriteria($rule['rule']->id);
				$keys = '';
				foreach($rule['items'] As $item){
					$value = $item['data'][0][_FF_DATA_VALUE];
					$combinedValues = '';

					foreach($item['data'] as $data) {
						$value = $data[_FF_DATA_VALUE];

						try{
							$value = $this->handleCode($value, $item['item']->code);
						} catch(Exception $e){
							$valOk = false;
							break;
						}
						$combinedValues .= $value.M_SEP;
					}
					$combinedValues = rtrim($combinedValues, M_SEP);

					$keys .= $item['item']->reference_column . '=' . $this->db->Quote( $combinedValues ) . ',';
				}
				$keys = rtrim($keys,',');
				
				$sql = str_replace('<keysvals>',$keys,$sql);

				$clauses = '';
				
				if(count($criteria['form']) != 0){
					
					foreach($criteria['form'] As $crit){
						
						if($clauses != ''){
							$clauses .= ' ' . $crit->andor . ' ';
						}
						
						$op = ' ';
						switch($crit->operator){
							case '%...%':
								$op = ' Like ' . $this->db->Quote( '%' . $this->data['data'.$crit->element_id][_FF_DATA_VALUE] . '%' );
								break;
							case '%...':
								$op = ' Like ' . $this->db->Quote( '%' . $this->data['data'.$crit->element_id][_FF_DATA_VALUE] );
								break;
							case '...%':
								$op = ' Like ' . $this->db->Quote( $this->data['data'.$crit->element_id][_FF_DATA_VALUE] . '%' );
								break;
							default: 
								$op = ' ' . $crit->operator . ' '. $this->db->Quote( $this->data['data'.$crit->element_id][_FF_DATA_VALUE] );
						}
						
						$clauses .= ' `' . $crit->reference_column . '` ' . $op;
					}
				}
				
				if(count($criteria['joomla']) != 0){
					
					foreach($criteria['joomla'] As $crit){
						
						if($clauses != ''){
							$clauses .= ' ' . $crit->andor . ' ';
						}
						
						$jobject = '';
						
						switch($crit->joomla_object){
							case 'Userid':
								$jobject = JFactory::getUser()->get('id', '');
								break;
							case 'Username':
								$jobject = JFactory::getUser()->get('username', '');
								break;
							case 'Language':
								$jobject = JFactory::getLanguage()->getName();
								break;
							case 'Date':
                                                                jimport('joomla.version');
                                                                $version = new JVersion();
                                                                if(version_compare($version->getShortVersion(), '3.0', '>=')){
                                                                    $jobject = JFactory::getDate()->toSql();
                                                                }else{
                                                                    $jobject = JFactory::getDate()->toMySQL();
                                                                }
								break;
						}
						
						$op = ' ';
						switch($crit->operator){
							case '%...%':
								$op = ' Like ' . $this->db->Quote( '%' . $jobject . '%' );
								break;
							case '%...':
								$op = ' Like ' . $this->db->Quote( '%' . $jobject );
								break;
							case '...%':
								$op = ' Like ' . $this->db->Quote( $jobject . '%' );
								break;
							default: 
								$op = ' ' . $crit->operator . ' '. $this->db->Quote( $jobject );
						}
						
						$clauses .= ' `' . $crit->reference_column . '` ' . $op;
					}
				}
				
				if(count($criteria['fixed']) != 0){
					
					foreach($criteria['fixed'] As $crit){
						
						if($clauses != ''){
							$clauses .= ' ' . $crit->andor . ' ';
						}
						
						$op = ' ';
						switch($crit->operator){
							case '%...%':
								$op = ' Like ' . $this->db->Quote( '%' . $crit->fixed_value . '%' );
								break;
							case '%...':
								$op = ' Like ' . $this->db->Quote( '%' . $crit->fixed_value );
								break;
							case '...%':
								$op = ' Like ' . $this->db->Quote( $crit->fixed_value . '%' );
								break;
							default: 
								$op = ' ' . $crit->operator . ' '. $this->db->Quote( $crit->fixed_value );
						}
						
						$clauses .= ' `' . $crit->reference_column . '` ' . $op;
					}
				}
				
				if($clauses != ''){
					$clauses = ' Where ' . $clauses;
				}
				
				$sql .= $clauses;
				
				if($valOk && count($rule['items']) != 0){
					
                                        try{
                                    
                                            $this->db->setQuery($sql);
                                            $ret = $this->db->query();

                                            // on update and no affected rows, we might like to add the row
                                            if($this->db->getAffectedRows($ret) <= 0){

                                                $sql = 'Insert Into '.$rule['rule']->reference_table.' (<keys>) Values (<values>)';

                                                $keys = '';
                                                $values = '';
                                                foreach($rule['items'] As $item){
                                                        $keys .= '`'.$item['item']->reference_column . '`,';
                                                        $value = $item['data'][_FF_DATA_VALUE];
                                                        try{
                                                                $value = $this->handleCode($value, $item['item']->code);
                                                        } catch(Exception $e){
                                                                $valOk = false;
                                                                break;
                                                        }
                                                        $values .= $this->db->Quote( $value ) . ',';
                                                }
                                                $keys = rtrim($keys,',');
                                                $values = rtrim($values,',');

                                                $sql = str_replace('<keys>',$keys,$sql);
                                                $sql = str_replace('<values>',$values,$sql);

                                                if($valOk && count($rule['items']) != 0){
                                                    try{
                                                        $this->db->setQuery($sql);
                                                        $this->db->query();
                                                    }catch(Exception $e){
                                                        
                                                    }
                                                }

                                            }

                                            if(trim($rule['rule']->finalize_code) != ''){
                                                    $this->handleFinalizeCode($rule['rule']->finalize_code);
                                            }
                                        
                                        }catch(Exception $e){
                                            
                                        }
				}
			}
		}
	}
	
	public function collectCriteria($ruleId){
		$crit['form'] = $this->getCriteria($ruleId);
		$crit['joomla'] = $this->getCriteriaJoomla($ruleId);
		$crit['fixed'] = $this->getCriteriaFixed($ruleId);
		return $crit;
	}
}