Advertisement
Guest User

Untitled

a guest
Aug 11th, 2016
281
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 17.32 KB | None | 0 0
  1. <?php
  2.  
  3. /**
  4. * Main model class for all bookings, this handles all the data
  5. */
  6. class WC_Booking {
  7.  
  8.     /** @public int */
  9.     public $id;
  10.  
  11.     /** @public string */
  12.     public $booking_date;
  13.  
  14.     /** @public string */
  15.     public $start;
  16.  
  17.     /** @public string */
  18.     public $end;
  19.  
  20.     /** @public bool */
  21.     public $all_day;
  22.  
  23.     /** @public string */
  24.     public $modified_date;
  25.  
  26.     /** @public object */
  27.     public $post;
  28.  
  29.     /** @public int */
  30.     public $product_id;
  31.  
  32.     /** @public object */
  33.     public $product;
  34.  
  35.     /** @public int */
  36.     public $order_id;
  37.  
  38.     /** @public object */
  39.     public $order;
  40.  
  41.     /** @public int */
  42.     public $customer_id;
  43.  
  44.     /** @public string */
  45.     public $status;
  46.  
  47.     /** @public array - contains all post meta values for this booking */
  48.     public $custom_fields;
  49.  
  50.     /** @public bool */
  51.     public $populated;
  52.  
  53.     /** @private array - used to temporarily hold order data for new bookings */
  54.     private $order_data;
  55.  
  56.     /**
  57.      * Constructor, possibly sets up with post or id belonging to existing booking
  58.      * or supplied with an array to construct a new booking
  59.      * @param int/array/obj $booking_data
  60.      */
  61.     public function __construct( $booking_data = false ) {
  62.         $populated = false;
  63.  
  64.         if ( is_array( $booking_data ) ) {
  65.             $this->order_data = $booking_data;
  66.             $populated = false;
  67.         } else if ( is_int( intval( $booking_data ) ) && 0 < $booking_data ) {
  68.             $populated = $this->populate_data( $booking_data );
  69.         } else if ( is_object( $booking_data ) && isset( $booking_data->ID ) ) {
  70.             $this->post = $booking_data;
  71.             $populated = $this->populate_data( $booking_data->ID );
  72.         }
  73.  
  74.         $this->populated = $populated;
  75.     }
  76.  
  77.     /**
  78.      * Actual create for the new booking belonging to an order
  79.      * @param string Status for new order
  80.      */
  81.     public function create( $status = 'unpaid' ) {
  82.         $this->new_booking( $status, $this->order_data );
  83.         $this->schedule_events();
  84.     }
  85.  
  86.     /**
  87.      * Schedule events for this booking
  88.      */
  89.     public function schedule_events() {
  90.         switch ( get_post_status( $this->id ) ) {
  91.             case "paid" :
  92.                 if ( $this->start && $this->get_order() ) {
  93.                     $order_status = $this->get_order()->get_status();
  94.  
  95.                     if ( ! in_array( $order_status, array( 'cancelled', 'refunded', 'pending', 'on-hold' ) ) ) {
  96.                         wp_schedule_single_event( strtotime( '-' . absint( apply_filters( 'woocommerce_bookings_remind_before_days', 1 ) ) . ' day', $this->start ), 'wc-booking-reminder', array( $this->id ) );
  97.                     }
  98.                 }
  99.                 if ( $this->end ) {
  100.                     wp_schedule_single_event( $this->end, 'wc-booking-complete', array( $this->id ) );
  101.                 }
  102.             break;
  103.             default :
  104.                 wp_clear_scheduled_hook( 'wc-booking-reminder', array( $this->id ) );
  105.                 wp_clear_scheduled_hook( 'wc-booking-complete', array( $this->id ) );
  106.             break;
  107.         }
  108.     }
  109.  
  110.     /**
  111.      * Makes the new booking belonging to an order
  112.      * @param string $status The status for this new booking
  113.      * @param array $order_data Array with all the new order data
  114.      */
  115.     private function new_booking( $status, $order_data ) {
  116.         global $wpdb;
  117.  
  118.         $order_data = wp_parse_args( $order_data, array(
  119.             'user_id'           => 0,
  120.             'resource_id'       => '',
  121.             'product_id'        => '',
  122.             'order_item_id'     => '',
  123.             'persons'           => array(),
  124.             'cost'              => '',
  125.             'start_date'        => '',
  126.             'end_date'          => '',
  127.             'all_day'           => 0,
  128.             'parent_id'         => 0,
  129.         ) );
  130.  
  131.         // Get parent data
  132.         if ( $order_data['parent_id'] ) {
  133.             if ( ! $order_data['order_item_id'] ) {
  134.                 $order_data['order_item_id'] = get_post_meta( $order_data['parent_id'], '_booking_order_item_id', true );
  135.             }
  136.  
  137.             if ( ! $order_data['user_id'] ) {
  138.                 $order_data['user_id'] = get_post_meta( $order_data['parent_id'], '_booking_customer_id', true );
  139.             }
  140.         }
  141.  
  142.         // Get order ID from order item
  143.         if ( $order_data['order_item_id'] ) {
  144.             $order_id = $wpdb->get_var( $wpdb->prepare( "SELECT order_id FROM {$wpdb->prefix}woocommerce_order_items WHERE order_item_id = %d", $order_data['order_item_id'] ) );
  145.         } else {
  146.             $order_id = 0;
  147.         }
  148.  
  149.         $booking_data = array(
  150.             'post_type'   => 'wc_booking',
  151.             'post_title'  => sprintf( __( 'Booking &ndash; %s', 'woocommerce-bookings' ), strftime( _x( '%b %d, %Y @ %I:%M %p', 'Booking date parsed by strftime', 'woocommerce-bookings' ) ) ),
  152.             'post_status' => $status,
  153.             'ping_status' => 'closed',
  154.             'post_parent' => $order_id
  155.         );
  156.  
  157.         $this->id = wp_insert_post( $booking_data );
  158.  
  159.         // Setup the required data for the current user
  160.         if ( ! $order_data['user_id'] ) {
  161.             if ( is_user_logged_in() ) {
  162.                 $order_data['user_id'] = get_current_user_id();
  163.             } else {
  164.                 $order_data['user_id'] = 0;
  165.             }
  166.         }
  167.  
  168.         // Convert booking start and end to requried format
  169.         if ( is_numeric( $order_data['start_date'] ) ) {
  170.             // Convert timestamp
  171.             $order_data['start_date'] = date( 'YmdHis', $order_data['start_date'] );
  172.             $order_data['end_date']   = date( 'YmdHis', $order_data['end_date'] );
  173.         } else {
  174.             $order_data['start_date'] = date( 'YmdHis', strtotime( $order_data['start_date'] ) );
  175.             $order_data['end_date']   = date( 'YmdHis', strtotime( $order_data['end_date'] ) );
  176.         }
  177.  
  178.         $meta_args = array(
  179.             '_booking_order_item_id' => $order_data['order_item_id'],
  180.             '_booking_product_id'    => $order_data['product_id'],
  181.             '_booking_resource_id'   => $order_data['resource_id'],
  182.             '_booking_persons'       => $order_data['persons'],
  183.             '_booking_cost'          => $order_data['cost'],
  184.             '_booking_start'         => $order_data['start_date'],
  185.             '_booking_end'           => $order_data['end_date'],
  186.             '_booking_all_day'       => intval( $order_data['all_day'] ),
  187.             '_booking_parent_id'     => $order_data['parent_id'],
  188.             '_booking_customer_id'   => $order_data['user_id'],
  189.         );
  190.  
  191.         foreach ( $meta_args as $key => $value ) {
  192.             update_post_meta( $this->id, $key, $value );
  193.         }
  194.  
  195.         WC_Cache_Helper::get_transient_version( 'bookings', true );
  196.  
  197.         do_action( 'woocommerce_new_booking', $this->id );
  198.     }
  199.  
  200.     /**
  201.      * Assign this booking to an order and order item by ID
  202.      * @param int $order_id
  203.      * @param int $order_item_id
  204.      */
  205.     public function set_order_id( $order_id, $order_item_id ) {
  206.         $this->order_id = $order_id;
  207.         wp_update_post( array( 'ID' => $this->id, 'post_parent' => $this->order_id ) );
  208.         update_post_meta( $this->id, '_booking_order_item_id', $order_item_id );
  209.     }
  210.  
  211.     /**
  212.      * Populate the data with the id of the booking provided
  213.      * Will query for the post belonging to this booking and store it
  214.      * @param int $booking_id
  215.      */
  216.     public function populate_data( $booking_id ) {
  217.         if ( ! isset( $this->post ) ) {
  218.             $post = get_post( $booking_id );
  219.         }
  220.  
  221.         if ( is_object( $post ) ) {
  222.             // We have the post object belonging to this booking, now let's populate
  223.             $this->id            = $post->ID;
  224.             $this->booking_date  = $post->post_date;
  225.             $this->modified_date = $post->post_modified;
  226.             $this->customer_id   = $post->post_author;
  227.             $this->custom_fields = get_post_meta( $this->id );
  228.             $this->status        = $post->post_status;
  229.             $this->order_id      = $post->post_parent;
  230.  
  231.             // Define the data we're going to load: Key => Default value
  232.             $load_data = array(
  233.                 'product_id'  => '',
  234.                 'resource_id' => '',
  235.                 'persons'     => array(),
  236.                 'cost'        => '',
  237.                 'start'       => '',
  238.                 'customer_id' => '',
  239.                 'end'         => '',
  240.                 'all_day'     => 0,
  241.                 'parent_id'   => 0,
  242.             );
  243.  
  244.             // Load the data from the custom fields (with prefix for this plugin)
  245.             $meta_prefix = '_booking_';
  246.  
  247.             foreach ( $load_data as $key => $default ) {
  248.                 if ( isset( $this->custom_fields[ $meta_prefix . $key ][0] ) && $this->custom_fields[ $meta_prefix . $key ][0] !== '' ) {
  249.                     $this->$key = maybe_unserialize( $this->custom_fields[ $meta_prefix . $key ][0] );
  250.                 } else {
  251.                     $this->$key = $default;
  252.                 }
  253.             }
  254.  
  255.             // Start and end date converted to timestamp
  256.             $this->start = strtotime( $this->start );
  257.             $this->end   = strtotime( $this->end );
  258.  
  259.             // Save the post object itself for future reference
  260.             $this->post = $post;
  261.             return true;
  262.         }
  263.  
  264.         return false;
  265.     }
  266.  
  267.     /**
  268.      * Will change the booking status once the order is paid for
  269.      * @return bool
  270.      */
  271.     public function paid() {
  272.         $current_status = $this->status;
  273.         $event          = wp_get_schedule( 'wc-booking-reminder', array( $this->id ) );
  274.  
  275.         if ( $this->populated && in_array( $current_status, array( 'unpaid', 'confirmed' ) ) ) {
  276.             $this->update_status( 'paid' );
  277.  
  278.             if ( ! empty( $event ) ) {
  279.                 $this->schedule_events();
  280.             }
  281.  
  282.             return true;
  283.         }
  284.  
  285.         return false;
  286.     }
  287.  
  288.     /**
  289.      * Set the new status for this booking
  290.      * @param string $status
  291.      * @return bool
  292.      */
  293.     public function update_status( $status ) {
  294.         $current_status   = $this->get_status( true );
  295.         $allowed_statuses = array( 'unpaid', 'pending-confirmation', 'confirmed', 'paid', 'cancelled', 'complete', 'in-cart', 'was-in-cart' );
  296.  
  297.         if ( $this->populated ) {
  298.             if ( in_array( $status, $allowed_statuses ) ) {
  299.                 wp_update_post( array( 'ID' => $this->id, 'post_status' => $status ) );
  300.  
  301.                 // Reschedule cron
  302.                 $this->schedule_events();
  303.  
  304.                 // Trigger actions
  305.                 do_action( 'woocommerce_booking_' . $current_status . '_to_' . $status, $this->id );
  306.                 do_action( 'woocommerce_booking_' . $status, $this->id );
  307.  
  308.                 // Note in the order
  309.                 if ( $order = $this->get_order() ) {
  310.                     $order->add_order_note( sprintf( __( 'Booking #%d status changed from "%s" to "%s', 'woocommerce-bookings' ), $this->id, $current_status, $status ) );
  311.                 }
  312.  
  313.                 return true;
  314.             }
  315.         }
  316.  
  317.         return false;
  318.     }
  319.  
  320.     /**
  321.      * Checks the booking status against a passed in status.
  322.      *
  323.      * @return bool
  324.      */
  325.     public function has_status( $status ) {
  326.         return apply_filters( 'woocommerce_booking_has_status', ( is_array( $status ) && in_array( $this->get_status(), $status ) ) || $this->get_status() === $status ? true : false, $this, $status );
  327.     }
  328.  
  329.     /**
  330.      * Returns the status of this booking
  331.      * @param Bool to ask for pretty status name (if false)
  332.      * @return String of the booking status
  333.      */
  334.     public function get_status( $raw = true ) {
  335.         if ( $this->populated ) {
  336.             if ( $raw ) {
  337.                 return $this->status;
  338.             } else {
  339.                 $status_object = get_post_status_object( $this->status );
  340.                 return $status_object->label;
  341.             }
  342.         }
  343.  
  344.         return false;
  345.     }
  346.  
  347.     /**
  348.      * Returns the id of this booking
  349.      * @return Id of the booking or false if booking is not populated
  350.      */
  351.     public function get_id() {
  352.         if ( $this->populated ) {
  353.             return $this->id;
  354.         }
  355.  
  356.         return false;
  357.     }
  358.  
  359.     /**
  360.      * Get the product ID for the booking
  361.      * @return int or false if booking is not populated
  362.      */
  363.     public function get_product_id() {
  364.         if ( $this->populated ) {
  365.             return $this->product_id;
  366.         }
  367.  
  368.         return false;
  369.     }
  370.  
  371.     /**
  372.      * Returns the object of the order corresponding to this booking
  373.      * @return Product object or false if booking is not populated
  374.      */
  375.     public function get_product() {
  376.         if ( empty( $this->product ) ) {
  377.             if ( $this->populated && $this->product_id ) {
  378.                 $this->product = get_product( $this->product_id );
  379.             } else {
  380.                 return false;
  381.             }
  382.         }
  383.  
  384.         return $this->product;
  385.     }
  386.  
  387.     /**
  388.      * Returns the object of the order corresponding to this booking
  389.      * @return Order object or false if booking is not populated
  390.      */
  391.     public function get_order() {
  392.         if ( empty( $this->order ) ) {
  393.             if ( $this->populated && ! empty( $this->order_id ) && 'shop_order' === get_post_type( $this->order_id ) ) {
  394.                 $this->order = wc_get_order( $this->order_id );
  395.             } else {
  396.                 return false;
  397.             }
  398.         }
  399.  
  400.         return $this->order;
  401.     }
  402.  
  403.     /**
  404.      * Returns the cancel URL for a booking
  405.      *
  406.      * @param string $redirect
  407.      * @return string
  408.      */
  409.     public function get_cancel_url( $redirect = '' ) {
  410.         $cancel_page = get_permalink( wc_get_page_id( 'myaccount' ) );
  411.  
  412.         if ( ! $cancel_page ) {
  413.             $cancel_page = home_url();
  414.         }
  415.  
  416.         return apply_filters( 'bookings_cancel_booking_url', wp_nonce_url( add_query_arg( array( 'cancel_booking' => 'true', 'booking_id' => $this->id, 'redirect' => $redirect ), $cancel_page ), 'woocommerce-bookings-cancel_booking' ) );
  417.     }
  418.  
  419.     /**
  420.      * Return if all day event
  421.      * @return boolean
  422.      */
  423.     public function is_all_day() {
  424.         if ( $this->populated ) {
  425.             if ( $this->all_day ) {
  426.                 return true;
  427.             } else {
  428.                 return false;
  429.             }
  430.         }
  431.         return false;
  432.     }
  433.  
  434.     /**
  435.      * See if this booking is within a block
  436.      * @return boolean
  437.      */
  438.     public function is_within_block( $block_start, $block_end ) {
  439.         if ( $this->populated ) {
  440.             if ( $this->start >= $block_end ) {
  441.                 return false; // Booking starts after block ends
  442.             }
  443.  
  444.             if ( $this->end <= $block_start ) {
  445.                 return false; // Booking ends before block starts
  446.             }
  447.  
  448.             return true;
  449.         }
  450.         return false;
  451.     }
  452.  
  453.     /**
  454.      * See if this booking is booked on said date
  455.      * @return boolean
  456.      */
  457.     public function is_booked_on_day( $block_start, $block_end ) {
  458.         if ( $this->populated ) {
  459.             $loop_date        = $this->start;
  460.             $multiday_booking = date( 'Y-m-d', $this->start ) < date( 'Y-m-d', $this->end );
  461.  
  462.             if ( $multiday_booking ) {
  463.                 if ( date( 'YmdHi', $block_end ) > date( 'YmdHi', $this->start ) || date( 'YmdHi', $block_start ) < date( 'YmdHi', $this->end ) ) {
  464.                     return true;
  465.                 }
  466.                 return false;
  467.             }
  468.  
  469.             while ( $loop_date <= $this->end ) {
  470.                 if ( date( 'Y-m-d', $loop_date ) === date( 'Y-m-d', $block_start ) ) {
  471.                     return true;
  472.                 }
  473.                 $loop_date = strtotime( "+1 day", $loop_date );
  474.             }
  475.         }
  476.         return false;
  477.     }
  478.  
  479.     /**
  480.      * See if this booking can still be cancelled by the user or not
  481.      * @return boolean
  482.      */
  483.     public function passed_cancel_day() {
  484.         $booking = $this->get_product();
  485.  
  486.         if ( $booking !== false ) {
  487.             $cancel_limit      = $booking->wc_booking_cancel_limit;
  488.             $cancel_limit_unit = $cancel_limit > 1 ? $booking->wc_booking_cancel_limit_unit . 's' : $booking->wc_booking_cancel_limit_unit;
  489.             $cancel_string     = sprintf( '%s +%d %s', current_time( 'd F Y H:i:s' ), $cancel_limit, $cancel_limit_unit );
  490.  
  491.             if ( strtotime( $cancel_string ) >= $this->start ) {
  492.                 return true;
  493.             }
  494.         }
  495.  
  496.         return false;
  497.     }
  498.  
  499.     /**
  500.      * Returns booking start date
  501.      * @return string Date formatted via date_i18n
  502.      */
  503.     public function get_start_date( $date_format = null, $time_format = null ) {
  504.         if ( $this->populated && ! empty( $this->start ) ) {
  505.             if ( is_null( $date_format ) ) {
  506.                 $date_format = apply_filters( 'woocommerce_bookings_date_format', 'M jS Y' );
  507.             }
  508.             if ( is_null( $time_format ) ) {
  509.                 $time_format = apply_filters( 'woocommerce_bookings_time_format', ', g:ia' );
  510.             }
  511.             if ( $this->is_all_day() ) {
  512.                 return date_i18n( $date_format, $this->start );
  513.             } else {
  514.                 return date_i18n( $date_format . $time_format, $this->start );
  515.             }
  516.         }
  517.  
  518.         return false;
  519.     }
  520.  
  521.     /**
  522.      * Returns booking end date
  523.      * @return string Date formatted via date_i18n
  524.      */
  525.     public function get_end_date( $date_format = null, $time_format = null ) {
  526.         if ( $this->populated && ! empty( $this->end ) ) {
  527.             if ( is_null( $date_format ) ) {
  528.                 $date_format = apply_filters( 'woocommerce_bookings_date_format', 'M jS Y' );
  529.             }
  530.             if ( is_null( $time_format ) ) {
  531.                 $time_format = apply_filters( 'woocommerce_bookings_time_format', ', g:ia' );
  532.             }
  533.             if ( $this->is_all_day() ) {
  534.                 return date_i18n( $date_format, $this->end );
  535.             } else {
  536.                 return date_i18n( $date_format . $time_format, $this->end );
  537.             }
  538.         }
  539.  
  540.         return false;
  541.     }
  542.  
  543.     /**
  544.      * Returns information about the customer of this order
  545.      * @return array containing customer information
  546.      */
  547.     public function get_customer() {
  548.         if ( $this->populated ) {
  549.             $order = $this->get_order();
  550.  
  551.             if ( $order )
  552.                 return (object) array(
  553.                     'name'    => trim( $order->billing_first_name . ' ' . $order->billing_last_name ),
  554.                     'email'   => $order->billing_email,
  555.                     'user_id' => $order->customer_user,
  556.                 );
  557.             elseif ( $this->customer_id ) {
  558.                 $user = get_user_by( 'id', $this->customer_id );
  559.  
  560.                 return (object) array(
  561.                     'name'    => $user->display_name,
  562.                     'email'   => $user->user_email,
  563.                     'user_id' => $this->customer_id
  564.                 );
  565.             }
  566.         }
  567.  
  568.         return false;
  569.     }
  570.  
  571.     /**
  572.      * Returns if persons are enabled/needed for the booking product
  573.      * @return boolean
  574.      */
  575.     public function has_persons() {
  576.         return $this->get_product() ? $this->get_product()->has_persons() : false;
  577.     }
  578.  
  579.     /**
  580.      * Returns if resources are enabled/needed for the booking product
  581.      * @return boolean
  582.      */
  583.     public function has_resources() {
  584.         return $this->get_product() ? $this->get_product()->has_resources() : false;
  585.     }
  586.  
  587.     /**
  588.      * Return a array with the booking persons.
  589.      * @return array
  590.      */
  591.     public function get_persons() {
  592.         return (array) $this->persons;
  593.     }
  594.  
  595.     /**
  596.      * Return the amount of persons for this booking.
  597.      * @return int
  598.      */
  599.     public function get_persons_total() {
  600.         return array_sum( $this->get_persons() );
  601.     }
  602.  
  603.     /**
  604.      * Get the resource id
  605.      * @return int
  606.      */
  607.     public function get_resource_id() {
  608.         if ( $this->populated ) {
  609.             return absint( $this->resource_id );
  610.         }
  611.         return 0;
  612.     }
  613.  
  614.     /**
  615.      * Get the resource/type for this booking if applicable.
  616.      * @return bool|object WP_Post
  617.      */
  618.     public function get_resource() {
  619.         $resource_id = $this->get_resource_id();
  620.  
  621.         if ( ! $resource_id || ! ( $product = $this->get_product() ) || ! method_exists( $product, 'get_resource' ) ) {
  622.             return false;
  623.         }
  624.  
  625.         return $product->get_resource( $resource_id );
  626.     }
  627. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement