I'm creating a plugin for a friend to log search terms on his site. It's very basic. It creates a new table to store terms entered in the search box. It converts the search term to lower case, checks the database for a matching term and either inserts the term into the database or increases the count of a matching term. It was working as expected on my hosting account. Then I installed it on a WP install on a GoDaddy hosting account...
As long as I'm logged in it seems to work whether or not there is a matching term in the database. When I search the site as a guest, it will add a new unique search term to the database but if there is an existing term it does nothing. Well, that's not entirely true. I've seen it increase the count a few times but not by 1, by 2. It seems to function very sporadically on GoDaddy. I can't make sense of this. The actual plugin can be found here.
I appreciate any time spent looking at this.
Thanks
// Register function to be called when plugin is activated
register_activation_hook( __FILE__, 'mac_search_log_activation' );
function mac_search_log_activation(){
global $wpdb;
$prefix = $wpdb->prefix;
$creation_query =
'CREATE TABLE ' . $prefix . 'mac_search_log (
`id` mediumint(8) NOT NULL AUTO_INCREMENT,
`full_search_term` text NOT NULL,
`count` mediumint(8) NOT NULL,
PRIMARY KEY (`id`)
);';
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
dbDelta( $creation_query );
}
// Register function to be called when administration pages init takes place
add_action( 'admin_init', 'mac_search_log_admin_init' );
function mac_search_log_admin_init(){
add_action('admin_post_delete_mac_search_log_term', 'delete_mac_search_log_term');
}
// Register function to be called when admin menu is constructed
add_action( 'admin_menu', 'mac_search_log_settings_menu' );
// Add new menu item for Search Term History
function mac_search_log_settings_menu() {
add_menu_page( 'Search Term History',
'Search Term History', 'manage_options',
'search-term-history',
'mac_search_log_config_page',
null,
4.7);
}
// Function to render plugin admin page
function mac_search_log_config_page() {
global $wpdb;
?>
<!-- Top-level menu -->
<div id="mac_search_log-general" class="wrap">
<h2>Searched Terms</h2>
<form method="post"
action="<?php echo admin_url( 'admin-post.php' ); ?>">
<input type="hidden" name="action" value="delete_mac_search_log_term" />
<?php wp_nonce_field( 'mac_search_log_term_deletion' ); ?>
<?php
$term_query = 'select * from ';
$term_query .= $wpdb->prefix;
$term_query .= 'mac_search_log ORDER by count DESC';
$term_items = $wpdb->get_results( $wpdb->prepare( $term_query ), ARRAY_A );
?>
<table class="wp-list-table widefat fixed" >
<thead><tr>
<th style="width: 50px">Delete</th><th style="width: 300px">Search Term</th><th>Count</th></tr></thead>
<?php
// Display search terms if query returned results
if ( $term_items ) {
foreach ( $term_items as $term_item ) {
echo '<tr style="background: #FFF">';
echo '<td><input type="checkbox" name="terms[]" value="';
echo esc_attr( $term_item['id'] ) . '" /></td>';
echo '<td>' . $term_item['full_search_term'] . '</td>';;
echo '<td>' . $term_item['count'] . '</td></tr>';
}
} else {
echo '<tr style="background: #FFF">';
echo '<td colspan=4>No Searches Yet</td></tr>';
}
?>
</table><br />
<input type="submit" value="Delete Selected"
class="button-primary"/>
</form>
</div>
<?php }
add_filter('pre_get_posts','MACSearchLog');
function MACSearchLog($query) {
if ($query->is_search) {
global $wpdb;
$term = strtolower($query->query_vars['s']);
$term_query = 'select * from ';
$term_query .= $wpdb->prefix;
$term_query .= 'mac_search_log';
$term_query .= ' WHERE full_search_term = "'.$term.'"';
$term_items = $wpdb->get_row( $wpdb->prepare( $term_query ), ARRAY_A );
if(empty($term_items)){
// insert term and set count to 1
$term_item = array(
'full_search_term' => $term,
'count' => 1
);
$wpdb->insert($wpdb->prefix.'mac_search_log', $term_item);
}else{
// update existing row count++
$new_query = 'UPDATE ';
$new_query .= $wpdb->prefix;
$new_query .= 'mac_search_log';
$new_query .= ' SET count = count+1 ';
$new_query .= 'WHERE id = '.$term_items['id'];
$wpdb->query($wpdb->prepare($new_query));
}
}
}
function delete_mac_search_log_term(){
$deleted_terms = array();
// Check that user has proper security level
if ( !current_user_can( 'manage_options' ) )
wp_die( 'Not allowed' );
// Check if nonce field is present
check_admin_referer( 'mac_search_log_term_deletion' );
// If search terms are present, cycle through array and call SQL
// command to delete entries one by one
if ( !empty( $_POST['terms'] ) ) {
// Retrieve array of search term IDs to be deleted
$terms_to_delete = $_POST['terms'];
global $wpdb;
foreach ( $terms_to_delete as $term_to_delete ) {
$deleted_terms[] = get_search_term_by_id(intval($term_to_delete));// TO GET SEARCH TERMS FOR EMAIL
$query = 'DELETE from ' . $wpdb->prefix;
$query .= 'mac_search_log ';
$query .= 'WHERE id = ' .
intval( $term_to_delete );
$wpdb->query( $wpdb->prepare( $query ) );
}
}
// UNCOMMENT THE FOLLOWING 2 LINES TO DISPATCH EMAIL WITH DELETED SEARCH TERMS
// $terms = print_r($deleted_terms, true);
// wp_mail( get_option('admin_email'), 'Search Terms Deleted', $terms);
// Reload the search term history page
wp_redirect( add_query_arg( 'page', 'search-term-history',
admin_url( 'admin.php' ) ) );
exit;
}
function get_search_term_by_id($id){
global $wpdb;
$term_query = 'select * from ';
$term_query .= $wpdb->prefix;
$term_query .= 'mac_search_log ';
$term_query .= 'WHERE `id` = '.$id;
$term_item = $wpdb->get_row( $wpdb->prepare( $term_query ), OBJECT );
if($term_item){
return $term_item->full_search_term;
}else{
return null;
}
}
Edit: I've been logging queries and everything else involved. Nothing looks off. I replaced the SQL query with $wpdb->update() and replaced if(empty($term_items)){
with if($term_items)
while swapping the associated actions, and that seems to have cleared up some of the anomolies with the count, but it just will not update on the GoDaddy account unless I am logged in. On one hand I find it hard to believe that a different hosting account would have an effect on this, but I've seen stranger things from GoDaddy in the past.
prepare
isn't being used correctly. it's probably not a reason things would be misbehaving, but it's definitely something that should be fixed. see this post for an explanation.printf()
I made that change and now on GoDaddy it will update once when searching as a guest, but does nothing after the first update. Still works as expected on HostGator. Guess this is one step closer to solving the problem.prepare()
. If I change the first query in the above code to use %s for table name then use->prepare($term_query, $table_name)
it puts backticks around the table name and I get no results. Any idea why that would be? If I include the table name in the query and use->prepare($term_query)
there are no backticks around the table name and it returns all my rows.