How to add an AJAX function / URL to WordPress

Put this function in your theme’s functions.php (or even better, in an ajax.php file in the theme that is require’d in):

/* The function ajax_read_more() will be called when the following URL is requested
 * from WordPress:
 *
 * http://www.yoursite.com/wp-admin/admin-ajax.php?action=read_more&limit=5
 */
function ajax_read_more() {
    // Take in a few input parameters from $_GET or $_POST (depending on how you're passing the values) about
    // what data to retrieve and display.
    $num_limit = (int) $_POST['limit'];
    $str_category_name = filter_var($_POST['category_name'], FILTER_SANITIZE_STRING);
  
    // Call some built-in WordPress functions just to demonstrate that we can.
    $user_id = get_current_user_id();
  
    // Now let's return some JSON data to whatever called this URL (we can return HTML, XML or whatever else too,
    // just make sure to set the appropriate Content-Type header).
    $arr_sample_data = array('key' => 'value');
    echo json_encode($arr_sample_data);
    exit; // You must use exit to end an AJAX function in WordPress, or it'll append a 0 to the output.
}
add_action( 'wp_ajax_read_more', 'ajax_read_more' ); // This action exposes the AJAX action "read_more" to logged-in WordPress users.
add_action( 'wp_ajax_nopriv_read_more', 'ajax_read_more' ); // This action exposes the AJAX action "read_more" to anonymous (not logged in) WordPress users.

Then all you need to do is write a jQuery or even just a regular HTML form that submits a request to your new AJAX URL:

jQuery.ajax({
    type: 'get',
    url: '/wp-admin/admin-ajax.php?action=read_more&limit=5',
    dataType: 'json'
})
.done( function( response ) {
    console.log(response);
});

One last thing – visit your WordPress site’s Permalinks page in order to rebuild the list of URLs WordPress will respond to. This will make your new URL (for the AJAX function) active.

Forcing images to conform to a 16:9 aspect ratio

In the Bootstrap front-end framework, you can add the classes embed-responsive embed-responsive-16by9 or embed-responsive embed-responsive-4by3 on a DIV that wraps an IFRAME, EMBED or OBJECT element to ensure that video players always conform to a 16:9 aspect ratio on your responsive website (more info).

But what about images? In cases where content has been migrated onto a WordPress site, re-creating all thumbnails in the proper aspect ratio may just not be doable – or you may simply not have the controls in place to ensure that all images are of the correct aspect ratio. Luckily there appears to be a trick in CSS that can force aspect ratios. To get it to work, you’ll need to write CSS for a DIV that wraps the actual IMG tag like so:

.img-responsive-16by9 {
    display: block;
    height: 0;
    padding-bottom: 56.25%;
    overflow: hidden;
}

That’ll force the image output with the HTML illustrated below to respect a 16:9 aspect ratio:

<div class="img-responsive-16by9">
    <img src="http://www.570news.com/wp-content/blogs.dir/sites/3/2015/04/1429827607_NSD502266764_low.jpg">
</div>

Regular expressions: Greedy regex versus lazy regex

Here’s a typical regex scenario: You’ve got a string in which you need to find/capture the HTML tags from. Let’s say our string is:

This is a <em>first</em> test

Typically, you’d write a regular expression to capture the tag by writing this:

var re = new RegExp("<(.+)>", "");

Unexpectedly, however, the result you’re going to get matched back is:

"em>first</em"

The reason for this is explained on the Regex Tutorial website:

The first token in the regex is . You should see the problem by now. The dot matches the >, and the engine continues repeating the dot. The dot will match all remaining characters in the string. The dot fails when the engine has reached the void after the end of the string. Only at this point does the regex engine continue with the next token: >.

What we need to do instead is force the dot character to be lazy by adding a question mark after the plus sign (or a star, or numbers in curly braces):

var re = new RegExp("<(.+?)>", "");

This time, we’ll get back:

"em"

Reference: Regex Tutorial – Repetition with Star and Plus

When “compass compile” leads to an ‘Invalid UTF-8 character “\xCA”‘ error

We’ve got some pretty large CSS files to work with on a few projects I work on, and use SCSS plus the Compass tool to make management of the styles a bit easier. Recently, though, Compass has been throwing us this error:

    error scss/sportsnet.scss (Line 969 of scss/_inc-controls.scss: Invalid UTF-8 character "\xCA")

The root cause appears to be non-ASCII characters in a SCSS file. That’s easy enough to root out by hand if the file is a manageable size, but if you need an automated filter instead, try the following:

iconv -t ASCII//IGNORE -f UTF8 < _inc-controls.scss > _inc-controls.ascii

This pipes the offending SCSS file through iconv, and spits out the file _inc-controls.ascii which should contain differing lines where non-ASCII lines are found.

Overwriting a branch in Git with remote results (and bypassing merge conflicts)

If you’ve ever tried to do a git pull to get a branch up to date and have run into conflicts that you just want to bypass and go with the contents of the remote branch, do the following:

# Fetch from the default remote of origin.
git fetch origin
# Check out the branch you want to override the conflicts upon.
git checkout master
# Reset your current branch of master to origin's master.
git reset --hard origin/master

Reference: Stack Overflow: Git pull from remote.. Can I force it to overwrite rather than report conflicts?

Get a list of files added, removed and modified in Git between two branches

It’s sometimes useful to know exactly what files you’ve made changes to in your feature branch as you’re getting ready to merge back into your trunk code. Git’s diff option allows for this to be done quick easily:

git diff --name-status master..newfeature

The output looks like the following:

M       .gitmodules
A       plugins/backplane.php
A       plugins/multiple-post-thumbnails
M       themes/sportsnet/css/scss/_inc-controls.scss
M       themes/sportsnet/functions.php
M       themes/sportsnet/header.php
M       themes/sportsnet/single-sn-article.php
M       themes/sportsnet/single-sn-blog-entry.php
M       themes/sportsnet/single-sn-signing.php
M       themes/sportsnet/single-sn-trade.php
A       themes/sportsnet/zones/articles-comment-form.php
A       themes/sportsnet/zones/global/user-account-links.php
(END)

Reference: Stack Overflow – Showing which files have changed between git branches

Checking Akamai cache expiry times on your website’s pages

This involves sending some custom headers along with your HTTP GET request, so utilize either the wget command line tool:

wget -S -O /dev/null --header="Pragma: akamai-x-cache-on, akamai-x-cache-remote-on, akamai-x-check-cacheable, akamai-x-get-cache-key, akamai-x-get-extracted-values, akamai-x-get-nonces, akamai-x-get-ssl-client-session-id, akamai-x-get-true-cache-key, akamai-x-serial-no" http://www.sportsnet.ca/

Or the curl command line tool:

curl -H "Pragma: akamai-x-cache-on, akamai-x-cache-remote-on, akamai-x-check-cacheable, akamai-x-get-cache-key, akamai-x-get-extracted-values, akamai-x-get-nonces, akamai-x-get-ssl-client-session-id, akamai-x-get-true-cache-key, akamai-x-serial-no" -IXGET http://www.sportsnet.ca/

The X-Cache-Key setting will contain the amount of time the URL is cached for; in this example, the time is 1 minute (“1m”):

X-Cache-Key: /L/370/77322/1m/www.sportsnet.ca/

Running Windows? No problem – grab a compiled version of wget for Windows.

Source: Stack Overflow – What’s the best way to troubleshoot Akamai headers these days?

Selectively taking commits out of a GitHub pull request

Once in a while it’s necessary to get picky and only accept one or more commits from a bundle sent over in a GitHub pull request – or maybe someone’s been working on a fork of a repository of yours and you want to pull a change or two in. The git command cherry-pick is there for this purpose.

To start, you’ll need to run git fetch on the forked repository:

git fetch [email protected]:hakimel/Fokus.git

Next, take the hash of the commit you want to retrieve files for and run the cherry-pick command on it:

git cherry-pick 00988a520bda3e365c74033a44a96941d77be86f

That should do it! Check your git log to see the commit pulled into your repository.

Source: StackOverflow – Pull in changes from a Github fork

Profiling a MySQL query to optimize performance

The Query Profiler in MySQL isn’t something I’ve spent much time in recently – with more sites making use of popular CMSes like WordPress, query performance isn’t something that’s top of mind anymore (Automatic seems to do a good job in this area). But it’s still a useful tool when you’ve already picked the low hanging fruit off of the optimization tree.

Profiling is enabled on an individual basis for each MySQL session; when the session ends, all profiling information is lost.

To check to see if profiling is currently enabled for your session, do:

mysql> SELECT @@profiling;
+-------------+
| @@profiling |
+-------------+
|           0 |
+-------------+
1 row in set (0.00 sec)

Next, enable profiling for all queries:

mysql> SET profiling = 1;
Query OK, 0 rows affected (0.00 sec)

And run the query you’d like to see a breakdown for:

mysql> SELECT COUNT(*) FROM wp_posts;
+----------+
| count(*) |
+----------+
|   238121 |
+----------+
1 row in set (18.80 sec)

Get the numeric ID of the profile we want to see:

mysql> SHOW PROFILES;
+----------+----------+---------------------------------------+
| Query_ID | Duration | Query                                 |
+----------+----------+---------------------------------------+
|        1 | 18.80000 | SELECT COUNT(*) FROM wp_posts;        |
+----------+----------+---------------------------------------+
1 row in set (0.00 sec)

Finally, actually see the query profiled:

mysql> SHOW PROFILE FOR QUERY 1;
+--------------------------------+-----------+
| Status                         | Duration  |
+--------------------------------+-----------+
| starting                       |  0.000027 |
| checking query cache for query |  0.000041 |
| checking permissions           |  0.000017 |
| Opening tables                 |  0.000018 |
| System lock                    |  0.000008 |
| Table lock                     |  0.000037 |
| init                           |  0.000014 |
| optimizing                     |  0.000008 |
| statistics                     |  0.000016 |
| preparing                      |  0.000013 |
| executing                      |  0.000008 |
| Sending data                   | 18.802902 |
| end                            |  0.000015 |
| end                            |  0.000008 |
| query end                      |  0.000006 |
| storing result in query cache  |  0.000453 |
| freeing items                  |  0.000009 |
| closing tables                 |  0.000007 |
| logging slow query             |  0.000007 |
| logging slow query             |  0.000031 |
| cleaning up                    |  0.000005 |
+--------------------------------+-----------+
21 rows in set (0.00 sec)

To get even more in depth, check out the optional type values for the SHOW PROFILE command, or use SHOW PROFILE ALL FOR QUERY 1; and view everything MySQL’s got at once.

Very basic JSONP

JSONP allows you to make HTTP requests outside of your own domain due to the SCRIPT tag not having the same-domain limitation XMLHttpRequest does. The basic form of this workaround is as follows:

var scr = document.createElement('script');
scr.src = 'http://openexchangerates.org/latest.json?callback=formatCurrency';
document.body.appendChild(scr);

function formatCurrency(data) {
	// Do stuff with the data that's been returned.
	1;
}

Lines 1 – 3 of the above create a SCRIPT tag in the DOM, defines the URL to retrieve data from and in line 3 makes the request. To continue the execution cycle, the script at openexchangerates.org must wrap its data in a function:

formatCurrency({ "hello" : "Hi, I'm JSON. Who are you?"})

This calls the locally defined function formatCurrency(), which does whatever it needs to do with the returned data. A quick hack to make your API (assuming you control it) work with JSONP would be as follows:

// assume $json holds the JSON response
if ($GET['callback'] != '') $json = $GET['callback']."( $json )";
return $json;

I have yet to test this, but I imagine you could also be much more daring and avoid having to get the following code uploaded to your API of choice. To do this, execute the first bit of JavaScript on this page, and then execute an eval() statement on the data in the manner of the below:

eval('formatCurrency(' + returned_data + ')');