From 7907bc94d52fc077844a697e07f87dbb8db38d21 Mon Sep 17 00:00:00 2001
From: jrfnl <github_nospam@adviesenzo.nl>
Date: Tue, 8 Dec 2015 20:40:27 +0100
Subject: [PATCH] Refresh of @mordauk's patch: Add wp_unschedule_hook() + unit
 tests.

---
 src/wp-includes/cron.php     | 25 +++++++++++++++++++++++++
 tests/phpunit/tests/cron.php | 22 ++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/src/wp-includes/cron.php b/src/wp-includes/cron.php
index 60492c5..88ca1b5 100644
--- a/src/wp-includes/cron.php
+++ b/src/wp-includes/cron.php
@@ -211,6 +211,31 @@ function wp_clear_scheduled_hook( $hook, $args = array() ) {
 }
 
 /**
+ * Unschedule all previously scheduled cron jobs for a hook.
+ *
+ * Can be useful for plugins when deactivating to clean up the cron queue.
+ *
+ * The $hook parameter is required, so that the events can be identified.
+ *
+ * @since x.x
+ *
+ * @param string $hook Action hook, the execution of which will be unscheduled.
+ */
+function wp_unschedule_hook( $hook ) {
+	$crons = _get_cron_array();
+
+	foreach( $crons as $timestamp => $args ) {
+		unset( $crons[ $timestamp ][ $hook ] );
+
+		if ( empty( $crons[ $timestamp ] ) ) {
+			unset( $crons[ $timestamp ] );
+		}
+	}
+
+	_set_cron_array( $crons );
+}
+
+/**
  * Retrieve the next timestamp for a cron event.
  *
  * @since 2.1.0
diff --git a/tests/phpunit/tests/cron.php b/tests/phpunit/tests/cron.php
index b411a5b..e03bd3e 100644
--- a/tests/phpunit/tests/cron.php
+++ b/tests/phpunit/tests/cron.php
@@ -124,6 +124,28 @@ class Tests_Cron extends WP_UnitTestCase {
 		$this->assertFalse( wp_next_scheduled($hook, $args) );
 	}
 
+	/**
+	 * @ticket 18997
+	 */
+	function test_unschedule_hook() {
+		$hook = rand_str();
+		$args = array(rand_str());
+
+		// schedule several events with and without arguments.
+		wp_schedule_single_event( strtotime('+1 hour'), $hook );
+		wp_schedule_single_event( strtotime('+2 hour'), $hook );
+		wp_schedule_single_event( strtotime('+3 hour'), $hook, $args );
+		wp_schedule_single_event( strtotime('+4 hour'), $hook, $args );
+
+		// make sure they're returned by wp_next_scheduled().
+		$this->assertTrue( wp_next_scheduled($hook) > 0 );
+		$this->assertTrue( wp_next_scheduled($hook, $args) > 0 );
+
+		// clear the schedule for the no args events and make sure it's gone.
+		wp_unschedule_hook($hook);
+		$this->assertFalse( wp_next_scheduled($hook) );
+	}
+
 	function test_clear_schedule_multiple_args() {
 		$hook = rand_str();
 		$args = array(rand_str(), rand_str());
-- 
1.9.4.msysgit.2

