Skip to content

Instantly share code, notes, and snippets.

@Grezvany13
Last active January 12, 2016 20:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Grezvany13/35384a7855d544c7fed7 to your computer and use it in GitHub Desktop.
Save Grezvany13/35384a7855d544c7fed7 to your computer and use it in GitHub Desktop.
WordPress Cron handler with multisite support
<?php
/**
* WP Cron Multi
*
* A simple script which can be executed through the command line (or crontab)
* to run wp_cron for multisite (or not) without the use of wget, wp_remote or cURL.
*
* It has a 'copy' of wp-cron.php to run the transients.
*
* @author Johan de Jong <johan@notitia.nl>
* @version 1.0
* @package WordPress
*/
ignore_user_abort(true);
$opts = getopt('', [
"url::",
"wp::",
"help"
]);
// display help settings
if (isset($opts['help']) || empty($opts)) {
echo "\n";
echo "\033[0;33mUsage:\033[0m\n";
echo " php wp-cron-multi.php <options>\n";
echo "\n";
echo "\033[0;33mOptions:\033[0m\n";
echo " \033[0;32m--help\033[0m This help\n";
echo " \033[0;32m--url=<base_url>\033[0m Network domain\n";
echo " The base URL is required to run the cronjob.\n";
echo " It MUST match the domain of the website, or\n";
echo " the network domain of a multisite.\n";
echo " \033[0;32m--wp=<wp_path>\033[0m Path to WP directory\n";
echo " If the location of wp-load.php is different\n";
echo " from the current location, set the relative\n";
echo " path with a trailing slash.\n";
echo "\n";
exit;
}
// set URL argument
// useful if wp-config.php uses $_SERVER['HTTP_HOST']
// required for sunrise.php by wordpress-mu-domain-mapping plugin
if (isset($opts['url']) && !empty($opts['url'])) {
$_SERVER['HTTP_HOST'] = trim($opts['url']);
} else {
echo "\033[0;31mERROR:\033[0m This script requires the --url argument\n";
echo " Please check --help for more information\n";
exit;
}
/**
* Tell WordPress we are doing the CRON task.
*
* @var bool
*/
define('DOING_CRON', true);
if (!defined('ABSPATH')) {
$wp_loaded = false;
/**
* if the --wp argument is set, try to load wp-load.php through this path
*/
if (isset($opts['wp']) && !empty($opts['wp'])) {
$path = dirname(__FILE__).DIRECTORY_SEPARATOR.$opts['wp'];
if (false !== $path && file_exists($path . '/wp-load.php')) {
require_once($path . '/wp-load.php');
$wp_loaded = true;
}
}
if (!$wp_loaded) {
if (file_exists(dirname(__FILE__) . '/wp-load.php')) {
require_once(dirname(__FILE__) . '/wp-load.php');
} else {
echo "\033[0;31mERROR:\033[0m Can't find wp-load.php\n";
echo " Please check --help for more information\n";
exit;
}
}
}
// check if multisite
if (defined('MULTISITE') && true === MULTISITE) {
global $wpdb;
$blogs = $wpdb->get_results($wpdb->prepare("SELECT blog_id FROM $wpdb->blogs WHERE archived='%d' AND deleted ='%d' LIMIT 0,300", 0, 0));
foreach ($blogs as $blog) {
switch_to_blog($blog->blog_id);
run_cron();
}
} else {
run_cron();
}
/**
* The actual code to run WP-Cron (code from wp-cron.php)
*/
function run_cron()
{
if (false === $crons = _get_cron_array()) {
die();
}
$keys = array_keys($crons);
$gmt_time = microtime(true);
if (isset($keys[0]) && $keys[0] > $gmt_time) {
die();
}
// The cron lock: a unix timestamp from when the cron was spawned.
$doing_cron_transient = get_transient('doing_cron');
// Use global $doing_wp_cron lock otherwise use the GET lock. If no lock, trying grabbing a new lock.
if (empty($doing_wp_cron)) {
if (empty($_GET['doing_wp_cron'])) {
// Called from external script/job. Try setting a lock.
if ($doing_cron_transient && ($doing_cron_transient + WP_CRON_LOCK_TIMEOUT > $gmt_time)) {
return;
}
$doing_cron_transient = $doing_wp_cron = sprintf('%.22F', microtime(true));
set_transient('doing_cron', $doing_wp_cron);
} else {
$doing_wp_cron = $_GET['doing_wp_cron'];
}
}
/*
* The cron lock (a unix timestamp set when the cron was spawned),
* must match $doing_wp_cron (the "key").
*/
if ($doing_cron_transient != $doing_wp_cron) {
return;
}
foreach ($crons as $timestamp => $cronhooks) {
if ($timestamp > $gmt_time) {
break;
}
foreach ($cronhooks as $hook => $keys) {
foreach ($keys as $k => $v) {
$schedule = $v['schedule'];
if ($schedule != false) {
$new_args = array($timestamp, $schedule, $hook, $v['args']);
call_user_func_array('wp_reschedule_event', $new_args);
}
wp_unschedule_event($timestamp, $hook, $v['args']);
/**
* Fires scheduled events.
*
* @ignore
* @since 2.1.0
*
* @param string $hook Name of the hook that was scheduled to be fired.
* @param array $args The arguments to be passed to the hook.
*/
do_action_ref_array($hook, $v['args']);
// If the hook ran too long and another cron process stole the lock, quit.
if (_get_cron_lock() != $doing_wp_cron) {
return;
}
}
}
}
if (_get_cron_lock() == $doing_wp_cron) {
delete_transient('doing_cron');
}
}
/**
* Retrieves the cron lock.
*
* Returns the uncached `doing_cron` transient.
*
* @ignore
* @since 3.3.0
*
* @return string|false Value of the `doing_cron` transient, 0|false otherwise.
*/
function _get_cron_lock()
{
global $wpdb;
$value = 0;
if (wp_using_ext_object_cache()) {
/*
* Skip local cache and force re-fetch of doing_cron transient
* in case another process updated the cache.
*/
$value = wp_cache_get('doing_cron', 'transient', true);
} else {
$row = $wpdb->get_row($wpdb->prepare("SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", '_transient_doing_cron'));
if (is_object($row)) {
$value = $row->option_value;
}
}
return $value;
}
die();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment