*/ class AffiGet_Review_Storage { /** * * @var AffiGet_Product_Meta $meta */ protected $meta; public function __construct( AffiGet_Review_Meta $meta ){ $this->meta = $meta; } public function load_post_fields( array &$review_data, $post ){ //afg_log(__METHOD__, $post); if( is_numeric( $post ) ){ $review_data['post_fields'] = get_post( $post, ARRAY_A ); if( ! $review_data['post_fields'] ){ echo '
';
throw new AffiGet_Exception('Failed to load post fields:' . compact('post'));
}
} elseif( is_object( $post ) && is_a( $post, 'WP_Post' ) ){
$review_data['post_fields'] = $post->to_array();
} elseif ( ! is_array( $post ) ) {
throw new AffiGet_Exception('Unexpected type of $post parameter: ' . compact('post'));
}
}
//
// Should be called AFTER $review has its ID assigned.
//
public function load_meta_fields( array &$review_data, $post_id = null ) {
if( is_null( $post_id )){
$post_id = $review_data['post_fields']['ID'];
}
if( ! $post_id ){
throw new AffiGet_Exception('Failed to load meta fields:' . compact('review_data'));
}
if( ! isset( $review_data['meta_fields'] )){
$review_data['meta_fields'] = array();
}
$fields = get_post_custom( $post_id );
if( $fields ){
foreach( $this->meta->known_meta_fields as $field_name => $config ){
$key = AFG_META_PREFIX . $field_name; //filter?
if( isset( $fields[ $key ] ) ){
$value = $fields[ $key ][0];
if( is_serialized( $value ) ){
$value = unserialize( $value );
} else {
//$value = $value;
}
if( has_filter("afg_review_storage__load_review_{$field_name}") ){
$value = apply_filters("afg_review_storage__load_review_{$field_name}", $value, 'raw', $post_id );
}
$review_data['meta_fields'][ $field_name ] = $value;
}
}
}
}
//
// get taxonomies, terms, categories
// Should be called AFTER $review has its ID assigned.
//
public function load_taxonomic_fields( array &$review_data, $post_id = null, $post_type = null ) {
if( is_null( $post_id )){
$post_id = $review_data['post_fields']['ID'];
}
if( is_null( $post_type )){
$post_type = $review_data['post_fields']['post_type'];
}
if( ! $post_id || ! $post_type ){
throw new AffiGet_Exception('Could not load taxonomic fields:' . compact('review_data', 'post_id', 'post_type'));
}
// get post type taxonomies
$taxonomies = get_object_taxonomies ( $post_type );
if( ! isset( $review_data['taxonomic_fields'] )){
$review_data['taxonomic_fields'] = array();
}
foreach( $taxonomies as $taxonomy_name ) {
// get the terms related to post
$terms = get_the_terms ( $post_id, $taxonomy_name );
//echo ''.$taxonomy_name.':'.print_r($terms, true).'
';
if( ! empty( $terms )) {
$tax = array();
foreach( $terms as $term ) {
$tax[ $term->term_id ] = html_entity_decode( $term->name ); //name comes sans slashes, entity-encoded
}
$review_data['taxonomic_fields'][ $taxonomy_name ] = $tax;
}
}
}
public function store_review_data( array &$review_data ){
if( empty( $review_data )){
throw new AffiGet_Exception('Parameter review_data should not be empty');
}
if( ! isset( $review_data['post_fields'] )){
throw new AffiGet_Exception('Parameter $review_data[post_fields] should not be empty!');
}
$has_meta = isset( $review_data['meta_fields'] ) && !empty( $review_data['meta_fields'] );
$has_tax = isset( $review_data['taxonomic_fields'] ) && !empty( $review_data['taxonomic_fields'] );
$result = $this->commit_post_fields( $review_data['post_fields'] );
if( ! is_wp_error( $result )){
$review_data['post_fields'] = $result;
$post_id = $review_data['post_fields']['ID'];
if( $has_meta ){
//afg_log( $review_data );
$result = $this->commit_meta_fields( $post_id, $review_data['meta_fields'] );
if( ! is_wp_error( $result )){
$review_data['meta_fields'] = $result;
}
}
if( $has_tax ){
$result = $this->commit_taxonomic_fields( $post_id, $review_data['taxonomic_fields'] );
if( ! is_wp_error( $result )){
$review_data['taxonomic_fields'] = $result;
}
}
if( is_wp_error( $result )){
return $result;
}
return true;
} else {
return $result;
}
}
function commit_post_fields( array $post_data ){
if( isset( $post_data['post_content'] )){
$post_data['post_content'] = addslashes( $post_data['post_content'] );
}
if( isset( $post_data['post_excerpt'] )){
$post_data['post_excerpt'] = addslashes( $post_data['post_excerpt'] );
}
$post_data = apply_filters('afg_review_storage__commit_post_fields', $post_data );
//afg_log(__METHOD__, compact('post_data') );
$post_id = isset( $post_data['ID'] ) ? $post_data['ID'] : null;
//avoid regenerating post_content on every meta update
if( $post_id ){
$result = wp_update_post( $post_data, $wp_error = true );
if( ! is_wp_error( $result )){
//we need new post_id and other fully-escaped values
$inst = WP_Post::get_instance( $post_id );
return $inst->to_array();
}
return $result;
} else {
//do not generate post content on first insert
$was_filtering = remove_filter('wp_insert_post_data', array( $this->meta->renderer, 'build_post_content' ));
$result = wp_insert_post( $post_data, $wp_error = true );
if( $was_filtering ){
add_filter( 'wp_insert_post_data', array( $this->meta->renderer, 'build_post_content'), 10, 2 );
}
if( ! is_wp_error( $result )){
//we need new post_id and other fully-escaped values
$inst = WP_Post::get_instance( $result ); //result will contain post_id value
//afg_log(array('Inserted post'=>$inst->to_array()));
return $inst->to_array();
//echo $wp_error->get_error_message();
} else {
afg_log(array('Could not insert new post' => $result));
}
return $result;
}
}
function commit_meta_fields( $post_id, array $meta_data ){
if( ! $post_id ){
throw new AffiGet_Exception('Parameter post_id cannot be empty!');
}
//avoid regenerating post_content on every meta update
$was_filtering = remove_filter('updated_postmeta', array($this->meta->renderer, 'trigger_build_post_content'));
//it is not safe to pass entire $review_data object, as it's in a transitionary state
//so we pass only meta_data
$meta_data = apply_filters('afg_review_storage__commit_meta_fields', $meta_data, 10 );
foreach( $meta_data as $field_name => $value ){
if( $this->meta->is_meta_field( $field_name ) ){
if( is_string( $value ) ){
if( is_serialized( $value ) ){
$value = unserialize( $value );
} else {
$value = addslashes( $value );
}
}
$meta_key = AFG_META_PREFIX . $field_name; //filter?
//echo ''.$field_name.':'.print_r($value, true).'
'."\n";
update_post_meta( $post_id , $meta_key, $value );
} else {
//echo '';
//print_r($this->meta->known_meta_fields);
throw new AffiGet_Exception('Field ['. $field_name .'] is not considered to be a metafield.');
}
}
if( $was_filtering ){
add_filter( 'updated_postmeta', $this->meta->renderer, 'trigger_build_post_content', 10, 5 );
//trigger content update directly:
wp_update_post( array( 'ID' => $post_id, 'post_type' => $this->meta->post_type_name ));
}
return $meta_data;
}
function commit_taxonomic_fields( $post_id, array $taxonomic_data ){
if( ! $post_id ){
throw new AffiGet_Exception('Parameter post_id cannot be empty!');
}
//it is not safe to pass entire $review object, as it's in a transition state
$taxonomic_data = apply_filters('afg_review_storage__commit_taxonomic_fields', $taxonomic_data );
foreach( $taxonomic_data as $tax => &$terms ){
if( ! empty( $terms ) ){
foreach( $terms as $id => &$term_name ){
//note, $id here is not necessarily term_id, maybe just numeric array index
$term_name = htmlspecialchars( addslashes_gpc( $term_name ));
}
$terms = $this->_maybe_insert_missing_terms( array_values( $terms ), $tax );
}
//now $terms are properly indexed by term_id
$term_ids = null;
if( ! empty( $terms )){
$term_ids = array_keys( $terms );
} else {
//echo 'Taxonomy is empty:'.$tax;
}
$result = wp_set_object_terms( $post_id, $term_ids, $tax, $append = false );
}
return $taxonomic_data;
}
function apply_differences( array $older, array $newer ){
//echo ''.print_r(array('request' => $_REQUEST), true).'';
//echo ''.print_r(array('older' => $older, 'newer' => $newer ), true).'';
$preserve_fields = array( 'ID', 'post_modified', 'post_modified_gmt', 'guid', 'post_type' );
$preserve_fields = apply_filters('afg_review_storage__apply_differences__preserve_fields', $preserve_fields);
$pf = &$older['post_fields'];
$post_id = $pf['ID'];
$changed = false;
foreach( $newer['post_fields'] as $field => $value ){
if( in_array( $field, $preserve_fields ) ){
continue;
}
if( is_array( $value ) || is_object( $value ) || $pf[ $field ] != $value ){
$pf[ $field ] = $value;
$changed = true;
}
}
//commit changed post
if( $changed ){
$result = $this->commit_post_fields( $pf );
if( is_wp_error( $result )){
return $result;
}
$older['post_fields'] = $result;
}
//calculate differences in meta fields
$mod = array();
$mf = &$older['meta_fields'];
foreach( $newer['meta_fields'] as $field => $value ){
if( in_array( $field, $preserve_fields ) ){
continue;
}
if( ! isset( $mf[ $field ] ) || serialize( $mf[ $field ] ) !== serialize( $value ) ){
$mf[ $field ] = $value;
$mod[ $field ] = $value;
}
}
if( ! empty( $mod )){
//update modified meta
$this->commit_meta_fields( $post_id, $mod );
if( is_wp_error( $result )){
return $result;
}
$older['meta_fields'] = $result;
}
//remove deleted meta
//$del = array_diff( $older, $newer );//old fields that are not in the new array
//foreach( $del as $field ){
// if( in_array( $field, $preserve_fields ) ){
// continue;
// }
// delete_post_meta( $post_id, $field );
//}
//calculate differences in taxonomic fields
$tf = &$older['taxonomic_fields'];
$changed = false;
foreach( $newer['taxonomic_fields'] as $field => $value ){
if( in_array( $field, $preserve_fields ) ){
continue;
}
if( isset( $tf[ $field ]) ){
$current = $tf[ $field ];
if( !$current && $value ){
$tf[ $field ] = $value;
$changed = true;
} else {
if( ! isset( $tf[ $field ] ) || serialize( $tf[ $field ] ) != serialize( $value ) ){
$tf[ $field ] = $value;
$changed = true;
}
}
} else {
$tf[ $field ] = $value;
$changed = true;
}
}
//commit taxonomy terms
if( $changed ){
$result = $this->commit_taxonomic_fields( $post_id, $tf );
if( is_wp_error( $result )){
return $result;
}
$older['taxonomic_fields'] = $result;
}
//echo ''.print_r(array('merged' => $older), true).'';
}
/**
*
* @param array $params Must contain post_id, and optionally hard_delete.
* @return mixed status record
*/
public function delete_review( $post_id, $hard_delete = false, $delete_media = false ){
if( ! $post_id ) return false;
if( $delete_media ){
$images = get_children( array (
'post_parent' => $post_id,
'post_type' => 'attachment',
'posts_per_page' => -1,
));
if( ! empty( $images )){
foreach ( $images as $attachment_id => $attachment ) {
wp_delete_attachment( $attachment_id, $hard_delete );
}
}
}
//Deletes comments, post meta fields, and terms associated with the post.
return wp_delete_post( $post_id, $hard_delete );
}
//
//adapted from from get_terms_by()
//
protected function _maybe_insert_missing_terms( $names_or_ids, $taxonomy ) {
global $wpdb;
if( ! taxonomy_exists( $taxonomy ) )
return false;
if( empty( $names_or_ids ))
return false;
//assuming names & ids are already sanitized
$list = "'" . join( "','", $names_or_ids ) . "'";
//afg_log( __METHOD__ .' ('. $taxonomy.') Requested names:', $names_or_ids );
$terms = $wpdb->get_results( $wpdb->prepare( "SELECT t.term_id, t.name FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy = %s AND (t.name IN ( $list ) OR t.term_id IN ( $list ))", $taxonomy ), OBJECT_K );
//echo '
Query results:' . print_r( $terms, true ).'
';
//afg_log( __METHOD__ . ' Retrieved names:', $terms );
$resolved = array();
$new_terms = array();
foreach( $names_or_ids as $n ){
if( is_numeric( $n )){
if( array_key_exists( $n, $terms )){
$resolved[ $n ] = $terms[ $n ]->name;
unset( $terms[ $n ]); //drop it from results to optimize further searches, if any
//continue;
} else {
throw new AffiGet_Exception( 'Unknown term id: '.$n );
}
} else {
$found = false;
foreach( $terms as $term_id => $term ){
if( addslashes_gpc( $n ) == $term->name ){
$found = $term_id;
}
}
if( false !== $found ){
$resolved[ $found ] = $terms[ $found ]->name;
unset( $terms[ $found ]); //drop it from results to optimize further searches, if any
} else {
$new_terms[] = $n;
}
}
}
//echo '
New terms:' . print_r( $new_terms, true );
//afg_log( __METHOD__ . ' New terms:', $terms );
if( ! empty( $new_terms )){
foreach( $new_terms as $term ){
if( $term != '' ){
//afg_log( __METHOD__ . ' Inserting term:', $term );
$inserted = wp_insert_term( $term, $taxonomy );
if( is_wp_error( $inserted ) ){
//echo '';
//print_r( $inserted );
//afg_log( __METHOD__ . " Term '{$term}' could not be inserted into taxonomy '{$taxonomy}'.", $inserted );
//throw new AffiGet_Exception("Term '{$term}' could not be inserted into taxonomy '{$taxonomy}'.");
} else {
$resolved[ $inserted['term_id'] ] = $term;
//afg_log( __METHOD__ . " Term inserted: ", array( $inserted['term_id'], $resolved[ $inserted['term_id'] ] ));
}
}
}
}
//afg_log(__METHOD__ . ' Resolved terms:', $resolved );
return $resolved;
}
}