我需要你對WordPress和woocommerce很棒的技能,我有一個問題,我不知道爲什麼woocommerce預訂會拋出:Woocommerce預訂:致命錯誤:調用一個非對象的成員函數has_persons()
**Fatal error: Call to a member function `has_persons()` on a non-object in `xxx/plugins/woocommerce-bookings/includes/class-wc-booking.php` on line 557**
並且它停止所有的腳本執行。
的woocommerce艙位:所有預訂
<?php
/** * 主要模型類,這個處理所有的數據 */ 類WC_Booking {
/** @public int */
public $id;
/** @public string */
public $booking_date;
/** @public string */
public $start;
/** @public string */
public $end;
/** @public bool */
public $all_day;
/** @public string */
public $modified_date;
/** @public object */
public $post;
/** @public int */
public $product_id;
/** @public object */
public $product;
/** @public int */
public $order_id;
/** @public object */
public $order;
/** @public int */
public $customer_id;
/** @public string */
public $status;
/** @public array - contains all post meta values for this booking */
public $custom_fields;
/** @public bool */
public $populated;
/** @private array - used to temporarily hold order data for new bookings */
private $order_data;
/**
* Constructor, possibly sets up with post or id belonging to existing booking
* or supplied with an array to construct a new booking
* @param int/array/obj $booking_data
*/
public function __construct($booking_data = false) {
$populated = false;
if (is_array($booking_data)) {
$this->order_data = $booking_data;
$populated = false;
} else if (is_int(intval($booking_data)) && 0 < $booking_data) {
$populated = $this->populate_data($booking_data);
} else if (is_object($booking_data) && isset($booking_data->ID)) {
$this->post = $booking_data;
$populated = $this->populate_data($booking_data->ID);
}
$this->populated = $populated;
}
/**
* Actual create for the new booking belonging to an order
* @param string Status for new order
*/
public function create($status = 'unpaid') {
$this->new_booking($status, $this->order_data);
$this->schedule_events();
}
/**
* Schedule events for this booking
*/
public function schedule_events() {
switch (get_post_status($this->id)) {
case "paid" :
if ($this->start && $this->get_order()) {
$order_status = $this->get_order()->get_status();
if (! in_array($order_status, array('cancelled', 'refunded', 'pending', 'on-hold'))) {
wp_schedule_single_event(strtotime('-' . absint(apply_filters('woocommerce_bookings_remind_before_days', 1)) . ' day', $this->start), 'wc-booking-reminder', array($this->id));
}
}
if ($this->end) {
wp_schedule_single_event($this->end, 'wc-booking-complete', array($this->id));
}
break;
default :
wp_clear_scheduled_hook('wc-booking-reminder', array($this->id));
wp_clear_scheduled_hook('wc-booking-complete', array($this->id));
break;
}
}
/**
* Makes the new booking belonging to an order
* @param string $status The status for this new booking
* @param array $order_data Array with all the new order data
*/
private function new_booking($status, $order_data) {
global $wpdb;
$order_data = wp_parse_args($order_data, array(
'user_id' => 0,
'resource_id' => '',
'product_id' => '',
'order_item_id' => '',
'persons' => array(),
'cost' => '',
'start_date' => '',
'end_date' => '',
'all_day' => 0,
'parent_id' => 0,
));
// Get parent data
if ($order_data['parent_id']) {
if (! $order_data['order_item_id']) {
$order_data['order_item_id'] = get_post_meta($order_data['parent_id'], '_booking_order_item_id', true);
}
if (! $order_data['user_id']) {
$order_data['user_id'] = get_post_meta($order_data['parent_id'], '_booking_customer_id', true);
}
}
// Get order ID from order item
if ($order_data['order_item_id']) {
$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']));
} else {
$order_id = 0;
}
$booking_data = array(
'post_type' => 'wc_booking',
'post_title' => sprintf(__('Booking – %s', 'woocommerce-bookings'), strftime(_x('%b %d, %Y @ %I:%M %p', 'Booking date parsed by strftime', 'woocommerce-bookings'))),
'post_status' => $status,
'ping_status' => 'closed',
'post_parent' => $order_id
);
$this->id = wp_insert_post($booking_data);
// Setup the required data for the current user
if (! $order_data['user_id']) {
if (is_user_logged_in()) {
$order_data['user_id'] = get_current_user_id();
} else {
$order_data['user_id'] = 0;
}
}
// Convert booking start and end to requried format
if (is_numeric($order_data['start_date'])) {
// Convert timestamp
$order_data['start_date'] = date('YmdHis', $order_data['start_date']);
$order_data['end_date'] = date('YmdHis', $order_data['end_date']);
} else {
$order_data['start_date'] = date('YmdHis', strtotime($order_data['start_date']));
$order_data['end_date'] = date('YmdHis', strtotime($order_data['end_date']));
}
$meta_args = array(
'_booking_order_item_id' => $order_data['order_item_id'],
'_booking_product_id' => $order_data['product_id'],
'_booking_resource_id' => $order_data['resource_id'],
'_booking_persons' => $order_data['persons'],
'_booking_cost' => $order_data['cost'],
'_booking_start' => $order_data['start_date'],
'_booking_end' => $order_data['end_date'],
'_booking_all_day' => intval($order_data['all_day']),
'_booking_parent_id' => $order_data['parent_id'],
'_booking_customer_id' => $order_data['user_id'],
);
foreach ($meta_args as $key => $value) {
update_post_meta($this->id, $key, $value);
}
WC_Cache_Helper::get_transient_version('bookings', true);
do_action('woocommerce_new_booking', $this->id);
}
/**
* Assign this booking to an order and order item by ID
* @param int $order_id
* @param int $order_item_id
*/
public function set_order_id($order_id, $order_item_id) {
$this->order_id = $order_id;
wp_update_post(array('ID' => $this->id, 'post_parent' => $this->order_id));
update_post_meta($this->id, '_booking_order_item_id', $order_item_id);
}
/**
* Populate the data with the id of the booking provided
* Will query for the post belonging to this booking and store it
* @param int $booking_id
*/
public function populate_data($booking_id) {
if (! isset($this->post)) {
$post = get_post($booking_id);
}
if (is_object($post)) {
// We have the post object belonging to this booking, now let's populate
$this->id = $post->ID;
$this->booking_date = $post->post_date;
$this->modified_date = $post->post_modified;
$this->customer_id = $post->post_author;
$this->custom_fields = get_post_meta($this->id);
$this->status = $post->post_status;
$this->order_id = $post->post_parent;
// Define the data we're going to load: Key => Default value
$load_data = array(
'product_id' => '',
'resource_id' => '',
'persons' => array(),
'cost' => '',
'start' => '',
'customer_id' => '',
'end' => '',
'all_day' => 0,
'parent_id' => 0,
);
// Load the data from the custom fields (with prefix for this plugin)
$meta_prefix = '_booking_';
foreach ($load_data as $key => $default) {
if (isset($this->custom_fields[ $meta_prefix . $key ][0]) && $this->custom_fields[ $meta_prefix . $key ][0] !== '') {
$this->$key = maybe_unserialize($this->custom_fields[ $meta_prefix . $key ][0]);
} else {
$this->$key = $default;
}
}
// Start and end date converted to timestamp
$this->start = strtotime($this->start);
$this->end = strtotime($this->end);
// Save the post object itself for future reference
$this->post = $post;
return true;
}
return false;
}
/**
* Will change the booking status once the order is paid for
* @return bool
*/
public function paid() {
$current_status = $this->status;
$event = wp_get_schedule('wc-booking-reminder', array($this->id));
if ($this->populated && in_array($current_status, array('unpaid', 'confirmed'))) {
$this->update_status('paid');
if (! empty($event)) {
$this->schedule_events();
}
return true;
}
return false;
}
/**
* Set the new status for this booking
* @param string $status
* @return bool
*/
public function update_status($status) {
$current_status = $this->get_status(true);
$allowed_statuses = array('unpaid', 'pending-confirmation', 'confirmed', 'paid', 'cancelled', 'complete', 'in-cart', 'was-in-cart');
if ($this->populated) {
if (in_array($status, $allowed_statuses)) {
wp_update_post(array('ID' => $this->id, 'post_status' => $status));
// Reschedule cron
$this->schedule_events();
// Trigger actions
do_action('woocommerce_booking_' . $current_status . '_to_' . $status, $this->id);
do_action('woocommerce_booking_' . $status, $this->id);
// Note in the order
if ($order = $this->get_order()) {
$order->add_order_note(sprintf(__('Booking #%d status changed from "%s" to "%s', 'woocommerce-bookings'), $this->id, $current_status, $status));
}
return true;
}
}
return false;
}
/**
* Checks the booking status against a passed in status.
*
* @return bool
*/
public function has_status($status) {
return apply_filters('woocommerce_booking_has_status', (is_array($status) && in_array($this->get_status(), $status)) || $this->get_status() === $status ? true : false, $this, $status);
}
/**
* Returns the status of this booking
* @param Bool to ask for pretty status name (if false)
* @return String of the booking status
*/
public function get_status($raw = true) {
if ($this->populated) {
if ($raw) {
return $this->status;
} else {
$status_object = get_post_status_object($this->status);
return $status_object->label;
}
}
return false;
}
/**
* Returns the id of this booking
* @return Id of the booking or false if booking is not populated
*/
public function get_id() {
if ($this->populated) {
return $this->id;
}
return false;
}
/**
* Get the product ID for the booking
* @return int or false if booking is not populated
*/
public function get_product_id() {
if ($this->populated) {
return $this->product_id;
}
return false;
}
/**
* Returns the object of the order corresponding to this booking
* @return Product object or false if booking is not populated
*/
public function get_product() {
if (empty($this->product)) {
if ($this->populated && $this->product_id) {
$this->product = get_product($this->product_id);
} else {
return false;
}
}
return $this->product;
}
/**
* Returns the object of the order corresponding to this booking
* @return Order object or false if booking is not populated
*/
public function get_order() {
if (empty($this->order)) {
if ($this->populated && ! empty($this->order_id) && 'shop_order' === get_post_type($this->order_id)) {
$this->order = wc_get_order($this->order_id);
} else {
return false;
}
}
return $this->order;
}
/**
* Returns the cancel URL for a booking
*
* @param string $redirect
* @return string
*/
public function get_cancel_url($redirect = '') {
$cancel_page = get_permalink(wc_get_page_id('myaccount'));
if (! $cancel_page) {
$cancel_page = home_url();
}
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'));
}
/**
* Return if all day event
* @return boolean
*/
public function is_all_day() {
if ($this->populated) {
if ($this->all_day) {
return true;
} else {
return false;
}
}
return false;
}
/**
* See if this booking is booked on said date
* @return boolean
*/
public function is_booked_on_day($block_start, $block_end) {
if ($this->populated) {
$loop_date = $this->start;
$multiday_booking = date('Y-m-d', $this->start) < date('Y-m-d', $this->end);
if ($multiday_booking) {
if (date('YmdHi', $block_end) > date('YmdHi', $this->start) || date('YmdHi', $block_start) < date('YmdHi', $this->end)) {
return true;
}
return false;
}
while ($loop_date <= $this->end) {
if (date('Y-m-d', $loop_date) === date('Y-m-d', $block_start)) {
return true;
}
$loop_date = strtotime("+1 day", $loop_date);
}
}
return false;
}
/**
* See if this booking can still be cancelled by the user or not
* @return boolean
*/
public function passed_cancel_day() {
$booking = $this->get_product();
if ($booking !== false) {
$cancel_limit = $booking->wc_booking_cancel_limit;
$cancel_limit_unit = $cancel_limit > 1 ? $booking->wc_booking_cancel_limit_unit . 's' : $booking->wc_booking_cancel_limit_unit;
$cancel_string = sprintf('now +%d %s', $cancel_limit, $cancel_limit_unit);
if (strtotime($cancel_string) >= $this->start) {
return true;
}
}
return false;
}
/**
* Returns booking start date
* @return string Date formatted via date_i18n
*/
public function get_start_date($date_format = null, $time_format = null) {
if ($this->populated && ! empty($this->start)) {
if (is_null($date_format)) {
$date_format = apply_filters('woocommerce_bookings_date_format', 'M jS Y');
}
if (is_null($time_format)) {
$time_format = apply_filters('woocommerce_bookings_time_format', ', g:ia');
}
if ($this->is_all_day()) {
return date_i18n($date_format, $this->start);
} else {
return date_i18n($date_format . $time_format, $this->start);
}
}
return false;
}
/**
* Returns booking end date
* @return string Date formatted via date_i18n
*/
public function get_end_date($date_format = null, $time_format = null) {
if ($this->populated && ! empty($this->end)) {
if (is_null($date_format)) {
$date_format = apply_filters('woocommerce_bookings_date_format', 'M jS Y');
}
if (is_null($time_format)) {
$time_format = apply_filters('woocommerce_bookings_time_format', ', g:ia');
}
if ($this->is_all_day()) {
return date_i18n($date_format, $this->end);
} else {
return date_i18n($date_format . $time_format, $this->end);
}
}
return false;
}
/**
* Returns information about the customer of this order
* @return array containing customer information
*/
public function get_customer() {
if ($this->populated) {
$order = $this->get_order();
if ($order)
return (object) array(
'name' => trim($order->billing_first_name . ' ' . $order->billing_last_name),
'email' => $order->billing_email,
'user_id' => $order->customer_user,
);
elseif ($this->customer_id) {
$user = get_user_by('id', $this->customer_id);
return (object) array(
'name' => $user->display_name,
'email' => $user->user_email,
'user_id' => $this->customer_id
);
}
}
return false;
}
/**
* Returns if persons are enabled/needed for the booking product
* @return boolean
*/
public function has_persons() {
return $this->get_product()->has_persons();
}
/**
* Returns if resources are enabled/needed for the booking product
* @return boolean
*/
public function has_resources() {
return $this->get_product()->has_resources();
}
/**
* Return a array with the booking persons.
* @return array
*/
public function get_persons() {
return (array) $this->persons;
}
/**
* Return the amount of persons for this booking.
* @return int
*/
public function get_persons_total() {
return array_sum($this->get_persons());
}
/**
* Get the resource id
* @return int
*/
public function get_resource_id() {
if ($this->populated) {
return absint($this->resource_id);
}
return 0;
}
/**
* Get the resource/type for this booking if applicable.
* @return bool|object WP_Post
*/
public function get_resource() {
$resource_id = $this->get_resource_id();
if (! $resource_id || ! ($product = $this->get_product()) || ! method_exists($product, 'get_resource')) {
return false;
}
return $product->get_resource($resource_id);
}
}
and on line 57
/**
* Returns if persons are enabled/needed for the booking product
* @return boolean
*/
public function has_persons() {
return $this->get_product()->has_persons();
}
有人可以幫我嗎?
謝謝
的woocommerce-預訂插件似乎是調用'has_persons()'方法的非對象上。該方法需要在WC_Booking類型的對象上調用 – henrywright
謝謝您回覆henrywright,但我不明白我可以在哪裏WC_Booking? – user44321