private function _validate_dependencies($id, $referer = array())
{
// reference to the form submission method
global ${'_' . $this->form_properties['method']};
$method =& ${'_' . $this->form_properties['method']};
// if the rule is applied to a radio button group or a checkbox group
// there will be no entry with the given id as all group's elements will have their ID in the form of [name]_[value]
if (!isset($this->controls[$id])) {
// ...therefore, we have to iterate over all the form's controls
foreach ($this->controls as $control) {
// and if we find the control we're looking for
if (preg_replace('/\\[\\]$/', '', $control->attributes['name']) == $id) {
// get the ID of the control
$id = $control->attributes['id'];
// don't look any further
break;
}
}
}
// if there are more than 2 entries in the referer array, remove the first one
if (count($referer) > 2) {
array_shift($referer);
}
// if current element is the referer array
if (in_array($id, $referer)) {
// we're having a recursion and we're stopping execution
_zebra_form_show_error('Infinite recursion detected. The loop of dependencies is created by the following elements: "' . implode('", "', $referer) . '"', E_USER_ERROR);
}
// add current element to the stack
array_push($referer, $id);
$result = true;
// if the control exists
if (isset($this->controls[$id])) {
// if we're checking if a proxy depends on another proxy, but it doesn't, return TRUE now
if (!isset($this->controls[$id]->rules['dependencies'])) {
return true;
}
// get all the conditions needed to validate the element
$conditions = $this->controls[$id]->rules['dependencies'];
// if the name of a callback function is also given
// the actual conditions are in the first entry of the array
if (isset($conditions[1])) {
$conditions = $conditions[0];
}
// iterate through the elements the validation of the current element depends on (proxies)
foreach ($conditions as $proxy => $required_values) {
// if we have a cached result of the result
if (isset($this->proxies_cache[$proxy][serialize($required_values)])) {
// get the result from cache
$result = $this->proxies_cache[$proxy][serialize($required_values)];
} else {
$is_radio_or_checkbox = false;
// $this->controls[$proxy] will never be set for radio or checkbox controls (as $proxy is the ID, not the name)
if (!isset($this->controls[$proxy])) {
// iterate through all the controls
foreach ($this->controls as $control_properties) {
// if we found a control radio/checkbox element with the sought name
if ($control_properties->attributes['name'] == $proxy && ($control_properties->attributes['type'] == 'radio' || $control_properties->attributes['name'] == 'checkbox')) {
// set this flag
$is_radio_or_checkbox = true;
// don't look further
break;
}
}
}
$found = false;
// a proxy may also depend on the values of or or more other proxies
// therefore, continue only if those conditions are met
if ((isset($this->controls[$proxy]) || $is_radio_or_checkbox) && (!$is_radio_or_checkbox && $this->controls[$proxy]->attributes['type'] == 'image' && isset($method[$proxy . '_x']) && isset($method[$proxy . '_y']) || isset($method[$proxy])) && $this->_validate_dependencies($proxy, $referer)) {
// if proxy is a submit or an image submit button
if (!$is_radio_or_checkbox && in_array($this->controls[$proxy]->attributes['type'], array('image', 'submit'))) {
$current_values = array('click');
} else {
$current_values = !is_array($method[$proxy]) ? array($method[$proxy]) : $method[$proxy];
}
// if condition is not an array
if (!is_array($required_values)) {
// iterate through the proxy's values
// (remember, we store it as an array even if there's a single value)
foreach ($current_values as $current_value) {
// if the value of the condition is amongst the proxy's values, flag it
if ($current_value == $required_values) {
$found = true;
}
}
// if condition is given as an array
} else {
// iterate through all the conditions
foreach ($required_values as $required_value) {
$matches = 0;
// iterate through the values of the proxy element
// (remember, we store it as an array even if there's a single value)
foreach ($current_values as $current_value) {
// if current entry in the conditions list is not an array
// and its value is equal to the current value
if (!is_array($required_value) && $current_value == $required_value) {
$found = true;
} else {
if (is_array($required_value) && in_array($current_value, $required_value)) {
$matches++;
}
}
}
// if all conditions are met
if (!$found && $matches == count($required_values)) {
$result = true;
}
}
}
// if not all conditions are met, don't check any further
if (!$found) {
$result = false;
break;
}
// if proxy is not submitted, or proxy's dependendecies are not ok, don't check the other conditions
} else {
$result = false;
}
}
// cache the result
if (!isset($this->proxies_cache[$proxy][serialize($required_values)])) {
$this->proxies_cache[$proxy][serialize($required_values)] = $result;
}
}
}
// if script gets this far, consider all the conditions are met, and validate the other rules
return $result;
}