Passing Meta Array in WP-REST API - wordpress

I have been trying to pass a meta array to a post via front-end using WP-REST API but to no avail.
functions.php:
//Add custom field to REST API
function filter_post_json( $data, $post, $context ) {
$social_media = get_post_custom_values( 'social_media' );
$sm = [];
if($social_media):
foreach ( $social_media as $key => $value ) {
$sm[] = $value;
}
endif;
$data->data['social_media'] = $sm;
return $data;
}
add_filter( 'rest_prepare_custom-post-type', 'filter_post_json', 10, 3 );
add_action('rest_api_init', 'register_custom_meta');
function register_custom_meta() {
$post_custom_fields = array(
'social_media'
);
foreach ($post_custom_fields as $key) {
register_rest_field('custom-post-type', $key, array(
'schema' => null,
'get_callback' => 'get_meta_field',
'update_callback' => 'update_meta_field',
));
}
}
/**
* Handler for getting custom field data.
*
* #since 0.1.0
*
* #param array $object The object from the response
* #param string $field_name Name of field
* #param WP_REST_Request $request Current request
*
* #return mixed
*/
function get_meta_field( $object, $field_name, $request ) {
return get_post_meta( $object[ 'id' ], $field_name );
}
/**
* Handler for updating custom field data.
*
* #since 0.1.0
*
* #param mixed $value The value of the field
* #param object $object The object from the response
* #param string $field_name Name of field
*
* #return bool|int
*/
function update_meta_field( $value, $object, $field_name ) {
if ( ! $value || ! is_string( $value ) ) {
return;
}
return update_post_meta( $object->ID, $field_name, strip_tags( $value ) );
}
jQuery:
var sm1 = ['hi','hello'];
console.log(sm1);
var data = {
social_media: sm1
};
$.ajax({
method: "POST",
url: POST_SUBMITTER.root + 'wp/v2/custom',
data: data,
beforeSend: function ( xhr ) {
xhr.setRequestHeader( 'X-WP-Nonce', POST_SUBMITTER.nonce );
},
success : function( response ) {
console.log( response );
alert( POST_SUBMITTER.success );
},
fail : function( response ) {
console.log( response );
alert( POST_SUBMITTER.failure );
}
This is the JSON output when I try to insert a post:
{
"id": 120,
"date": "2017-04-07T09:48:39",
"date_gmt": "2017-04-07T08:48:39",
"author": 1,
"featured_media": 0,
"menu_order": 0,
"template": "",
"format": "standard",
"social_media": [],
}
}
JSON output when I view a post (for brevity I have kept it short):
[
{
"id": 116,
"date": "2017-04-07T09:43:53",
"date_gmt": "2017-04-07T08:43:53",
"social_media": [
"facebook",
"instagram"
]
}]

Related

/Public_html/Wp-Includes/Class-Wp-Hook.Php On Line 307 loader imageClose

[enter image description here][1]
Warning: Call_user_func_array() Expects Parameter 1 To Be A Valid Callback, Function 'Feed' Not Found Or Invalid Function Name In /Home/Hkrpvloo/Public_html/Wp-Includes/Class-Wp-Hook.Php On Line 307
/**
* Calls the callback functions that have been added to a filter hook.
*
* #since 4.7.0
*
* #param mixed $value The value to filter.
* #param array $args Additional parameters to pass to the callback functions.
* This array is expected to include $value at index 0.
* #return mixed The filtered value after all hooked functions are applied to it.
*/
public function apply_filters( $value, $args ) {
if ( ! $this->callbacks ) {
return $value;
}
$nesting_level = $this->nesting_level++;
$this->iterations[ $nesting_level ] = array_keys( $this->callbacks );
$num_args = count( $args );
do {
$this->current_priority[ $nesting_level ] = current( $this->iterations[ $nesting_level ] );
$priority = $this->current_priority[ $nesting_level ];
foreach ( $this->callbacks[ $priority ] as $the_ ) {
if ( ! $this->doing_action ) {
$args[0] = $value;
}
// Avoid the array_slice if possible.
if ( $the_['accepted_args'] == 0 ) {
$value = call_user_func_array( $the_['function'], array() );
} elseif ( $the_['accepted_args'] >= $num_args ) {
$value = call_user_func_array( $the_['function'], $args );
} else {
$value = call_user_func_array( $the_['function'], array_slice( $args, 0, (int)$the_['accepted_args'] ) );
}
}
} while ( false !== next( $this->iterations[ $nesting_level ] ) );
unset( $this->iterations[ $nesting_level ] );
unset( $this->current_priority[ $nesting_level ] );
[enter image description here][2]
$this->nesting_level--;
return $value;
}

wp_verfy_nonce keeps giving false

i have a form somthing like this
<form id="sample_docs" method="post" action="<?php echo admin_url('admin-ajax.php'); ?>">
<?php wp_nonce_field('nonce_action_sample_docs', 'nonce_sample_docs'); ?>
<input type="hidden" name="action" value="sample_docs">
</form>
and then i have a ajax for this like so
$('form#sample_docs').on('submit', function(e){
e.preventDefault();
id = $(this).attr('id');
url = $(this).attr('action');
$.ajax({
url: url,
type: "POST",
data: formData,
cache: false,
processData: false,
contentType: false,
async: true,
headers: {
"cache-control": "no-cache"
},
success: function(data){
data = $.parseJSON(data);
console.log('data', data);
}
});
return false;
});
and then in my php side to handle the ajax m doing this
function sample_docs()
{
var_dump(wp_verify_nonce($_POST['nonce_sample_docs'],'nonce_action_sample_docs));
die();
if(wp_verify_nonce($_POST['nonce_sample_docs'],'nonce_action_sample_docs'))
{
//do something
}
} add_action('wp_ajax_sample_docs', 'sample_docs'); add_action('wp_ajax_nopriv_sample_docs', 'sample_docs');
the wp_verify_nonce() function (in built WordPress function)
function wp_verify_nonce( $nonce, $action = -1 ) {
$nonce = (string) $nonce;
$user = wp_get_current_user();
$uid = (int) $user->ID;
if ( ! $uid ) {
/**
* Filters whether the user who generated the nonce is logged out.
*
* #since 3.5.0
*
* #param int $uid ID of the nonce-owning user.
* #param string $action The nonce action.
*/
$uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
}
if ( empty( $nonce ) ) {
return false;
}
$token = wp_get_session_token();
$i = wp_nonce_tick();
// Nonce generated 0-12 hours ago
$expected = substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
if ( hash_equals( $expected, $nonce ) ) {
return 1;
}
// Nonce generated 12-24 hours ago
$expected = substr( wp_hash( ( $i - 1 ) . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
if ( hash_equals( $expected, $nonce ) ) {
return 2;
}
/**
* Fires when nonce verification fails.
*
* #since 4.4.0
*
* #param string $nonce The invalid nonce.
* #param string|int $action The nonce action.
* #param WP_User $user The current user object.
* #param string $token The user's session token.
*/
do_action( 'wp_verify_nonce_failed', $nonce, $action, $user, $token );
// Invalid nonce
return false;
}
so when i do this i get false
i have checked if the value $_POST['nonce_sample_doc'], goes to the function
and it does i have also checked that if it goes inside the wp_verify_nonce() function and it does what i found odd was that
in side the wp_verify_nonce() function when i checked the value of $expected and $nonce it was different
so my question is how to make the value true
inside my sample_doc function
You have a typo in your sample_doc function, the input name is nonce_sample_docs, but you are using nonce_sample_doc in $_POST.
Fixed code:
function sample_doc()
{
var_dump(wp_verify_nonce($_POST['nonce_sample_docs'],'nonce_action_sample_docs));
die();
if(wp_verify_nonce($_POST['nonce_sample_doc'],'nonce_action_sample_docs'))
{
//do something
}
} add_action('wp_ajax_sample_doc', 'sample_doc'); add_action('wp_ajax_nopriv_sample_doc', 'sample_doc');

Create Post with Meta Field – WP REST API

I have just started with REST API and using it for creating posts from frontend. I managed to publish post with Title, Excerpt, Content.
I want to add a Custom Meta Field value aswell, any example or help is much appreciated.
This is my Ajax Code, all other fields working fine except meta value is not being added in post
jQuery( document ).ready( function ( $ ) {
$( '#post-submission-form' ).on( 'submit', function(e) {
e.preventDefault();
var title = $( '#post-submission-title' ).val();
var excerpt = $( '#post-submission-excerpt' ).val();
var content = $( '#post-submission-content' ).val();
var status = 'draft';
var data = {
title: title,
excerpt: excerpt,
content: content,
status: status,
meta: {
'video_url_url' : 'abc',
}
};
$.ajax({
method: "POST",
url: POST_SUBMITTER.root + 'wp/v2/posts',
data: data,
beforeSend: function ( xhr ) {
xhr.setRequestHeader( 'X-WP-Nonce', POST_SUBMITTER.nonce );
},
success : function( response ) {
console.log( response );
alert( POST_SUBMITTER.success );
},
fail : function( response ) {
console.log( response );
alert( POST_SUBMITTER.failure );
}
});
});
} );
Add this to your functions.php :
/**
* Add the meta fields to REST API responses for posts read and write
* Read and write a post meta fields in post responses
*/
function mg_register_meta_api() {
//Meta Fields that should be added to the API
$meta_fields = array(
'video_url_url',
'another_meta_key'
);
//Iterate through all fields and add register each of them to the API
foreach ($meta_fields as $field) {
register_rest_field( 'ring',
$field,
array(
'get_callback' => array( $this, 'mg_fw_get_meta'),
'update_callback' => array( $this, 'mg_fw_update_meta'),
'schema' => null,
)
);
}
}
add_action( 'rest_api_init', 'mg_register_meta_api' );
/**
* Handler for getting custom field data.
*
* #since 0.1.0
*
* #param array $object The object from the response
* #param string $field_name Name of field
*
* #return mixed
*/
function mg_get_meta( $object, $field_name ) {
return get_post_meta( $object[ 'id' ], $field_name );
}
/**
* Handler for updating custom field data.
*
* #since 0.1.0
* #link http://manual.unyson.io/en/latest/helpers/php.html#database
* #param mixed $value The value of the field
* #param object $object The object from the response
* #param string $field_name Name of field
*
* #return bool|int
*/
function mg_update_meta( $value, $object, $field_name ) {
if ( ! $value || ! is_string( $value ) ) {
return;
}
return update_post_meta( $object->ID, $field_name, maybe_serialize( strip_tags( $value ) ) );
}
Now you should be able to read and write for meta 'video_url_url' using the api.
I was playing around with this today and came up with the following solution that works well and adds multiple fields.
Hope this helps anyone who may be stuck on this.
add_action( 'rest_api_init', 'foo_register_meta_api' );
function foo_register_meta_api() {
// Meta Fields to add to the API
$meta_fields = array(
'field_1',
'foo_bar',
'foobar',
'another_field'
);
// Loop all fields and register each of them to the API
foreach ($meta_fields as $field) {
register_rest_field( 'my-post-type',
$field,
array(
'get_callback' => function ($params) use ($field) {
return \get_post_meta($params['id'], $field);
},
'update_callback' => function ($value, $object, $fieldName){
return \update_post_meta($object->ID, $fieldName, $value);
},
'schema' => null
)
);
}
}
I am trying to save phy_marks in post type candidates. What I've got is creating the post but not saving phy_marks.
My JSON data:
{ "title": "Why not working finally","content": "Test", "status": "publish" ,"post_type": "candidates", "meta": {
"phy_marks": 66 } }
My Code:
add_action( 'rest_api_init', 'foo_register_meta_api' );
function foo_register_meta_api() {
// Meta Fields to add to the API
$meta_fields = array(
'phy_marks'
);
// Loop all fields and register each of them to the API
foreach ($meta_fields as $field) {
register_rest_field( 'candidates',
$field,
array(
'get_callback' => function ($params) use ($field) {
return \get_post_meta($params['id'], $field);
},
'update_callback' => function ($value, $object, $fieldName){
return \update_post_meta($object->ID, $fieldName, $value);
},
'schema' => null
)
);
}
}

Woocommerce booking :Fatal error: Call to a member function has_persons() on a non-object in

I need your great skills on WordPress and woocommerce, I have an issue that I don't know why woocommerce booking throw this :
**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**
and it stop all scripts executions.
the woocommerce booking class :
<?php
/**
* Main model class for all bookings, this handles all the data
*/
class 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();
}
Can someone help me please?
Thank you
I solved exactly the same error message with this fix :
In folder
/var/www/html/wp-content/plugins/woocommerce-bookings/includes
In file :
class-wc-booking.php
Replace :
/**
* Returns if persons are enabled/needed for the booking product
* #return boolean
*/
public function has_persons() {
return $this->get_product()->has_persons();
}
By :
/**
* Returns if persons are enabled/needed for the booking product
* #return boolean
*/
public function has_persons() {
if ($this->get_product()) {
return $this->get_product()->has_persons();
} else
{
return 0;
}
}

Symfony2 refactoring controller logic into a service

I'm slowly beginning to understand how things in Symfony2 are working.
I have set up a service which pulls json data from a live feed.
My controller uses this service to pull the data and then persist it to my database, I currently have 3 entities, though there are likely to be quite a few more.
All the logic at present is in FantasyPro/DataBundle
I'm currently breaking all sorts of rules, such as the logic for persisting my data is in a controller, so i'm thinking i need to take all this logic and put it into a service which i can use to persist the pulled data into my database via doctrine.
I would like to create this new PersistServce in the DataBundle
As the service will need to use doctrine all the entitys i have as well as the api service i'm not sure how to go about making these available to the service.
It probably worth mentioning that i intend to create commands so that i can run cron jobs to pull this data, in fact i don't think i will need the controller at all as they will only be used internally and not for generating requests.
I have it in a controller right now simply for testing purposes.
Whats the best way to refactor this code into a service?
Heres my messy controller code
<?php
namespace FantasyPro\DataBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use FantasyPro\DataBundle\Entity\Stadium;
use FantasyPro\DataBundle\Entity\Team;
use FantasyPro\DataBundle\Entity\Player;
class DefaultController extends Controller
{
public function indexAction($name)
{
return $this->render('DataBundle:Default:index.html.twig', array('name' => $name));
}
/**
* #return \Symfony\Component\HttpFoundation\Response
*/
public function updateStadiumAction(){
//get list of stadiums
$client = $this->container->get('fantasyapi');
$stadiumData = $client->Stadiums();
//get the entity manager
$em = $this->getDoctrine()->getManager();
$repo = $em->getRepository('DataBundle:Stadium');
$log = array();
$log = $this->addStadiumList( $stadiumData, $repo, $em, $log );
$em->flush();
return $this->render('DataBundle:Default:index.html.twig', array('log' => $log));
}
public function updateTeamAction()
{
//get list of teams
$client = $this->container->get('fantasyapi');
$teamData = $client->Teams();
//get the entity manager
$em = $this->getDoctrine()->getManager();
$repo = $em->getRepository('DataBundle:Team');
$log = array();
$log = $this->addTeamList( $teamData, $repo, $em, $log, 'Team' );
$em->flush();
return $this->render('DataBundle:Default:index.html.twig', array('log' => $log));
}
public function updatePlayerAction()
{
//get the api client
$client = $this->container->get('fantasyapi');
//get the manager
$em = $this->getDoctrine()->getManager();
$teamRepo = $em->getRepository('DataBundle:Team');
$playerRepo = $em->getRepository('DataBundle:Player');
$log = array();
//first we need to get a list of teams as players can only be collected via a teamID
/** #var Team $teams */
$teams = $client->Teams();
//var_dump($teams);die;
//loop through the teams and pull the playerData
foreach($teams as $team){
//log the team we are processing
$logData = ['action' => 'Processing Players for:', 'itemID' => $team['TeamID'], 'itemName' => $team['FullName']];
$log[] = $logData;
//get list players on this team
$players = $client->Players(['Team' => $team['Key']]);
//loop through the players
$log = $this->addPlayerList( $players, $playerRepo, $em, $log, 'Added Active Player' );
}
//now get free agents
$freeAgents = $client->FreeAgents();
$log = $this->addPlayerList($freeAgents, $playerRepo, $em, $log, 'Free Agent');
$em->flush();
return $this->render('DataBundle:Default:index.html.twig', array('log' => $log));
}
public function parseDate($dateString)
{
if ($dateString) {
preg_match( '/\/Date\((\d+)([-+])(\d+)\)\//', $dateString, $date );
$timestamp = $date[1] / 1000;
$operator = $date[2];
$hours = $date[3] * 36; // Get the seconds
// $datetime = new \DateTime($timestamp, new \DateTimeZone('America/New_York'));
$datetime = new \DateTime();
$datetime->setTimestamp($timestamp);
$datetime->modify( $operator.$hours.' seconds' );
$datetime->setTimezone(new \DateTimeZone('UTC'));
//$datetime->format( 'd-m-Y H:i:s' );
//var_dump( $datetime );
//echo('*');
return ($datetime);
}
return(null);
}
/**
* #param Array $players
* #param $playerRepo
* #param $em
* #param Array $log
*
* #param String $logTitle
*
* #return array
*/
public function addPlayerList( $players, $playerRepo, $em, $log, $logTitle )
{
foreach ($players as $player) {
// Get the current player in the list
$criteria = array( 'playerID' => $player['PlayerID'] );
/** #var Player $storedPlayer */
$storedPlayer = $playerRepo->FindOneBy( $criteria );
//var_dump($player);
if ( ! $storedPlayer) {
//no player exists with the PlayerID passed
//create a new entry
/** #var Player $entry */
$entry = new Player();
$entry->setTeam( $player['Team'] );
$entry->setPlayerID( $player['PlayerID'] );
$entry->setNumber( $player['Number'] );
$entry->setFirstName( $player['FirstName'] );
$entry->setLastName( $player['LastName'] );
$entry->setPosition( $player['Position'] );
$entry->setStatus( $player['Status'] );
$entry->setHeight( $player['Height'] );
$entry->setWeight( $player['Weight'] );
//need to parse the date on this field
$entry->setBirthDate( $this->parseDate( $player['BirthDate']));
$entry->setCollege( $player['College'] );
$entry->setExperience( $player['Experience'] );
$entry->setFantasyPosition( $player['FantasyPosition'] );
$entry->setActive( $player['Active'] );
$entry->setPositionCategory( $player['PositionCategory'] );
$entry->setName( $player['Name'] );
$entry->setAge( $player['Age'] );
$entry->setExperienceString( $player['ExperienceString'] );
$entry->setBirthDateString( $player['BirthDateString'] );
$entry->setPhotoUrl( $player['PhotoUrl'] );
$entry->setByeWeek( $player['ByeWeek'] );
$entry->setUpcomingGameOpponent( $player['UpcomingGameOpponent'] );
$entry->setUpcomingGameWeek( $player['UpcomingGameWeek'] );
$entry->setShortName( $player['ShortName'] );
$entry->setAverageDraftPos( $player['AverageDraftPosition'] );
$entry->setDepthPositionCategory( $player['DepthPositionCategory'] );
$entry->setDepthPosition( $player['DepthOrder'] );
$entry->setDepthDisplayOrder( $player['DepthDisplayOrder'] );
$entry->setCurrentTeam( $player['CurrentTeam'] );
$entry->setCollegeDraftTeam( $player['CollegeDraftTeam'] );
$entry->setCollegeDraftYear( $player['CollegeDraftYear'] );
$entry->setCollegeDraftRound( $player['CollegeDraftRound'] );
$entry->setCollegeDraftPick( $player['CollegeDraftPick'] );
$entry->setIsUndraftedFreeAgent( $player['IsUndraftedFreeAgent'] );
$entry->setHeightFeet( $player['HeightFeet'] );
$entry->setHeightInches( $player['HeightInches'] );
$entry->setUpcomingOpponentRank( $player['UpcomingOpponentRank'] );
$entry->setUpcomingOpponentPositionRank( $player['UpcomingOpponentPositionRank'] );
$entry->setCurrentStatus( $player['CurrentStatus'] );
$entry->setUpcomingSalary( $player['UpcomingSalary'] );
$em->persist( $entry );
$logData = [ 'action' => 'Added '.$logTitle,
'itemID' => $player['PlayerID'],
'itemName' => $player['Name']
];
$log[] = $logData;
} else {
$storedPlayer->setPlayerID( $player['PlayerID'] );
$storedPlayer->setTeam( $player['Team'] );
$storedPlayer->setPlayerID( $player['PlayerID'] );
$storedPlayer->setNumber( $player['Number'] );
$storedPlayer->setFirstName( $player['FirstName'] );
$storedPlayer->setLastName( $player['LastName'] );
$storedPlayer->setPosition( $player['Position'] );
$storedPlayer->setStatus( $player['Status'] );
$storedPlayer->setHeight( $player['Height'] );
$storedPlayer->setWeight( $player['Weight'] );
//need to parse the date on this field
$storedPlayer->setBirthDate( $this->parseDate( $player['BirthDate']));
$storedPlayer->setCollege( $player['College'] );
$storedPlayer->setExperience( $player['Experience'] );
$storedPlayer->setFantasyPosition( $player['FantasyPosition'] );
$storedPlayer->setActive( $player['Active'] );
$storedPlayer->setPositionCategory( $player['PositionCategory'] );
$storedPlayer->setName( $player['Name'] );
$storedPlayer->setAge( $player['Age'] );
$storedPlayer->setExperienceString( $player['ExperienceString'] );
$storedPlayer->setBirthDateString( $player['BirthDateString'] );
$storedPlayer->setPhotoUrl( $player['PhotoUrl'] );
$storedPlayer->setByeWeek( $player['ByeWeek'] );
$storedPlayer->setUpcomingGameOpponent( $player['UpcomingGameOpponent'] );
$storedPlayer->setUpcomingGameWeek( $player['UpcomingGameWeek'] );
$storedPlayer->setShortName( $player['ShortName'] );
$storedPlayer->setAverageDraftPos( $player['AverageDraftPosition'] );
$storedPlayer->setDepthPositionCategory( $player['DepthPositionCategory'] );
$storedPlayer->setDepthPosition( $player['DepthOrder'] );
$storedPlayer->setDepthDisplayOrder( $player['DepthDisplayOrder'] );
$storedPlayer->setCurrentTeam( $player['CurrentTeam'] );
$storedPlayer->setCollegeDraftTeam( $player['CollegeDraftTeam'] );
$storedPlayer->setCollegeDraftYear( $player['CollegeDraftYear'] );
$storedPlayer->setCollegeDraftRound( $player['CollegeDraftRound'] );
$storedPlayer->setCollegeDraftPick( $player['CollegeDraftPick'] );
$storedPlayer->setIsUndraftedFreeAgent( $player['IsUndraftedFreeAgent'] );
$storedPlayer->setHeightFeet( $player['HeightFeet'] );
$storedPlayer->setHeightInches( $player['HeightInches'] );
$storedPlayer->setUpcomingOpponentRank( $player['UpcomingOpponentRank'] );
$storedPlayer->setUpcomingOpponentPositionRank( $player['UpcomingOpponentPositionRank'] );
$storedPlayer->setCurrentStatus( $player['CurrentStatus'] );
$storedPlayer->setUpcomingSalary( $player['UpcomingSalary'] );
$em->persist( $storedPlayer );
$logData = [ 'action' => 'Updated '.$logTitle,
'itemID' => $player['PlayerID'],
'itemName' => $player['Name']
];
$log[] = $logData;
}
}
return ($log);
}
/**
* #param Array $teamData
* #param $repo
* #param $em
* #param String $logTitle
*
* #return array
*/
public function addTeamList( $teamData, $repo, $em, $log, $logTitle )
{
foreach ($teamData as $team) {
// Get the current team in the list
$criteria = array( 'teamID' => $team['TeamID'] );
//var_dump($criteria);
/** #var Team $storedTeam */
$storedTeam = $repo->FindOneBy( $criteria );
if ( ! $storedTeam) {
//no stadium exists with the StadiumID passed
//create a new entry
/** #var Team $entry */
$entry = new Team();
$entry->setTeamKey( $team['Key'] );
$entry->setTeamID( $team['TeamID'] );
$entry->setPlayerID( $team['PlayerID'] );
$entry->setCity( $team['City'] );
$entry->setName( $team['Name'] );
$entry->setConference( $team['Conference'] );
$entry->setDivision( $team['Division'] );
$entry->setFullName( $team['FullName'] );
$entry->setStadiumID( $team['StadiumID'] );
$entry->setByeWeek( $team['ByeWeek'] );
$entry->setAvergageDraftPos( $team['AverageDraftPosition'] );
$entry->setAverageDraftPosPPR( $team['AverageDraftPositionPPR'] );
$entry->setHeadCoach( $team['HeadCoach'] );
$entry->setOffensiveCoordinator( $team['OffensiveCoordinator'] );
$entry->setDefensiveCoordinator( $team['DefensiveCoordinator'] );
$entry->setSpecialTeamsCoach( $team['SpecialTeamsCoach'] );
$entry->setOffensiveScheme( $team['OffensiveScheme'] );
$entry->setDefensiveScheme( $team['DefensiveScheme'] );
$entry->setUpcomingSalary( $team['UpcomingSalary'] );
$entry->setUpcomingOpponentRank( $team['UpcomingOpponentRank'] );
$entry->setUpcomingOpponentPositionRank( $team['UpcomingOpponentPositionRank'] );
$em->persist( $entry );
$logData = [ 'action' => 'Added New '.$logTitle , 'itemID' => $team['TeamID'], 'itemName' => $team['Name'] ];
$log[] = $logData;
} else {
$storedTeam->setTeamKey( $team['Key'] );
$storedTeam->setPlayerID( $team['PlayerID'] );
$storedTeam->setCity( $team['City'] );
$storedTeam->setName( $team['Name'] );
$storedTeam->setConference( $team['Conference'] );
$storedTeam->setDivision( $team['Division'] );
$storedTeam->setFullName( $team['FullName'] );
$storedTeam->setStadiumID( $team['StadiumID'] );
$storedTeam->setByeWeek( $team['ByeWeek'] );
$storedTeam->setAvergageDraftPos( $team['AverageDraftPosition'] );
$storedTeam->setAverageDraftPosPPR( $team['AverageDraftPositionPPR'] );
$storedTeam->setHeadCoach( $team['HeadCoach'] );
$storedTeam->setOffensiveCoordinator( $team['OffensiveCoordinator'] );
$storedTeam->setDefensiveCoordinator( $team['DefensiveCoordinator'] );
$storedTeam->setSpecialTeamsCoach( $team['SpecialTeamsCoach'] );
$storedTeam->setOffensiveScheme( $team['OffensiveScheme'] );
$storedTeam->setDefensiveScheme( $team['DefensiveScheme'] );
$storedTeam->setUpcomingSalary( $team['UpcomingSalary'] );
$storedTeam->setUpcomingOpponentRank( $team['UpcomingOpponentRank'] );
$storedTeam->setUpcomingOpponentPositionRank( $team['UpcomingOpponentPositionRank'] );
$em->persist( $storedTeam );
$logData = [ 'action' => 'Updated '.$logTitle , 'itemID' => $team['TeamID'], 'itemName' => $team['Name'] ];
$log[] = $logData;
}
}
return $log;
}
/**
* #param Array $stadiumData
* #param $repo
* #param $em
* #param $log
*
* #return array
*/
public function addStadiumList( $stadiumData, $repo, $em, $log )
{
foreach ($stadiumData as $stadium) {
// Get the current stadium in the list
$criteria = array( 'stadiumID' => $stadium['StadiumID'] );
//var_dump($criteria);
/** #var Stadium $storedStadium */
$storedStadium = $repo->FindOneBy( $criteria );
if ( ! $storedStadium) {
//no stadium exists with the StadiumID passed
//create a new entry
/** #var Stadium $entry */
$entry = new Stadium();
$entry->setStadiumID( $stadium['StadiumID'] );
$entry->setName( $stadium['Name'] );
$entry->setCity( $stadium['City'] );
$entry->setState( $stadium['State'] );
$entry->setCountry( $stadium['Country'] );
$entry->setCapacity( $stadium['Capacity'] );
$entry->setPlayingSurface( $stadium['PlayingSurface'] );
$em->persist( $entry );
$logData = [ 'action' => 'Added New Stadium',
'itemID' => $stadium['StadiumID'],
'itemName' => $stadium['Name']
];
$log[] = $logData;
} else {
$storedStadium->setStadiumID( $stadium['StadiumID'] );
$storedStadium->setName( $stadium['Name'] );
$storedStadium->setCity( $stadium['City'] );
$storedStadium->setState( $stadium['State'] );
$storedStadium->setCountry( $stadium['Country'] );
$storedStadium->setCapacity( $stadium['Capacity'] );
$storedStadium->setPlayingSurface( $stadium['PlayingSurface'] );
$em->persist( $storedStadium );
$logData = [ 'action' => 'Updated Stadium',
'itemID' => $stadium['StadiumID'],
'itemName' => $stadium['Name']
];
$log[] = $logData;
}
}
return $log;
}
}
The best way to handle your purposes for me is to create extended repository classes for your entities.
See Symfony2 - Doctrine documentation
In your case this might be:
namespace SomeBundle\Repository;
use Doctrine\ORM\EntityRepository;
class PlayerRepository extends EntityRepository
{
/**
* #param Array $players
* #param $playerRepo
* #param $em
* #param Array $log
*
* #param String $logTitle
*
* #return array
*/
public function addPlayerList($players, $log, $logTitle)
{
foreach ($players as $player) {
// Get the current player in the list
$criteria = array('playerID' => $player['PlayerID']);
/** #var Player $storedPlayer */
$storedPlayer = $this->findOneBy($criteria);
if (!$storedPlayer) {
$storedPlayer = new Player();
$logData = [
'action' => 'Added '.$logTitle,
'itemID' => $player['PlayerID'],
'itemName' => $player['Name']
];
$log[] = $logData;
} else {
$logData = [
'action' => 'Updated '.$logTitle,
'itemID' => $player['PlayerID'],
'itemName' => $player['Name']
];
$log[] = $logData;
}
$storedPlayer->setPlayerID($player['PlayerID']);
$storedPlayer->setTeam($player['Team']);
$storedPlayer->setPlayerID($player['PlayerID']);
$storedPlayer->setNumber($player['Number']);
$storedPlayer->setFirstName($player['FirstName']);
$storedPlayer->setLastName($player['LastName']);
$storedPlayer->setPosition($player['Position']);
$storedPlayer->setStatus($player['Status']);
$storedPlayer->setHeight($player['Height']);
$storedPlayer->setWeight($player['Weight']);
//need to parse the date on this field
$storedPlayer->setBirthDate($this->parseDate($player['BirthDate']));
$storedPlayer->setCollege($player['College']);
$storedPlayer->setExperience($player['Experience']);
$storedPlayer->setFantasyPosition($player['FantasyPosition']);
$storedPlayer->setActive($player['Active']);
$storedPlayer->setPositionCategory($player['PositionCategory']);
$storedPlayer->setName($player['Name']);
$storedPlayer->setAge($player['Age']);
$storedPlayer->setExperienceString($player['ExperienceString']);
$storedPlayer->setBirthDateString($player['BirthDateString']);
$storedPlayer->setPhotoUrl($player['PhotoUrl']);
$storedPlayer->setByeWeek($player['ByeWeek']);
$storedPlayer->setUpcomingGameOpponent($player['UpcomingGameOpponent']);
$storedPlayer->setUpcomingGameWeek($player['UpcomingGameWeek']);
$storedPlayer->setShortName($player['ShortName']);
$storedPlayer->setAverageDraftPos($player['AverageDraftPosition']);
$storedPlayer->setDepthPositionCategory($player['DepthPositionCategory']);
$storedPlayer->setDepthPosition($player['DepthOrder']);
$storedPlayer->setDepthDisplayOrder($player['DepthDisplayOrder']);
$storedPlayer->setCurrentTeam($player['CurrentTeam']);
$storedPlayer->setCollegeDraftTeam($player['CollegeDraftTeam']);
$storedPlayer->setCollegeDraftYear($player['CollegeDraftYear']);
$storedPlayer->setCollegeDraftRound($player['CollegeDraftRound']);
$storedPlayer->setCollegeDraftPick($player['CollegeDraftPick']);
$storedPlayer->setIsUndraftedFreeAgent($player['IsUndraftedFreeAgent']);
$storedPlayer->setHeightFeet($player['HeightFeet']);
$storedPlayer->setHeightInches($player['HeightInches']);
$storedPlayer->setUpcomingOpponentRank($player['UpcomingOpponentRank']);
$storedPlayer->setUpcomingOpponentPositionRank($player['UpcomingOpponentPositionRank']);
$storedPlayer->setCurrentStatus($player['CurrentStatus']);
$storedPlayer->setUpcomingSalary($player['UpcomingSalary']);
}
return ($log);
}
}
Also on my own I'll rather created date parser class to parse date inside this repositories like
$date = (new CustomDateTimeParser('your fancy date string here'))->getDateTime();

Resources