View source
<?php
class availability_calendar_handler_filter_availability extends views_handler_filter {
public static $instance;
protected $autoSubmit = FALSE;
public function __construct() {
self::$instance = $this;
$this->always_multiple = TRUE;
module_load_include('inc', 'availability_calendar');
}
public function option_definition() {
$options = parent::option_definition();
$options['value'] = array(
'contains' => array(
'from' => array(
'default' => '',
),
'to' => array(
'default' => '',
),
'to1' => array(
'default' => '',
),
'duration' => array(
'default' => '',
),
),
);
$options['operator'] = array(
'default' => 'from_duration',
);
return $options;
}
public function operators() {
$operators = array(
'at' => array(
'title' => t('At (date)'),
'method' => 'op_at',
'summary' => t('at %from'),
'values' => array(
'from',
),
),
'from_to' => array(
'title' => t('From begin up to and including end'),
'method' => 'op_from_to',
'summary' => t('From %from to %to'),
'values' => array(
'from',
'to',
),
),
'from_to1' => array(
'title' => t('From arrival to departure'),
'method' => 'op_from_to1',
'summary' => t('From %from to %to1'),
'values' => array(
'from',
'to1',
),
),
'from_duration' => array(
'title' => t('From begin during duration'),
'method' => 'op_from_duration',
'summary' => t('From %from during %duration days'),
'values' => array(
'from',
'duration',
),
),
);
return $operators;
}
public function operator_options($which = 'title') {
$options = array();
foreach ($this
->operators() as $id => $operator) {
$options[$id] = $operator[$which];
}
return $options;
}
public function value_form(&$form, &$form_state) {
$form['value']['#tree'] = TRUE;
if (empty($form_state['exposed'])) {
$form['value']['#element_validate'][] = 'availability_calendar_handler_filter_availability_validate_value';
}
$dependent_element = '';
$operators = $this
->operators();
if (!empty($form_state['exposed'])) {
if (empty($this->options['expose']['use_operator']) || empty($this->options['expose']['operator_id'])) {
$operators = array_intersect_key($operators, array(
$this->operator => 0,
));
}
else {
$dependent_element = $this->options['expose']['operator_id'];
}
}
else {
if (!empty($form['operator'])) {
$dependent_element = 'operator';
}
}
if ($dependent_element) {
$dependent_name = str_replace('_', '-', $dependent_element);
$dependency_source = $form[$dependent_element]['#type'] === 'radios' ? "radio:options[{$dependent_name}]" : "edit-{$dependent_name}";
}
else {
$dependency_source = NULL;
}
$values = array();
foreach ($operators as $operator => $options) {
foreach ($options['values'] as $value) {
if (isset($values[$value])) {
$values[$value][] = $operator;
}
else {
$values[$value] = array(
$operator,
);
}
}
}
foreach ($values as $value => $operators) {
if ($value !== 'duration') {
$form['value'][$value] = $this
->value_form_date_field($values[$value], $value, $dependency_source);
}
else {
$form['value'][$value] = $this
->value_form_duration_field($values[$value], $value, $dependency_source);
}
}
if (module_exists('date_popup')) {
if (!empty($form['value']['to'])) {
if (empty($form['value']['to1'])) {
$this
->change_elements_into_date_range_picker($form['value']['from'], 'to');
}
}
else {
if (!empty($form['value']['to1'])) {
$this
->change_elements_into_date_range_picker($form['value']['from'], 'to1');
}
}
}
}
protected function value_form_date_field($operators, $operand, $dependency_source) {
$operator = in_array($this->operator, $operators) ? $this->operator : reset($operators);
$variable_name = "availability_calendar_views_op_{$operator}_{$operand}";
$element = array(
'#type' => 'textfield',
'#title' => availability_calendar_get_customizable_text($variable_name),
'#size' => 12,
'#default_value' => $this->value[$operand],
);
if (module_exists('date_popup')) {
$this
->change_element_into_date_popup($element);
}
else {
$date_example = new DateTime();
if ($operand === 'to') {
$date_example
->modify('+6');
}
else {
if ($operand === 'to1') {
$date_example
->modify('+7');
}
}
$date_example = availability_calendar_format_entry_date($date_example);
$element['#description'] = t('E.g., @date', array(
'@date' => $date_example,
));
}
if ($dependency_source !== NULL) {
$element['#dependency'] = array(
$dependency_source => $operators,
);
}
return $element;
}
protected function value_form_duration_field($operators, $operand, $dependency_source) {
$operator = in_array($this->operator, $operators) ? $this->operator : reset($operators);
$options = array(
0 => t('- Select duration -'),
);
for ($i = 1; $i <= 28; $i++) {
if ($i % 7 === 0) {
$options[$i] = format_plural($i / 7, '1 week', '@count weeks');
}
else {
if ($i <= 20) {
if ($this->definition['allocation_type'] === AC_ALLOCATION_TYPE_FULLDAY) {
$options[$i] = format_plural($i, '1 day', '@count days');
}
else {
$options[$i] = format_plural($i, '1 night', '@count nights');
}
}
}
}
$variable_name = "availability_calendar_views_op_{$operator}_{$operand}";
$element = array(
'#type' => 'select',
'#title' => availability_calendar_get_customizable_text($variable_name),
'#options' => $options,
'#default_value' => $this->value[$operand],
);
if ($dependency_source !== NULL) {
$element['#dependency'] = array(
$dependency_source => $operators,
);
}
return $element;
}
protected function change_element_into_date_popup(&$element) {
$element['#type'] = 'date_popup';
$element['#date_label_position'] = 'none';
$element['#date_type'] = 'DATE_ISO';
$element['#date_format'] = variable_get('date_format_availability_calendar_date_entry', AC_DATE_ENTRY);
$element['#datepicker_options'] = $this
->get_date_popup_options();
}
protected function change_elements_into_date_range_picker(array &$elementFrom, $operand) {
$elementFrom['#datepicker_options'] += $this
->get_date_range_picker_options($operand);
$elementFrom['#attributes'] = array(
'data-date-range-end' => "[from] [{$operand}]",
);
$elementFrom['#attached']['js'][] = drupal_get_path('module', 'availability_calendar') . '/BuroRaDer.DateRangePicker.js';
$elementFrom['#attached']['css'][] = drupal_get_path('module', 'availability_calendar') . '/BuroRaDer.DateRangePicker.css';
$elementFrom['#attached']['js'][] = drupal_get_path('module', 'availability_calendar') . '/availability_calendar.date-range-picker.js';
}
protected function get_date_popup_options() {
$field_info = availability_calendar_get_field_instance_info($this->real_field);
$show_number_of_months = NULL;
$show_week_number = FALSE;
$first_day_of_week = NULL;
foreach ($field_info['bundles'] as $entity_type => $bundles) {
foreach ($bundles as $bundle => $field_instance_info) {
$settings = $field_instance_info['display']['default']['settings'];
if (isset($settings['show_number_of_months'])) {
$show_number_of_months = $show_number_of_months === NULL ? $settings['show_number_of_months'] : min($show_number_of_months, (int) $settings['show_number_of_months']);
}
if (isset($settings['first_day_of_week'])) {
if ($first_day_of_week !== FALSE) {
if ($first_day_of_week === NULL) {
$first_day_of_week = (int) $settings['first_day_of_week'];
}
else {
if ($first_day_of_week != (int) $settings['first_day_of_week']) {
$first_day_of_week = FALSE;
}
}
}
}
if (isset($settings['show_week_number'])) {
$show_week_number = $show_week_number || (bool) $settings['show_week_number'];
}
}
}
if ($first_day_of_week === NULL | $first_day_of_week === FALSE) {
$first_day_of_week = variable_get('date_first_day', 6);
}
return array(
'firstDay' => $first_day_of_week,
'minDate' => 0,
'maxDate' => sprintf('+%dm', $show_number_of_months),
'showWeek' => $show_week_number,
);
}
protected function get_date_range_picker_options($operand) {
$field_info = availability_calendar_get_field_instance_info($this->real_field);
$show_split_day = TRUE;
$first_day_of_week = NULL;
foreach ($field_info['bundles'] as $entity_type => $bundles) {
foreach ($bundles as $bundle => $field_instance_info) {
$show_split_day = $show_split_day && (bool) $field_instance_info['display']['default']['settings']['show_split_day'];
}
}
return array(
'showSplitDay' => $show_split_day,
'isTo1' => $operand === 'to1',
'minRangeDuration' => $operand === 'to1' ? 1 : 0,
'doneText' => availability_calendar_get_customizable_text('availability_calendar_date_range_picker_done'),
'clearText' => availability_calendar_get_customizable_text('availability_calendar_date_range_picker_clear'),
);
}
public function exposed_validate(&$form, &$form_state) {
if (empty($this->options['exposed'])) {
return;
}
$this
->validate_value($form[$this->options['expose']['identifier']], $form_state);
$this->autoSubmit = (bool) (!empty($form_state['exposed'])) && $form_state['exposed_form_plugin']->options['autosubmit'];
}
public function validate_value(&$element, $form_state) {
if (empty($form_state['exposed'])) {
if ($form_state['values']['options']['expose_button']['checkbox']['checkbox']) {
return;
}
$required = FALSE;
$autoSubmit = FALSE;
$operator = $form_state['values']['options']['operator'];
}
else {
$required = (bool) $this->options['expose']['required'];
$autoSubmit = (bool) $form_state['exposed_form_plugin']->options['autosubmit'];
$operator = empty($this->options['expose']['use_operator']) ? $this->operator : $form_state['values'][$this->options['expose']['operator_id']];
}
$operators = $this
->operators();
$values = empty($operator) ? array(
'from',
'to',
'to1',
'duration',
) : $operators[$operator]['values'];
$today = new DateTime();
$today
->setTime(0, 0, 0);
$value = drupal_array_get_nested_value($form_state['values'], $element['#parents']);
$from_valid = FALSE;
$requireFrom = FALSE;
if (in_array('from', $values) && array_key_exists('from', $value)) {
$from_valid = $this
->validate_valid_time_1($element['from'], $value['from'], $required && !$autoSubmit, $today, t('Only future availability can be searched.'));
}
if (in_array('to', $values) && array_key_exists('to', $value)) {
$to_valid = $this
->validate_valid_time_1($element['to'], $value['to'], ($required || $from_valid instanceof DateTime) && !$autoSubmit, $from_valid, t('The end date should be on or after the start date.'));
if ($to_valid instanceof DateTime) {
$requireFrom = TRUE;
}
}
if (in_array('to1', $values) && array_key_exists('to1', $value)) {
$to1_valid = $this
->validate_valid_time_1($element['to1'], $value['to1'], ($required || $from_valid instanceof DateTime) && !$autoSubmit, $from_valid, t('The departure date should be after the arrival date.'));
if ($to1_valid instanceof DateTime) {
$requireFrom = TRUE;
}
}
if (in_array('duration', $values) && array_key_exists('duration', $value)) {
$duration_valid = $this
->validate_valid_duration($element['duration'], $value['duration'], ($required || $from_valid instanceof DateTime) && !$autoSubmit);
if ($duration_valid && !empty($value['duration'])) {
$requireFrom = TRUE;
}
}
if ($from_valid && $requireFrom && !$autoSubmit && empty($value['from'])) {
form_error($element['from'], t('Field %field is required.', array(
'%field' => $element['from']['#title'],
)));
}
}
protected function validate_valid_time_1(&$element, $value, $required, $minimum, $minimum_error_message) {
if (is_array($value)) {
$value = $value['date'];
}
if (empty($value)) {
$result = !$required;
if ($required) {
form_error($element, t('Field %field is required.', array(
'%field' => $element['#title'],
)));
}
}
else {
if (($result = availability_calendar_parse_entry_date($value)) === FALSE) {
$result = $value == $element['#default_value'];
if (!$result) {
form_error($element, t('Invalid date format.'));
}
}
else {
if ($minimum instanceof DateTime && $result < $minimum) {
form_error($element, $minimum_error_message);
$result = FALSE;
}
}
}
return $result;
}
protected function validate_valid_duration(&$element, $value, $required) {
$valid = TRUE;
if (empty($value)) {
if ($required) {
form_error($element, t('Field %field is required.', array(
'%field' => $element['#title'],
)));
$valid = FALSE;
}
}
else {
if (!is_int($value) && !ctype_digit($value) || $value <= 0) {
form_error($element, t('Duration must be a positive number of days.'));
$valid = FALSE;
}
}
return $valid;
}
public function accept_exposed_input($input) {
if (empty($this->options['exposed'])) {
return TRUE;
}
if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator_id']) && isset($input[$this->options['expose']['operator_id']])) {
$this->operator = $input[$this->options['expose']['operator_id']];
}
if (!empty($this->options['expose']['identifier'])) {
$this->value = $input[$this->options['expose']['identifier']];
$operators = $this
->operators();
$values = $operators[$this->operator]['values'];
$from =& $this
->getValidOrEmptyValue($this->value[$values[0]], $values[0]);
if (count($values) === 1) {
return !empty($from);
}
else {
$other =& $this
->getValidOrEmptyValue($this->value[$values[1]], $values[1]);
if ($this->autoSubmit) {
$this
->fillEmptyValueFromOther($from, $other, $values[1]);
}
return !empty($from) && !empty($other);
}
}
return TRUE;
}
protected function &getValidOrEmptyValue(&$value, $type) {
$empty = empty($value);
if (!$empty) {
$valid = $type === 'duration' ? (is_int($value) || ctype_digit($value)) && $value > 0 : availability_calendar_parse_entry_date($value) !== FALSE;
if (!$valid) {
$value = NULL;
}
}
return $value;
}
protected function fillEmptyValueFromOther(&$value1, &$value2, $type) {
if ($type === 'to' || $type === 'to1') {
if (empty($value2)) {
$value2 = $value1;
}
else {
if (empty($value1)) {
if ($type === 'to') {
$value1 = $value2;
}
else {
$from = availability_calendar_parse_entry_date($value2);
$from
->modify('-1 day');
$value1 = $from
->format(AC_ISODATE);
}
}
}
}
}
public function query() {
$operators = $this
->operators();
if (isset($operators[$this->operator]['method'])) {
$this
->{$operators[$this->operator]['method']}();
}
}
protected function op_at() {
$this->value['duration'] = 1;
$this
->op_from_duration();
}
protected function op_from_to() {
$this
->build_query(availability_calendar_parse_entry_date($this->value['from']), availability_calendar_parse_entry_date($this->value['to']));
}
protected function op_from_to1() {
$from = availability_calendar_parse_entry_date($this->value['from']);
$to = availability_calendar_parse_entry_date($this->value['to1']);
if ($from instanceof DateTime && $to instanceof DateTime) {
if ($to > $from) {
$to
->modify('-1 day');
}
$this
->build_query($from, $to);
}
}
protected function op_from_duration() {
$this
->build_query(availability_calendar_parse_entry_date($this->value['from']), (int) $this->value['duration']);
}
protected function build_query($from, $to_or_duration) {
$this
->ensure_my_table();
availability_calendar_query_available($this->query, $this->table_alias, $this->real_field, $from, $to_or_duration, $this->definition['default_state']);
}
public function admin_summary() {
$output = '';
if (!empty($this->options['exposed'])) {
$output = t('exposed');
}
else {
$operators = $this
->operators();
if (isset($operators[$this->operator]['summary'])) {
$arguments = array();
foreach ($this->value as $key => $value) {
$arguments["%{$key}"] = $value;
}
$output = format_string($operators[$this->operator]['summary'], $arguments);
}
}
return $output;
}
}
function availability_calendar_handler_filter_availability_validate_value(&$element, &$form_state) {
availability_calendar_handler_filter_availability::$instance
->validate_value($element, $form_state);
}