/home/crealab/cars.brainware.com.co/wp-content/plugins/jet-booking/includes/settings.php
<?php

namespace JET_ABAF;

defined( 'ABSPATH' ) || exit; // Exit if accessed directly.

class Settings {

	/**
	 * Default settings array
	 *
	 * @var array
	 */
	private $defaults = [
		'is_set'                      => false,
		'hide_columns_manager'        => false,
		'related_post_type'           => '',
		'wc_integration'              => false,
		'wc_product_id'               => '',
		'wc_sync_orders'              => false,
		'filters_store_type'          => 'session',
		'additional_columns'          => [],
		'apartment_post_type'         => '',
		'booking_period'              => 'per_nights',
		'allow_checkout_only'         => false,
		'weekly_bookings'             => false,
		'week_offset'                 => '',
		'one_day_bookings'            => false,
		'start_day_offset'            => '',
		'end_date_type'               => 'none',
		'end_date_range_number'       => '1',
		'end_date_range_unit'         => 'year',
		'min_days'                    => '',
		'max_days'                    => '',
		'month_select'                => false,
		'year_select'                 => false,
		'show_calendar_price'         => false,
		'use_custom_labels'           => false,
		'hide_setup'                  => false,
		'ical_synch'                  => false,
		'remove_temporary_bookings'   => false,
		'remove_interval'             => 'daily',
		'booking_cancellation'        => false,
		'cancellation_limit'          => 1,
		'cancellation_unit'           => 'week',
		'modification_limit'          => 1,
		'modification_unit'           => 'week',
		'labels_booked'               => 'Sold out',
		'labels_only_checkout'        => 'Only checkout',
		'labels_selected'             => 'Chosen:',
		'labels_nights'               => 'Nights',
		'labels_days'                 => 'Days',
		'labels_apply'                => 'Close',
		'labels_week_1'               => 'Mon',
		'labels_week_2'               => 'Tue',
		'labels_week_3'               => 'Wed',
		'labels_week_4'               => 'Thu',
		'labels_week_5'               => 'Fri',
		'labels_week_6'               => 'Sat',
		'labels_week_7'               => 'Sun',
		'labels_month_name'           => 'January, February, March, April, May, June, July, August, September, October, November, December',
		'labels_past'                 => 'Past',
		'labels_previous'             => 'Previous',
		'labels_prev_week'            => 'Week',
		'labels_prev_month'           => 'Month',
		'labels_prev_year'            => 'Year',
		'labels_default'              => 'Please select a date range',
		'synch_interval'              => 'daily',
		'synch_interval_hours'        => '00',
		'synch_interval_mins'         => '00',
		'days_off'                    => [],
		'disable_weekday_1'           => false,
		'check_in_weekday_1'          => false,
		'check_out_weekday_1'         => false,
		'disable_weekday_2'           => false,
		'check_in_weekday_2'          => false,
		'check_out_weekday_2'         => false,
		'disable_weekday_3'           => false,
		'check_in_weekday_3'          => false,
		'check_out_weekday_3'         => false,
		'disable_weekday_4'           => false,
		'check_in_weekday_4'          => false,
		'check_out_weekday_4'         => false,
		'disable_weekday_5'           => false,
		'check_in_weekday_5'          => false,
		'check_out_weekday_5'         => false,
		'disable_weekend_1'           => false,
		'check_in_weekend_1'          => false,
		'check_out_weekend_1'         => false,
		'disable_weekend_2'           => false,
		'check_in_weekend_2'          => false,
		'check_out_weekend_2'         => false,
		'booking_hold_time'           => '300',
		'field_layout'                => 'single',
		'field_position'              => 'inline',
		'field_label'                 => '',
		'field_placeholder'           => 'YYYY-MM-DD',
		'check_in_field_label'        => '',
		'check_in_field_placeholder'  => 'YYYY-MM-DD',
		'check_out_field_label'       => '',
		'check_out_field_placeholder' => 'YYYY-MM-DD',
		'field_description'           => '',
		'field_date_format'           => 'YYYY-MM-DD',
		'field_separator'             => '-',
		'field_start_of_week'         => 'monday',
		'booking_mode'                => 'plain',
	];

	/**
	 * Settings DB key
	 *
	 * @var string
	 */
	private $key = 'jet-abaf';

	/**
	 * Stored settings cache
	 *
	 * @var null
	 */
	private $settings = null;

	/**
	 * Stored labels
	 *
	 * @var null
	 */
	private $labels = null;

	/**
	 * Booking configuration setting holder.
	 *
	 * @var bool
	 */
	public $config_settings = false;

	/**
	 * Booked days holder.
	 *
	 * @var array
	 */
	private $booked_dates = [];

	public function __construct() {

		add_action( 'wp_ajax_jet_abaf_save_settings', [ $this, 'ajax_save_settings' ] );
		add_action( 'wp_ajax_jet_abaf_process_tables', [ $this, 'ajax_process_tables' ] );

		if ( is_admin() && ! wp_doing_ajax() ) {
			$this->hook_db_columns();
		}

	}

	/**
	 * AJAX save settings.
	 *
	 * Save settings by AJAX request.
	 *
	 * @since  1.0.0
	 * @since  2.6.2 Added `nonce` security check.
	 * @since  2.8.0 Small optimization.
	 * @since  3.0.0 Added reload for some setting change.
	 * @access public
	 *
	 * @return void
	 */
	public function ajax_save_settings() {

		if ( empty( $_REQUEST['nonce'] ) || ! wp_verify_nonce( $_REQUEST['nonce'], 'jet-abaf-settings' ) ) {
			wp_send_json_error( [
				'message' => __( 'Security check failed.', 'jet-booking' ),
			] );
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( [
				'message' => __( 'Access denied. Not enough permissions.', 'jet-booking' ),
			] );
		}

		$data     = ! empty( $_REQUEST['settings'] ) ? $_REQUEST['settings'] : [];
		$settings = wp_parse_args( $data, $this->defaults );

		if ( empty( $settings ) ) {
			wp_send_json_error( [
				'message' => __( 'Empty data.', 'jet-booking' ),
			] );
		}

		if ( ! isset( $settings['additional_columns'] ) ) {
			$settings['additional_columns'] = [];
		}

		$response        = [ 'message' => __( 'Settings saved!', 'jet-booking' ) ];
		$reload_settings = [ 'booking_mode', 'ical_synch' ];

		foreach ( $settings as $setting => $value ) {
			if ( $this->setting_registered( $setting ) ) {
				$value = $this->sanitize_setting( $setting, $value );
				$value = apply_filters( 'jet-booking/settings/on-save/value', $value, $setting );

				if ( ! jet_abaf()->wc->has_woocommerce() ) {
					if ( 'is_set' !== $setting && $value !== $this->get( $setting ) ) {
						if ( 'booking_mode' !== $setting ) {
							$settings['booking_mode'] = 'plain';
						} else {
							$value = 'plain';
						}
					}

					if ( 'booking_mode' === $setting && 'wc_based' === $settings[ $setting ] ) {
						wp_send_json_error( [
							'message' => __( 'WooCommerce Based booking mode setting requires WooCommerce to be installed and activated.', 'jet-booking' ),
						] );
					}
				}

				if ( in_array( $setting, $reload_settings ) && $value !== $this->get( $setting ) ) {
					$response['message'] = __( 'Settings saved! <br> This setting requires page reloading. Page will be reloaded automatically in a few seconds.', 'jet-booking' );
					$response['reload']  = true;
				}

				$this->update( $setting, $value, false );
			}
		}

		do_action( 'jet-booking/settings/on-ajax-save', $this );

		$this->write();

		wp_send_json_success( $response );

	}

	/**
	 * AJAX process tables.
	 *
	 * AJAX callback for creating/saving DB tables.
	 *
	 * @since  1.0.0
	 * @since  2.6.2 Added `nonce` security check.
	 * @since  3.3.0 Refactored table creation part.
	 */
	public function ajax_process_tables() {

		if ( empty( $_REQUEST['nonce'] ) || ! wp_verify_nonce( $_REQUEST['nonce'], 'jet-abaf-settings' ) ) {
			wp_send_json_error( [
				'message' => __( 'Security check failed.', 'jet-booking' ),
			] );
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( [
				'message' => __( 'Access denied. Not enough permissions.', 'jet-booking' ),
			] );
		}

		$message = __( 'DB tables created!', 'jet-booking' );

		ob_start();

		try {
			if ( ! jet_abaf()->db->units->is_table_exists() ) {
				jet_abaf()->db->units->create_table();
			}

			if ( jet_abaf()->db->bookings->is_table_exists() ) {
				$message = __( 'DB tables updated!', 'jet-booking' );
				jet_abaf()->db->update_columns_diff( $this->get_clean_columns() );
			} else {
				$this->hook_db_columns();
				jet_abaf()->db->bookings->create_table();
			}
		} catch ( \Exception $e ) {
			ob_get_clean();
			wp_send_json_error( [ 'message' => $e->getMessage() ] );
		}

		$warnings = ob_get_clean();

		if ( ! empty( $warnings ) ) {
			wp_send_json_error( [ 'message' => $warnings ] );
		} else {
			wp_send_json_success( [ 'message' => $message ] );
		}

	}

	/**
	 * Get preapred additional columns list
	 *
	 * @return array
	 */
	public function get_clean_columns() {

		$columns       = $this->get( 'additional_columns' );
		$clean_columns = array();

		if ( empty( $columns ) ) {
			return $clean_columns;
		}

		foreach ( $columns as $column ) {
			if ( ! empty( $column['column'] ) ) {
				$clean_columns[] = $this->sanitize_column_name( $column['column'] );
			}
		}

		return $clean_columns;

	}

	public function sanitize_column_name( $column ) {
		return sanitize_key( str_replace( array( ' ', '-' ), '_', $column ) );
	}

	/**
	 * Hook new DB columns.
	 *
	 * @since  2.0.0
	 * @access public
	 *
	 * @return void
	 */
	public function hook_db_columns() {

		$columns = $this->get_clean_columns();

		if ( empty( $columns ) ) {
			return;
		}

		add_filter( 'jet-abaf/db/additional-db-columns', function ( $db_columns ) use ( $columns ) {
			if ( empty( $db_columns ) || ! is_array( $db_columns ) ) {
				$db_columns = [];
			}

			foreach ( $columns as $column ) {
				if ( is_array( $column ) && ! empty( $column['column'] ) ) {
					$db_columns[] = $column['column'];
				} else {
					$db_columns[] = $column;
				}
			}

			return $db_columns;
		} );

	}

	/**
	 * Sanitize_settings.
	 *
	 * Sanitize updated bookings settings.
	 *
	 * @since  2.8.0 Added new schedules settings. Updates structure.
	 * @access public
	 *
	 * @param string $setting Settings key name.
	 * @param mixed  $value   Settings value.
	 *
	 * @return array|false|mixed
	 */
	public function sanitize_setting( $setting, $value ) {

		switch ( $setting ) {
			case 'additional_columns':
				$value = array_values( $value );
				break;

			case 'days_off':
				$value = is_array( $value ) ? wp_unslash( $value ) : false;
				break;

			case 'is_set':
			case 'use_custom_labels':
			case 'hide_setup':
			case 'hide_columns_manager':
			case 'wc_integration':
			case 'wc_sync_orders':
			case 'ical_synch':
			case 'remove_temporary_bookings':
			case 'booking_cancellation':
			case 'weekly_bookings':
			case 'allow_checkout_only':
			case 'one_day_bookings':
			case 'month_select':
			case 'year_select':
			case 'show_calendar_price':
			case 'disable_weekday_1':
			case 'check_in_weekday_1':
			case 'check_out_weekday_1':
			case 'disable_weekday_2':
			case 'check_in_weekday_2':
			case 'check_out_weekday_2':
			case 'disable_weekday_3':
			case 'check_in_weekday_3':
			case 'check_out_weekday_3':
			case 'disable_weekday_4':
			case 'check_in_weekday_4':
			case 'check_out_weekday_4':
			case 'disable_weekday_5':
			case 'check_in_weekday_5':
			case 'check_out_weekday_5':
			case 'disable_weekend_1':
			case 'check_in_weekend_1':
			case 'check_out_weekend_1':
			case 'disable_weekend_2':
			case 'check_in_weekend_2':
			case 'check_out_weekend_2':
				$value = filter_var( $value, FILTER_VALIDATE_BOOLEAN );
				break;

			case 'cancellation_limit':
			case 'modification_limit':
				if ( 0 >= $value ) {
					$value = 1;
				}

				break;

			default:
				$value = wp_unslash( $value );
				break;
		}

		return $value;
	}

	/**
	 * Passe settings.
	 *
	 * Processes settings before localization.
	 *
	 * @since  2.4.7
	 * @access public
	 *
	 * @param array $settings Plugin settings list.
	 *
	 * @return mixed
	 */
	public function passe_settings( $settings ) {

		if ( ! empty( $settings ) && ! empty( $settings['days_off'] ) ) {
			$new_days_off = [];

			foreach ( $settings['days_off'] as $value ) {
				if ( ! isset( $value["date"] ) ) {
					$new_days_off[] = $value;
					continue;
				}

				$start          = $value["date"];
				$startTimeStamp = strtotime( $start );

				$new_days_off[] = [
					'start'          => $start,
					'startTimeStamp' => $startTimeStamp,
					'end'            => $start,
					'endTimeStamp'   => $startTimeStamp,
					'name'           => $value["name"],
					'type'           => 'days_off',
				];
			}

			$settings['days_off'] = $new_days_off;
		}

		return $settings;

	}

	/**
	 * Get labels.
	 *
	 * Return all available labels list.
	 *
	 * @access public
	 *
	 * @return mixed
	 */
	public function get_labels( $key = null ) {

		if ( null === $this->labels ) {
			$this->labels = [
				'booked'          => $this->get( 'labels_booked' ),
				'only-checkout'   => $this->get( 'labels_only_checkout' ),
				'selected'        => $this->get( 'labels_selected' ),
				'nights'          => $this->get( 'labels_nights' ),
				'days'            => $this->get( 'labels_days' ),
				'apply'           => $this->get( 'labels_apply' ),
				'week-1'          => $this->get( 'labels_week_1' ),
				'week-2'          => $this->get( 'labels_week_2' ),
				'week-3'          => $this->get( 'labels_week_3' ),
				'week-4'          => $this->get( 'labels_week_4' ),
				'week-5'          => $this->get( 'labels_week_5' ),
				'week-6'          => $this->get( 'labels_week_6' ),
				'week-7'          => $this->get( 'labels_week_7' ),
				'month-name'      => $this->get_array_from_string( $this->get( 'labels_month_name' ) ),
				'past'            => $this->get( 'labels_past' ),
				'previous'        => $this->get( 'labels_previous' ),
				'prev-week'       => $this->get( 'labels_prev_week' ),
				'prev-month'      => $this->get( 'labels_prev_month' ),
				'prev-year'       => $this->get( 'labels_prev_year' ),
				'default-default' => $this->get( 'labels_default' ),
			];
		}

		if ( ! $key ) {
			return $this->labels;
		} else {
			return $this->labels[ $key ] ?? null;
		}

	}

	/**
	 * Parse array from strig
	 *
	 * @return [type] [description]
	 */
	public function get_array_from_string( $string ) {
		$string = str_replace( ', ', ',', $string );

		return explode( ',', $string );
	}

	/**
	 * Get all.
	 *
	 * Return all settings and setup settings cache.
	 *
	 * @since  3.0.0 Refactored.
	 * @access public
	 *
	 * @return array|mixed|null
	 */
	public function get_all() {

		if ( null === $this->settings ) {
			$this->settings = get_option( $this->key, [] );
			$this->settings = wp_parse_args( $this->settings, $this->defaults );
			$this->settings = $this->passe_settings( $this->settings );

			$this->settings['additional_columns'] = ! empty( $this->settings['additional_columns'] ) ? array_values( $this->settings['additional_columns'] ) : [];
		}

		return $this->settings;

	}

	/**
	 * Get.
	 *
	 * Returns setting by key.
	 *
	 * @since  2.0.0
	 * @since  3.0.0 Refactored.
	 * @access public
	 *
	 * @param string $setting Setting key.
	 *
	 * @return mixed
	 */
	public function get( $setting ) {

		$settings = $this->get_all();

		if ( isset( $settings[ $setting ] ) ) {
			$value = $settings[ $setting ];
		} else {
			$value = $this->defaults[ $setting ] ?? false;
		}

		return apply_filters( 'jet-booking/settings/get/' . $setting, $value );

	}

	/**
	 * Checkout only allowed.
	 *
	 * Returns status if the first day of the already booked period will be available for checkout.
	 *
	 * @since 2.2.5
	 * @since 3.5.1 Refactored. Options became local & global.
	 *
	 * @param int|string|null $post_id Booking instance ID.
	 *
	 * @return bool
	 */
	public function checkout_only_allowed( $post_id = null ) {
		$allow_checkout_only = $post_id ? $this->get_config_setting( $post_id, 'allow_checkout_only' ) : $this->get( 'allow_checkout_only' );

		return $this->is_per_nights_booking( $post_id ) && $allow_checkout_only;
	}

	/**
	 * Is per night bookings.
	 *
	 * Check if per nights booking mode enable.
	 *
	 * @since  2.8.0 Optimization.
	 * @since  3.5.1 Refactored. Options became local & global.
	 *
	 * @param int|string|null $post_id Booking instance ID.
	 *
	 * @return boolean
	 */
	public function is_per_nights_booking( $post_id = null ) {

		$period = $post_id ? $this->get_config_setting( $post_id, 'booking_period' ) : $this->get( 'booking_period' );

		if ( ! $period || 'per_nights' === $period ) {
			return true;
		}

		return false;

	}

	/**
	 * Is one day booking.
	 *
	 * Check if one day booking option available and enable.
	 *
	 * @since  2.5.2
	 * @since  2.6.3 Added booking instance item handling.
	 *
	 * @param string|number $id Booking instance item ID.
	 *
	 * @return bool
	 */
	public function is_one_day_bookings( $id ) {

		$check_in_days  = $this->get_days_by_rule( $id, 'check_in' );
		$check_out_days = $this->get_days_by_rule( $id, 'check_out' );

		if ( ! empty( $check_in_days ) && 7 > count( $check_in_days ) || ! empty( $check_out_days ) && 7 > count( $check_out_days ) ) {
			return false;
		}

		return ( ! $this->is_per_nights_booking( $id ) && $this->get_config_setting( $id, 'one_day_bookings' ) );

	}

	/**
	 * Is weekly bookings.
	 *
	 * Check if weekly bookings option available and enable.
	 *
	 * @since  3.0.0
	 *
	 * @param string|number $id Booking instance item ID.
	 *
	 * @return false|mixed
	 */
	public function is_weekly_bookings( $id ) {

		$check_in_days  = $this->get_days_by_rule( $id, 'check_in' );
		$check_out_days = $this->get_days_by_rule( $id, 'check_out' );

		if ( ! empty( $check_in_days ) && 7 > count( $check_in_days ) || ! empty( $check_out_days ) && 7 > count( $check_out_days ) ) {
			return false;
		}

		return $this->get_config_setting( $id, 'weekly_bookings' );

	}

	/**
	 * Get config option.
	 *
	 * Returns option for date range picker configuration.
	 *
	 * @since  2.6.0
	 *
	 * @param integer $post_id Post ID.
	 * @param string  $key     Options name key.
	 *
	 * @return mixed
	 */
	public function get_config_setting( $post_id, $key ) {

		$value = $this->get( $key );

		if ( ! $this->config_settings ) {
			$this->config_settings = get_post_meta( $post_id, 'jet_abaf_configuration', true );
		}

		if ( isset( $this->config_settings['config'] ) && $this->config_settings['config']['enable_config'] ) {
			$value = $this->config_settings['config'][ $key ] ?? $value;
		}

		return $value;

	}

	/**
	 * Schedule settings.
	 *
	 * Return custom schedule settings list for specific post or global.
	 *
	 * @since  2.5.0
	 * @since  2.8.0 Code refactor.
	 *
	 * @param null $post_id       Booking post type ID.
	 * @param null $default_value Default schedule value.
	 * @param null $meta_key      Post type meta value key.
	 *
	 * @return mixed|void
	 */
	public function get_schedule_settings( $post_id = null, $default_value = null, $meta_key = null ) {

		$schedule         = null;
		$post_schedule    = get_post_meta( $post_id, 'jet_abaf_custom_schedule', true );
		$general_schedule = $this->get( $meta_key ) ?? $default_value;

		if ( ! isset( $post_schedule['custom_schedule'] ) || ! $post_schedule['custom_schedule']['use_custom_schedule'] ) {
			$schedule = $general_schedule;
		} elseif ( isset( $post_schedule['custom_schedule'][ $meta_key ] ) ) {
			$schedule = $post_schedule['custom_schedule'][ $meta_key ] ?? $general_schedule;
		}

		return apply_filters( 'jet-booking/settings/custom-schedule', $schedule, $meta_key, $default_value, $post_id );

	}

	/**
	 * Get days by rule.
	 *
	 * Returns list of days by passed rule.
	 *
	 * @since  2.8.0
	 *
	 * @param string|number $post_id Booking post type id.
	 * @param string        $type    Rule type.
	 *
	 * @return array
	 */
	public function get_days_by_rule( $post_id = null, $type = 'disable' ) {

		if ( ! $post_id ) {
			return [];
		}

		$days          = [];
		$post_schedule = get_post_meta( $post_id, 'jet_abaf_custom_schedule', true );

		$rules = [
			$type . '_weekend_2',
			$type . '_weekday_1',
			$type . '_weekday_2',
			$type . '_weekday_3',
			$type . '_weekday_4',
			$type . '_weekday_5',
			$type . '_weekend_1',
		];

		if ( ! isset( $post_schedule['custom_schedule'] ) || ! $post_schedule['custom_schedule']['use_custom_schedule'] ) {
			foreach ( $rules as $key => $value ) {
				if ( $this->get( $value ) ) {
					$days[] = $key;
				}
			}
		} else {
			foreach ( $rules as $key => $value ) {
				if ( isset( $post_schedule['custom_schedule'][ $value ] ) && filter_var( $post_schedule['custom_schedule'][ $value ], FILTER_VALIDATE_BOOLEAN ) ) {
					$days[] = $key;
				}
			}
		}

		if ( 'disable' === $type ) {
			return $days;
		}

		$disabled_days = $this->get_days_by_rule( $post_id );

		if ( empty( $disabled_days ) ) {
			return $days;
		}

		foreach ( $disabled_days as $day ) {
			if ( ( $key = array_search( $day, $days ) ) !== false ) {
				unset( $days[ $key ] );
			}
		}

		return array_values( $days );

	}

	/**
	 * Booking days off.
	 *
	 * Returns booking days off - official days off.
	 *
	 * @since  2.5.0
	 *
	 * @param int $post_id Booking post type ID.
	 *
	 * @return array List of days off.
	 * @throws \Exception
	 */
	public function get_booking_days_off( $post_id ) {

		$days_off = $this->get_schedule_settings( $post_id, null, 'days_off' );
		$dates    = [];

		if ( empty( $days_off ) ) {
			return $dates;
		}

		foreach ( $days_off as $day ) {
			$from = new \DateTime( date( 'F d, Y', $day['startTimeStamp'] ) );
			$to   = new \DateTime( date( 'F d, Y', $day['endTimeStamp'] ) );

			if ( $to->format( 'Y-m-d' ) === $from->format( 'Y-m-d' ) ) {
				$dates[] = $from->format( 'Y-m-d' );
			} else {
				$to     = $to->modify( '+1 day' );
				$period = new \DatePeriod( $from, new \DateInterval( 'P1D' ), $to );

				foreach ( $period as $key => $value ) {
					$dates[] = $value->format( 'Y-m-d' );
				}
			}
		}

		return $dates;

	}

	/**
	 * Off dates.
	 *
	 * Returns off dates - official days off and booked dates.
	 *
	 * @since  2.5.0
	 * @since  2.5.5 Added additional `$post_id` handling.
	 * @access public
	 *
	 * @param int $post_id Booking post type ID.
	 *
	 * @return array|mixed
	 * @throws \Exception
	 */
	public function get_off_dates( $post_id ) {

		$post_id = jet_abaf()->db->get_initial_booking_item_id( $post_id );

		if ( isset( $this->booked_dates[ $post_id ] ) ) {
			return $this->booked_dates[ $post_id ];
		}

		$booked_dates = jet_abaf()->tools->get_booked_dates( $post_id );
		$days_off     = jet_abaf()->settings->get_booking_days_off( $post_id );

		if ( empty( $booked_dates ) && empty( $days_off ) ) {
			$this->booked_dates[ $post_id ] = [];

			return [];
		}

		$dates = array_merge( $booked_dates, $days_off );

		$this->booked_dates[ $post_id ] = $dates;

		return $dates;

	}

	/**
	 * Get end date.
	 *
	 * Returns string defines the latest date which is allowed for the user to pick compare to current date.
	 *
	 * @since 3.4.0
	 * @since 3.4.1 Added local configuration option handle.
	 *
	 * @param integer|string $post_id Post ID.
	 *
	 * @return false|int
	 */
	public function get_end_date( $post_id ) {

		if ( 'none' === $this->get_config_setting( $post_id, 'end_date_type' ) ) {
			return false;
		}

		$range = $this->get_config_setting( $post_id, 'end_date_range_number' );

		if ( ! $range ) {
			return false;
		}

		$unit  = $range > 1 ? $this->get_config_setting( $post_id, 'end_date_range_unit' ) . 's' : $this->get_config_setting( $post_id, 'end_date_range_unit' );
		$time  = sprintf( '%s +%d %s', current_time( 'd F Y H:i:s' ), $range, $unit );

		return strtotime( $time );

	}

	/**
	 * Update.
	 *
	 * Update setting in cache and database.
	 *
	 * @since  3.0.0 Added `'jet-booking/settings/before-update'` action hook.
	 * @access public
	 *
	 * @param null $setting Setting key name.
	 * @param null $value   Setting value.
	 * @param bool $write   DB update status.
	 *
	 * @return void
	 */
	public function update( $setting = null, $value = null, $write = true ) {

		$this->get_all();

		/**
		 * Modify options before write into DB.
		 */
		do_action( 'jet-booking/settings/before-update', $this->settings, $setting, $value );

		$this->settings[ $setting ] = $value;

		if ( $write ) {
			$this->write();
		}

	}

	/**
	 * Clear.
	 *
	 * Clear settings data.
	 *
	 * @since  2.0.0
	 * @since  2.8.0 Added global settings variable reset.
	 */
	public function clear() {
		delete_option( $this->key );
		$this->settings = null;
	}

	/**
	 * Write.
	 *
	 * Write settings cache.
	 *
	 * @since 2.0.0
	 */
	public function write() {

		/**
		 * Modify options before write into DB
		 */
		do_action( 'jet-abaf/settings/before-write', $this );

		update_option( $this->key, $this->settings, false );
	}

	/**
	 * Setting registered.
	 *
	 * Check if passed settings is registered in defaults.
	 *
	 * @since 2.0.0
	 *
	 * @param string $setting Setting key name.
	 *
	 * @return bool
	 */
	public function setting_registered( $setting ) {
		return ( $setting && isset( $this->defaults[ $setting ] ) );
	}

}