Skip to content

Instantly share code, notes, and snippets.

@Magnacarter
Last active June 15, 2020 16:02
Show Gist options
  • Save Magnacarter/b7d0741bf806cad2c0df40e51d3039fe to your computer and use it in GitHub Desktop.
Save Magnacarter/b7d0741bf806cad2c0df40e51d3039fe to your computer and use it in GitHub Desktop.
<?php
/**
* Load the Placement API class
* These methods can be used to interact with
* the peta_placements db table
*
* @package PETA\Placement_Plugin\inc
* @since 4.0.0
* @author adamc
* @licence GNU-2.0+
*/
namespace PETA\Plugin_Placement;
use PETA_Placement_Plugin;
use WP_Query;
/**
* Class Placement API
*/
class Placement_API extends Custom_Tables {
/**
* @var int
*/
protected $placement_id;
/**
* Hold instance of plugin's utility class
* @var object
*/
protected $plugin;
/**
* @var string
*/
protected $placement_name;
/**
* @var string
*/
protected $placement_url;
/**
* @var string
*/
protected $pos_order_number;
/**
* @var string
*/
public $table_name;
/**
* Placement_API Constructor
*/
public function __construct() {
parent::__construct();
add_action( 'pre_get_posts', array( $this, 'exclude_suppress_from_search' ), 1 );
}
/**
* Set our variables
*
* @since 4.0.0
* @author adamc
*
* @return void
*/
public function init( $placement_id ) {
// All our setters
$this->set_placement_id( $placement_id );
$this->set_pos_order_number( $placement_id );
$this->set_placement_url( $placement_id );
}
/**
* Set menu id
* Get the menu id from the GET query
*
* @since 3.0.0
* @return void
*/
public function set_placement_id( $placement_id = null ) {
$this->placement_id = $placement_id;
}
/**
* Set pos order number
*
* @since 4.0.0
* @author adamc
*
* @return void
*/
public function set_pos_order_number( $placement_id ) {
$this->pos_order_number = 'pos_order_' . $placement_id;
}
/**
* Set placement name and url
*
* @since 4.0.0
* @author acarter
*
* @return void
*/
public function set_placement_url( $placement_id ) {
$this->placement_url = untrailingslashit( get_admin_url() ) . '?page=placements&action=manage&mid=' . $placement_id;
}
/**
* Get placement id
*
* @since 4.0.0
* @author adamc
*
* @return int
*/
public function get_placement_id() {
return $this->placement_id;
}
/**
* Get pos order number
*
* @since 4.0.0
* @author adamc
*
* @return string
*/
public function get_pos_order_number() {
return $this->pos_order_number;
}
/**
* Get placement url
*
* @since 4.0.0
* @author adamc
*
* @return string
*/
public function get_placement_url() {
return $this->placement_url;
}
/**
* Get placement name
*
* @since 4.0.0
* @author acarter
*
* @param int $placement_id
* @return string $result
*/
public function get_placement_name( $placement_id ) {
global $wpdb;
$table_name = $this->get_placement_table_name();
$result = $wpdb->get_var( "SELECT placement_name FROM $table_name WHERE placement_id = $placement_id" );
return $result;
}
/**
* Get placement categories
*
* @since 4.0.0
* @author acarter
*
* @param int $placement_id
* @return array $result
*/
public function get_placement_categories( $placement_id = '' ) {
if ( ! empty( $placement_id ) ) {
global $wpdb;
$table_name = $this->get_placement_table_name();
$result = $wpdb->get_var( "SELECT categories FROM $table_name WHERE placement_id = $placement_id" );
return json_decode( $result, true );
}
}
/**
* Get placement post_types
*
* @since 4.0.0
* @author acarter
*
* @param int
* @return array $result
*/
public function get_placement_post_types( $placement_id = '' ) {
if ( ! empty( $placement_id ) ) {
global $wpdb;
$table_name = $this->get_placement_table_name();
$result = $wpdb->get_var( "SELECT post_types FROM $table_name WHERE placement_id = $placement_id" );
return json_decode( $result, true );
}
}
/**
* Get placement psa type
*
* @since 4.0.0
* @author acarter
*
* @param int $placement_id
* @return array $result
*/
public function get_placement_taxonomies( $placement_id = '' ) {
if ( ! empty( $placement_id ) ) {
global $wpdb;
$table_name = $this->get_placement_table_name();
$result = $wpdb->get_var( "SELECT taxonomies FROM $table_name WHERE placement_id = $placement_id" );
return json_decode( $result, true );
}
}
/**
* Generate a new placement id for peta_placements table
*
* @since 4.0.0
* @author acarter
*
* @return int
*/
public function get_new_placement_id() {
global $wpdb;
$table_name = $this->get_placement_table_name();
$id = $wpdb->get_var( "SELECT placement_id FROM $table_name ORDER BY placement_id DESC limit 0,1" );
return $id + 1;
}
/**
* Return all placements
*
*
* @return array $placements
*/
public function get_placement_list() {
global $wpdb;
$table_name = $this->get_placement_table_name();
$placements = $wpdb->get_results( "SELECT placement_name, placement_id, placement_url FROM $table_name", ARRAY_A );
return $placements;
}
/**
* Get single post position
* Return the post published time if post is not in the top 40 placements positions
*
* @since 4.0.0
* @author acarter
*
* @param int $post_id
* @return int $position
*/
public function get_single_post_position( $post_id, $placement_id ) {
$order = $this->get_placement_order( $placement_id );
if ( isset( $order ) ) {
foreach ( $order as $arr ) {
if ( $_GET['paged'] > 1 && $arr['post_id'] == $post_id ) {
return false;
}
if ( $arr['post_id'] == $post_id ) {
$position = $arr['position'];
break;
}
}
}
if ( isset( $position ) ) {
return $position;
} else {
return get_the_time( 'Y-m-d', $post_id );
}
}
/**
* Get placement order
* Return array of post ids that contain each ones' placement position,
* then decode the json object
*
* @since 4.0.0
* @author acarter
*
* @param int $placement_id
* @return array
*/
public function get_placement_order( $placement_id ) {
global $wpdb;
$table_name = $this->table_name;
$entries = $wpdb->get_var( $wpdb->prepare(
"
SELECT placement_order
FROM $table_name
WHERE placement_id = %d
",
$placement_id
));
// Convert the stdObject to an array
$placement_order = json_decode( $entries, true );
return $placement_order;
}
/**
* Calculate the offset needed for the top 40 posts.
*
* @since 4.0.0
* @author adamc
*
* @param array $top_forty
* @param int $offset
* @param int $total
* @return array $entries
*/
public function adjust_top_40_offset( $top_forty_posts, $offset, $total ) {
// Put top 40 order posts into the array.
foreach ( $top_forty_posts as $pos ) {
$found_posts[] = $pos['post_id'];
}
// Offset the top 40 array.
$i = 1;
$j = 1;
foreach ( $found_posts as $key => $value ) {
if ( 0 !== $offset ) {
if ( $i <= $offset ) {
$i++;
continue;
}
}
if ( $j <= $total ) {
$entries[] = $value;
}
$j++;
}
return $entries;
}
/**
* Returns placement post ids starting with
* top 40 placements then moving to posts outside the saved top 40.
*
* @since 4.0.0
* @author adamc
*
* @param string $name
* @param int $total
* @param int $offset
* @return array $entries
*/
public function get_placement_posts( $name, $total = 5, $offset = 0 ) {
$placement_id = $this->plugin->get_placement_id_from_name( $name );
$order = $this->get_placement_order( $placement_id );
$order_count = count( $order );
$settings = $this->get_placement_settings( $placement_id );
// Use the top forty array as a post not in arg for the wp_query later.
foreach ( $order as $arr ) {
$post_not_in[] = $arr['post_id'];
}
$top_forty_posts = $order;
$entries = $this->adjust_top_40_offset( $top_forty_posts, $offset, $total );
// If the entries are less than the total, start using placement posts outside the top 40.
if ( count( $entries ) < $total ) {
$adjust_total = $total - count( $entries );
$query = $this->get_placement_wp_query( $settings, ' ', $adjust_total, 0, $post_not_in );
$post_ids = wp_list_pluck( $query->posts, 'ID' );
}
// If there are no more top 40 posts, use the other placement posts.
if ( 0 == count( $entries ) ) {
$adjust_offset = $offset - $order_count;
$query = $this->get_placement_wp_query( $settings, ' ', $total, $adjust_offset, $post_not_in );
$post_ids = wp_list_pluck( $query->posts, 'ID' );
}
// Put wp_query posts in the array if they are not in the top 40.
if ( isset( $post_ids ) ) {
foreach ( $post_ids as $p_id ) {
$entries[] = $p_id;
}
}
return $entries;
}
/**
* Return the total number of posts for a placement.
* This includes the top 40 and all posts that fit into a placement's settings.
*
* @since 4.0.0
* @author adamc
*
* @param string $name
* @return int $total_records
*/
public function get_total_placement_records( $name ) {
$placement_id = $this->plugin->get_placement_id_from_name( $name );
$placement_settings = $this->get_placement_settings( $placement_id );
$query = $this->get_placement_wp_query( $placement_settings );
$total_records = $query->found_posts;
return $total_records;
}
/**
* Put together an array to save placement order row in the custom peta-placements db table
*
* @since 4.0.0
* @author acarter
*
* @param int $placement_id
* @param string $pos_order_number
* @param string $placement_name
* @param string $placement_url
* @param array $placement_order
* @return void
*/
public function get_placement_args( $placement_id, $pos_order_number, $placement_name, $placement_url, $placement_order ) {
$last_update = date( 'Y-m-d h:i:sa' );
$placement_order = wp_json_encode( $placement_order );
$args = array(
'placement_id' => $placement_id,
'pos_order_number' => $pos_order_number,
'placement_name' => $placement_name,
'placement_order' => $placement_order,
'last_update' => $last_update,
'placement_url' => $placement_url,
);
return $args;
}
/**
* Get the current placement settings
*
* @author adamc
* @since 4.0.0
*
* @param int $placement_id
* @return array $placement_settings
*/
public function get_placement_settings( $placement_id ) {
if ( empty( $placement_id ) ) {
return;
}
$placement_settings['menu_label'] = $this->get_placement_name( $placement_id );
$placement_settings['categories'] = $this->get_placement_categories( $placement_id );
$placement_settings['post_types'] = $this->get_placement_post_types( $placement_id );
$placement_settings['taxonomies'] = $this->get_placement_taxonomies( $placement_id );
return $placement_settings;
}
/**
* Start the save process
*
* @since 4.0.0
* @author acarter
*
* @param string $placement_id
* @param array $order
* @return array $response
*/
public function init_save_placement( $placement_id, $order, $args = array() ) {
$this->init( $placement_id );
// Run the setters and save order to peta_placements
$pos_order_num = $this->get_pos_order_number();
$placement_name = $this->get_placement_name( $placement_id );
$url = $this->get_placement_url();
if ( empty( $args ) ) {
// Setup the args to send it to the db.
$args = $this->get_placement_args( $placement_id, $pos_order_num, $placement_name, $url, $order );
$response = $this->save_placement( $args );
} else {
$meta['pos_order_number'] = $pos_order_num;
$meta['placement_name'] = $placement_name;
$meta['placement_url'] = $url;
$meta['last_update'] = date( 'Y-m-d h:i:sa' );
$new_placement = array_merge( $meta, $args );
$response = $this->save_placement( $new_placement );
}
return $response;
}
/**
* Save placement
* Save to our peta_placements table
* Returns the args array so you can place it in your ajax response in save_placement_order()
* in class-placement-hooks.php for debugging.
*
* @since 4.0.0
* @author acarter
*
* @param array $args
* @param string $table_name
* @return array $args
*/
public function save_placement( $args, $table_name = null ) {
global $wpdb;
if ( ! isset( $table_name ) ) {
$table_name = $this->get_placement_table_name();
}
$placement_id = $args['placement_id'];
$db_id = $wpdb->get_var( "SELECT placement_id FROM $table_name WHERE placement_id= $placement_id" );
if ( NULL === $db_id ) {
$wpdb->insert( $table_name, $args );
} else {
$wpdb->update( $table_name, $args, array( 'placement_id' => $db_id ) );
}
$args['placement_url'] = $wpdb->get_var( "SELECT placement_url FROM $table_name WHERE placement_id = $placement_id" );
return $args;
}
/**
* Delete top forty posts
* Delete the top forty posts by entering a null value
*
* @since 4.0.0
* @author adamc
*
* @param int $placement_id
* @return void
*/
public function delete_top_forty_posts( $placement_id ) {
$this->init_save_placement( $placement_id, $order = null );
}
/**
* Exclude supress from search.
*
* @since 4.0
* @param object $query
* @return void
*/
public function exclude_suppress_from_search( $query ) {
if ( ! $query->is_search ) {
return $query;
}
if ( is_admin() ) {
$tax_query = array(
array(
'taxonomy' => 'placement',
'field' => 'slug',
'terms' => 'suppress-from-search-results',
'operator' => 'NOT IN',
),
);
$query->set( 'tax_query', $tax_query );
} else {
$tax_query = array(
array(
'taxonomy' => 'placement',
'field' => 'slug',
'terms' => 'suppress-from-search-results-external',
'operator' => 'NOT IN',
),
);
$query->set( 'tax_query', $tax_query );
}
}
/**
* Get a new wp_query based on a placement's settings.
* Build an agrs array for wp_query dynamically
*
* @author adamc
* @since 4.0.0
*
* @param array $placment_settings
* @param string $search_term
* @param int $post_count
* @param int $offset
* @param array $post_not_in
* @return object $query
*/
public function get_placement_wp_query( $placement_settings, $search_term = '', $post_count = 40, $offset = 0, $post_not_in = null ) {
$args['posts_per_page'] = $post_count;
$args['paged'] = $_GET['paged'];
$args['post_status'] = 'publish';
if ( null !== $post_not_in ) {
$args['post__not_in'] = $post_not_in;
}
if ( $offset > 0 ) {
$args['offset'] = $offset;
}
if ( ! empty( $search_term ) ) {
$args['s'] = $search_term;
}
/**
* Put pts into an array.
* No empty check because posts will always have a post type
*/
foreach ( $placement_settings['post_types'] as $k => $pt ) {
$args['post_type'][] .= $pt;
}
// Put cats into array
if ( ! empty( $placement_settings['categories'] ) ) {
foreach ( $placement_settings['categories'] as $index => $cat ) {
$args['category__in'][] .= $cat;
}
}
// Put taxonomy terms into an array
if ( ! empty( $placement_settings['taxonomies'] ) ) {
// Find out if there is more than one taxonomy to add
$i = 0;
foreach ( $placement_settings['taxonomies'] as $tax_name => $term_ids ) {
if ( ! empty( $tax_name ) ) {
$i++;
}
}
/**
* If there's more than one tax in the placement,
* make sure to add the OR relationship to see if any posts
* have that term.
*/
if ( $i > 1 ) {
$args['tax_query']['relation'] = 'OR';
}
// Build the taxonomy array
$j = 0;
foreach ( $placement_settings['taxonomies'] as $key => $tax ) {
if ( isset( $tax ) ) {
$tax_query[ $j ] = array( 'taxonomy' => str_replace( '_', '-', $key ), 'field' => 'term_id' );
foreach ( $tax as $index => $term_id ) {
$tax_query[ $j ]['terms'] .= $term_id;
}
}
$j++;
}
}
$args['tax_query'] = $tax_query;
$args['suppress_filters'] = false;
$query = new WP_Query( $args );
return $query;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment