This is a bit of a two fold question. I’ve an ajax request that polles for duplicate post titles, but it’s getting thrown by different quote/apostrophes and their variants, returning negative when I know there is a duplicate.
I have a post titled: “Benâs Big Fish” ie with the apostrophe (’)
But doing a query for the following always comes back negative:
Ben's Big Fish (')
Benâs Big Fish (’)
Bens Big Fish (no apos)
However a query for Big Fish
returns all the variant posts titles with these words in it, including post titles with quotes and apostrophes in them.
Here are the main characters that are also causing issue:
Apostrophe ' '
Open single quote â ‘
Close single quote â ’
---
Quotation mark " "
Open double quotes â “
Close double quotes â ”
As users are often pulling text from MS Word docs etc, these characters are coming up a lot.
On the js end I encode the post title by passing it through this function before sending it via json to my ajax handler:
function htmlEntities(str) {
return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/â/g, '‘').replace(/â/g, '’').replace(/â/g, '“').replace(/â/g, '”');
}
In my php ajax hook I’m treating the incoming POST query as follows:
global $wpdb;
// Grab details from inbound POST array & prepare for sql
$title = html_entity_decode($_POST['post_title']); //first un-encode
$post_id = $_POST['post_id'];
$sim_query = "SELECT ID FROM $wpdb->posts WHERE post_status = 'publish' AND post_title LIKE '%%%s%%' AND ID != '%d'";
$sim_results = $wpdb->get_results( $wpdb->prepare( $sim_query, $wpdb->esc_like($title), $post_id ) );
if ($sim_results)
{ // Send the results back as json }
So my question is
a) how to get the query to return the obvious duplicates as expected
b) and possibly related, there a way we can efficiently search through strings that look for all variants the appearance of apostrophe and quotation characters without multiple queries?
The crux of the problem actually fell back to the original encoding from JS. One of the key characters that was tripping us up:
'
, is not actually decoded byhtml_entity_decode
, even with theENT_QUOTES
flag set. Instead it expects'
.So in the end our js looks like:
and we decode in PHP:
Its also important to note that SQL, will balk at single quotes, and apostrophes. It requires that they be escaped by doubling them like so:
''
. WordPress takes care of the escaping for us when we use its SQL escaping class$wpdb->prepare