287 lines
7.9 KiB
PHP
287 lines
7.9 KiB
PHP
<?php
|
|
/**
|
|
* Simply Schedule Appointments Availability Detective Case.
|
|
*
|
|
* @since 4.3.8-beta7
|
|
* @package Simply_Schedule_Appointments
|
|
*/
|
|
use League\Period\Period;
|
|
|
|
/**
|
|
* Simply Schedule Appointments Availability Detective Case.
|
|
*
|
|
* @since 4.3.8-beta7
|
|
*/
|
|
class SSA_Availability_Detective_Case {
|
|
/**
|
|
* Parent plugin class.
|
|
*
|
|
* @since 4.3.8-beta7
|
|
*
|
|
* @var SSA_Appointment_Type_Object
|
|
*/
|
|
protected $appointment_type;
|
|
protected $period;
|
|
protected $appointment;
|
|
|
|
public $all_suspects = array(
|
|
'appointment_type.min_booking_notice',
|
|
'appointment_type.max_booking_notice',
|
|
'appointment_type.availability_window',
|
|
'appointment_type.max_per_day',
|
|
'appointment_type.separate_appointment_type_availability',
|
|
|
|
// 'appointment_type.booking_window', // doesn't make sense, this is all frontend
|
|
// 'appointment_type.buffers', // TODO
|
|
// 'appointment_type.capacity', // TODO maybe
|
|
|
|
'appointment_type.appointments',
|
|
'appointment_type.appointments.booked',
|
|
'appointment_type.appointments.pending_form',
|
|
'appointment_type.appointments.pending_payment',
|
|
|
|
'staff',
|
|
// 'staff.appointment_type.buffers',
|
|
// 'staff.appointment_type.capacity',
|
|
|
|
'blackout_dates',
|
|
// 'blackout_dates.staff',
|
|
// 'blackout_dates.staff.123',
|
|
// 'blackout_dates.staff.456',
|
|
|
|
'google_calendar',
|
|
// 'google_calendar.staff',
|
|
// 'google_calendar.staff.123',
|
|
// 'google_calendar.staff.456',
|
|
|
|
'resources',
|
|
);
|
|
|
|
public $required = array(
|
|
'appointment_type'
|
|
);
|
|
public $already_investigated = array();
|
|
public $sequestered = array();
|
|
public $suspects = array(
|
|
'blackout_dates',
|
|
'google_calendar',
|
|
'staff',
|
|
'resources'
|
|
);
|
|
public $prime_suspects = array();
|
|
public $interrogation_room = array();
|
|
public $cleared = array();
|
|
public $culprits = array();
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @since 4.3.8-beta7
|
|
*
|
|
* @param Simply_Schedule_Appointments $plugin Main plugin object.
|
|
*/
|
|
public function __construct(
|
|
SSA_Appointment_Type_Object $appointment_type,
|
|
Period $period,
|
|
SSA_Appointment_Object $appointment
|
|
) {
|
|
$this->appointment_type = $appointment_type;
|
|
$this->period = $period;
|
|
$this->appointment = $appointment;
|
|
}
|
|
|
|
private function clone_instance() {
|
|
$clone = clone $this;
|
|
|
|
return $clone;
|
|
}
|
|
|
|
private function subinvestigation() {
|
|
$case = $this->clone_instance();
|
|
$case->required = array();
|
|
$case->sequestered = array();
|
|
$case->suspects = array();
|
|
$case->prime_suspects = array();
|
|
$case->interrogation_room = array();
|
|
$case->cleared = array();
|
|
$case->culprits = array();
|
|
|
|
return $case;
|
|
}
|
|
|
|
public function prepare_interrogation_room() {
|
|
$case = $this->clone_instance();
|
|
|
|
if ( ! empty( $case->required ) ) {
|
|
if ( empty( $case->cleared ) && empty( $case->culprits ) ) {
|
|
// we haven't tested the required suspects yet
|
|
$case->interrogation_room = $case->required;
|
|
return $case;
|
|
}
|
|
}
|
|
|
|
$culprits_that_are_required = array_intersect( $case->culprits, $case->required );
|
|
if ( ! empty( $culprits_that_are_required ) ) {
|
|
// if required suspects are guilty then don't continue investigation
|
|
$case->interrogation_room = array();
|
|
return $case;
|
|
}
|
|
|
|
if ( empty( $case->suspects ) ) {
|
|
// nobody left to interrogate
|
|
$case->interrogation_room = array();
|
|
return $case;
|
|
}
|
|
|
|
$next_suspects = array( array_shift( $case->suspects ) );
|
|
// solo interrogation
|
|
$case->interrogation_room = array_merge( $case->required, $next_suspects );
|
|
// $case->sequestered = array_diff( $case->suspects, $case->required, $case->cleared );
|
|
// group interrogation
|
|
// TODO: test suspects with all previously cleared modules
|
|
// $case->interrogation_room = array_merge( $case->required, $case->cleared, $next_suspects );
|
|
|
|
return $case;
|
|
}
|
|
|
|
public function clear_suspects( $suspects ) {
|
|
if ( ! is_array( $suspects ) ) {
|
|
$suspects = array( $suspects );
|
|
}
|
|
$case = $this->clone_instance();
|
|
$case->cleared = array_unique( array_merge( $case->cleared, $suspects ) );
|
|
$case->suspects = array_diff( $case->suspects, $case->cleared );
|
|
|
|
return $case;
|
|
}
|
|
|
|
public function get_suspect_group( $group_prefix ) {
|
|
$suspect_group = array_filter( $this->all_suspects, function( $suspect ) use ( $group_prefix ) {
|
|
if ( strpos( $suspect, $group_prefix.'.' ) === 0 ) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
} );
|
|
|
|
return $suspect_group;
|
|
}
|
|
|
|
public function get_uncleared_suspects_in_interrogation_room() {
|
|
$uncleared_suspects = array_diff( $this->interrogation_room, $this->cleared, $this->culprits );
|
|
|
|
return $uncleared_suspects;
|
|
}
|
|
|
|
public function clear_suspect_group( $group_prefix ) {
|
|
$case = $this->clone_instance();
|
|
|
|
$suspect_group = $this->get_suspect_group( $group_prefix );
|
|
|
|
$case->cleared = array_merge( $case->cleared, array( $group_prefix ), $suspect_group );
|
|
$case->suspects = array_diff( $case->suspects, array( $group_prefix ), $suspect_group );
|
|
|
|
return $case;
|
|
}
|
|
|
|
public function mark_culprits( $suspects ) {
|
|
if ( ! is_array( $suspects ) ) {
|
|
$suspects = array( $suspects );
|
|
}
|
|
$case = $this->clone_instance();
|
|
$case->culprits = array_unique( array_merge( $case->culprits, $suspects ) );
|
|
$case->suspects = array_diff( $case->suspects, $suspects );
|
|
|
|
return $case;
|
|
}
|
|
|
|
public function investigate() {
|
|
$case = $this->prepare_interrogation_room();
|
|
if ( empty( $case->interrogation_room ) ) {
|
|
return $case;
|
|
}
|
|
|
|
$query_args = $case->get_interrogation_room_query_args();
|
|
$detecting_appointments = isset($query_args['appointment_type.appointments']) &&
|
|
($query_args['appointment_type.appointments.pending_payment'] ||
|
|
$query_args['appointment_type.appointments.pending_form'] ||
|
|
$query_args['appointment_type.appointments.booked']);
|
|
|
|
$interrogation = new SSA_Availability_Query(
|
|
$case->appointment_type,
|
|
$case->period,
|
|
$query_args
|
|
);
|
|
|
|
if ( $interrogation->is_prospective_appointment_bookable( $case->appointment ) ) {
|
|
$case = $detecting_appointments? $case->declare_guilty():$case->declare_innocent();
|
|
} else {
|
|
$new_suspects = $case->get_uncleared_suspects_in_interrogation_room();
|
|
$case = $detecting_appointments? $case->declare_innocent():$case->declare_guilty();
|
|
foreach ($new_suspects as $group) {
|
|
if ( in_array( $group, $case->already_investigated ) ) {
|
|
continue;
|
|
}
|
|
$subgroup = $case->get_suspect_group( $group );
|
|
if ( empty( $subgroup ) ) {
|
|
continue;
|
|
}
|
|
|
|
$closer_look = $case->subinvestigation();
|
|
$closer_look->already_investigated = array( $group );
|
|
$closer_look->required = array( $group );
|
|
$closer_look->sequestered = array_merge( $case->cleared, $case->suspects, $case->culprits );
|
|
$closer_look->suspects = $subgroup;
|
|
$closer_look = $closer_look->investigate();
|
|
if ( ! empty( $closer_look->culprits ) ) {
|
|
$case = $case->mark_culprits( $closer_look->culprits );
|
|
}
|
|
}
|
|
}
|
|
|
|
$case = $case->investigate();
|
|
return $case;
|
|
}
|
|
|
|
public function declare_innocent() {
|
|
$case = $this->clone_instance();
|
|
$new_suspects = $this->get_uncleared_suspects_in_interrogation_room();
|
|
$case = $case->clear_suspects( $new_suspects );
|
|
// foreach ($new_suspects as $new_suspect) {
|
|
// $case = $case->clear_suspect_group( $new_suspect );
|
|
// }
|
|
|
|
return $case;
|
|
}
|
|
|
|
public function declare_guilty() {
|
|
$case = $this->clone_instance();
|
|
$new_suspects = $this->get_uncleared_suspects_in_interrogation_room();
|
|
$case = $case->mark_culprits( $new_suspects );
|
|
|
|
return $case;
|
|
}
|
|
|
|
public function get_interrogation_room_query_args() {
|
|
$cache_args = array(
|
|
'cache_level_read' => false,
|
|
'cache_level_write' => false,
|
|
);
|
|
$default_false = array_fill_keys( array_merge( $this->suspects, $this->cleared, $this->culprits ), false );
|
|
$sequestered_false = array_fill_keys( $this->sequestered, false );
|
|
$interrogating_true = array_fill_keys( $this->interrogation_room, true );
|
|
|
|
$query_args = array_merge( $default_false, $sequestered_false, $interrogating_true, $cache_args );
|
|
|
|
return $query_args;
|
|
}
|
|
|
|
public function investigate_methodically() {
|
|
|
|
}
|
|
|
|
public function investigate_randomly() {
|
|
|
|
}
|
|
}
|