From f2885553952d1e93cb22ff8c0821d56909dd221c Mon Sep 17 00:00:00 2001
From: paavan-cleverpush
Date: Wed, 28 Oct 2026 15:04:00 +0530
Subject: [PATCH]
hotfix/cp-12676-cleverpush-wordpress-plugin-not-saving-scheduled-push
---
cleverpush-api.php | 21 ++++++
cleverpush.php | 180 ++++++++++++++++++++++++++++++++++++++-------
readme.txt | 7 +-
3 files changed, 180 insertions(+), 28 deletions(-)
diff --git a/cleverpush-api.php b/cleverpush-api.php
index 5236cab..9c25a04 100644
--- a/cleverpush-api.php
+++ b/cleverpush-api.php
@@ -85,6 +85,27 @@ public static function send_notification($title, $body, $url, $options = array()
return CleverPush_Api::request('/notification/send', $params);
}
+ public static function delete_notification($notification_id)
+ {
+ $channel_id = get_option('cleverpush_channel_id');
+ $api_key_private = get_option('cleverpush_apikey_private');
+
+ if (empty($channel_id) || empty($notification_id) || empty($api_key_private)) {
+ return null;
+ }
+
+ return wp_remote_request(
+ CLEVERPUSH_API_ENDPOINT . '/channel/' . rawurlencode($channel_id) . '/notification/' . rawurlencode($notification_id),
+ array(
+ 'method' => 'DELETE',
+ 'timeout' => 20, // phpcs:ignore
+ 'headers' => array(
+ 'authorization' => $api_key_private
+ )
+ )
+ );
+ }
+
public static function update_channel($channel_id, $params = array())
{
if (empty($channel_id)) {
diff --git a/cleverpush.php b/cleverpush.php
index f7ee2da..3751094 100644
--- a/cleverpush.php
+++ b/cleverpush.php
@@ -4,7 +4,7 @@
Plugin URI: https://cleverpush.com
Description: Send push notifications to your users right through your website. Visit CleverPush for more details.
Author: CleverPush
-Version: 1.9.8
+Version: 1.9.9
Author URI: https://cleverpush.com
Text Domain: cleverpush
Domain Path: /languages
@@ -763,11 +763,46 @@ public function metabox($post)
cpCheckbox.addEventListener('change', function (e) {
cpContent.style.display = e.target.checked ? 'block' : 'none';
- if (!e.target.checked && cpScheduledAtPicker) {
- cpScheduledAtPicker.value = '';
+ if (!e.target.checked) {
+ if (cpScheduledAtPicker) {
+ cpScheduledAtPicker.value = '';
+ }
+ if (cpScheduledAtInput) {
+ cpScheduledAtInput.value = '';
+ }
}
});
+ var syncScheduledAt = function () {};
+ if (cpScheduledAtInput && cpScheduledAtPicker) {
+ var padDatePart = function (value) {
+ return (value < 10 ? '0' : '') + value;
+ };
+ var getLocalDateString = function (date) {
+ return date.getFullYear() + '-' + padDatePart(date.getMonth() + 1) + '-' + padDatePart(date.getDate()) + 'T' + padDatePart(date.getHours()) + ':' + padDatePart(date.getMinutes());
+ };
+ syncScheduledAt = function () {
+ if (!cpScheduledAtPicker.value) {
+ cpScheduledAtInput.value = '';
+ return;
+ }
+ var parsed = new Date(cpScheduledAtPicker.value);
+ if (!isNaN(parsed.getTime())) {
+ cpScheduledAtInput.value = parsed.toISOString();
+ }
+ };
+ cpScheduledAtPicker.min = getLocalDateString(new Date());
+ if (cpScheduledAtInput.value && new Date(cpScheduledAtInput.value) > new Date()) {
+ cpScheduledAtPicker.value = getLocalDateString(new Date(cpScheduledAtInput.value));
+ }
+ cpScheduledAtPicker.addEventListener('input', syncScheduledAt);
+ cpScheduledAtPicker.addEventListener('change', syncScheduledAt);
+ var postForm = document.getElementById('post');
+ if (postForm) {
+ postForm.addEventListener('submit', syncScheduledAt);
+ }
+ }
+
var initCleverPush = function () {
if (typeof wp !== 'undefined' && wp.data && wp.data.subscribe && wp.data.select) {
var hasNotice = false;
@@ -790,6 +825,10 @@ public function metabox($post)
var isPreviewingPost = coreEditor.isPreviewingPost();
var postStatus = coreEditor.getEditedPostAttribute('status');
+ if (isSavingPost && !wasSavingPost) {
+ syncScheduledAt();
+ }
+
// Save metaboxes on save completion, except for autosaves that are not a post preview.
var shouldTriggerTemplateNotice = (
(wasSavingPost && !isSavingPost && !wasAutosavingPost) ||
@@ -971,23 +1010,6 @@ public function metabox($post)
}
}
- if (cpScheduledAtInput && cpScheduledAtPicker) {
- var getLocalDateString = function(date) {
- return date.getFullYear() + '-' + ((date.getMonth() + 1) + '').padStart(2, '0') + '-' + (date.getDate() + '') + "T" + (date.getHours() + '').padStart(2, '0') + ":" + (date.getMinutes() + '').padStart(2, '0')
- };
- var date = new Date();
- cpScheduledAtPicker.min = getLocalDateString(date);
- if (cpScheduledAtInput.value && new Date(cpScheduledAtInput.value) > new Date()) {
- cpScheduledAtPicker.value = getLocalDateString(new Date(cpScheduledAtInput.value));
- }
- cpScheduledAtPicker.addEventListener('change', function() {
- if (!cpScheduledAtPicker.value) {
- cpScheduledAtInput.value = '';
- return;
- }
- cpScheduledAtInput.value = new Date(cpScheduledAtPicker.value).toISOString();
- });
- }
}
}
};
@@ -1126,16 +1148,18 @@ public function publish_post($post_id)
return;
}
- if (!current_user_can('cleverpush_send')) {
+ $saved_send = get_post_meta($post_id, 'cleverpush_send_notification', true);
+ $publishing_via_cron = (function_exists('wp_doing_cron') && wp_doing_cron()) || (defined('DOING_CRON') && DOING_CRON);
+ if (!current_user_can('cleverpush_send') && !($publishing_via_cron && $saved_send)) {
return;
}
- if (isset($_POST['cleverpush_metabox_form_data_available']) ? !isset($_POST['cleverpush_send_notification']) : !get_post_meta($post_id, 'cleverpush_send_notification', true)) {
+ if (isset($_POST['cleverpush_metabox_form_data_available']) ? !isset($_POST['cleverpush_send_notification']) : !$saved_send) {
return;
}
if (get_post_meta($post_id, 'cleverpush_notification_sent', true)) {
- $notification_sent_at = get_post_meta(get_the_ID(), 'cleverpush_notification_sent_at', true);
+ $notification_sent_at = get_post_meta($post_id, 'cleverpush_notification_sent_at', true);
if (!empty($notification_sent_at) && (time() - $notification_sent_at) < 60) {
return;
}
@@ -1145,15 +1169,28 @@ public function publish_post($post_id)
if (get_option('cleverpush_notification_title_required') == 'on') {
$title = null;
}
- $text = !empty(get_the_excerpt()) ? html_entity_decode(get_the_excerpt()) : '';
+ $text = get_the_excerpt($post_id);
+ $text = !empty($text) ? html_entity_decode($text) : '';
$url = get_permalink($post_id);
+ $metabox_submitted = isset($_POST['cleverpush_metabox_form_data_available']);
if (!empty($_POST['cleverpush_title'])) {
$title = sanitize_text_field(wp_unslash($_POST['cleverpush_title']));
$text = '';
+ } elseif (!$metabox_submitted) {
+ $saved_title = get_post_meta($post_id, 'cleverpush_title', true);
+ if (!empty($saved_title)) {
+ $title = $saved_title;
+ $text = '';
+ }
}
if (!empty($_POST['cleverpush_text'])) {
$text = sanitize_text_field(wp_unslash($_POST['cleverpush_text']));
+ } elseif (!$metabox_submitted) {
+ $saved_text = get_post_meta($post_id, 'cleverpush_text', true);
+ if (!empty($saved_text)) {
+ $text = $saved_text;
+ }
}
if (empty($title)) {
@@ -1170,13 +1207,19 @@ public function publish_post($post_id)
if (isset($_POST['cleverpush_use_tags']) && $_POST['cleverpush_use_tags'] == '1' && !empty($_POST['cleverpush_tags'])) {
$options['tags'] = array_map('sanitize_text_field', $_POST['cleverpush_tags']);
}
- $thumbnail_url = get_the_post_thumbnail_url();
+ $thumbnail_url = get_the_post_thumbnail_url($post_id);
if (!empty($thumbnail_url)) {
$options['mediaUrl'] = $thumbnail_url;
}
if (!empty($_POST['cleverpush_scheduled_at'])) {
$options['scheduledAt'] = sanitize_text_field(wp_unslash($_POST['cleverpush_scheduled_at']));
+ } else {
+ $saved_scheduled_at = get_post_meta($post_id, 'cleverpush_scheduled_at', true);
+ $saved_timestamp = !empty($saved_scheduled_at) ? strtotime($saved_scheduled_at) : false;
+ if ($saved_timestamp && $saved_timestamp > time()) {
+ $options['scheduledAt'] = $saved_scheduled_at;
+ }
}
delete_post_meta($post_id, 'cleverpush_send_notification');
@@ -1187,6 +1230,7 @@ public function publish_post($post_id)
update_option('cleverpush_notification_error', null);
update_post_meta($post_id, 'cleverpush_notification_sent', true);
update_post_meta($post_id, 'cleverpush_notification_sent_at', time());
+ $this->delete_draft_notification($post_id);
} catch (Exception $ex) {
update_option('cleverpush_notification_result', array('status' => 'error', 'message' => $ex->getMessage() ));
@@ -1215,10 +1259,12 @@ public function save_post($post_id, $post)
if (isset($_POST['cleverpush_text'])) {
update_post_meta($post_id, 'cleverpush_text', sanitize_text_field($_POST['cleverpush_text']));
}
- if (isset($_POST['cleverpush_scheduled_at'])) {
- update_post_meta($post_id, 'cleverpush_scheduled_at', sanitize_text_field($_POST['cleverpush_scheduled_at']));
+ if (isset($_POST['cleverpush_metabox_form_data_available']) && isset($_POST['cleverpush_scheduled_at'])) {
+ update_post_meta($post_id, 'cleverpush_scheduled_at', sanitize_text_field(wp_unslash($_POST['cleverpush_scheduled_at'])));
}
+ $this->sync_draft_notification($post_id);
+
if (!empty($_POST['cleverpush_story_id'])) {
if (isset($_POST['clear_cache']) && !empty($_POST['cleverpush_story_id'])) {
delete_transient('cleverpush_story_' . sanitize_text_field($_POST['cleverpush_story_id']) . '_content');
@@ -1245,6 +1291,86 @@ public function save_post($post_id, $post)
}
}
+ public function sync_draft_notification($post_id)
+ {
+ if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) {
+ return;
+ }
+
+ if (!isset($_POST['cleverpush_metabox_form_data_available'])) {
+ return;
+ }
+
+ $status = get_post_status($post_id);
+ if (!in_array($status, array('draft', 'future', 'pending'), true)) {
+ return;
+ }
+
+ if (!isset($_POST['cleverpush_send_notification'])) {
+ $this->delete_draft_notification($post_id);
+ return;
+ }
+
+ $title = html_entity_decode(get_the_title($post_id));
+ if (!empty($_POST['cleverpush_title'])) {
+ $title = sanitize_text_field(wp_unslash($_POST['cleverpush_title']));
+ }
+ $text = '';
+ if (!empty($_POST['cleverpush_text'])) {
+ $text = sanitize_text_field(wp_unslash($_POST['cleverpush_text']));
+ }
+ if (empty($title)) {
+ return;
+ }
+
+ $scheduled_at = get_post_meta($post_id, 'cleverpush_scheduled_at', true);
+ $scheduled_timestamp = !empty($scheduled_at) ? strtotime($scheduled_at) : false;
+ if (!$scheduled_timestamp || $scheduled_timestamp <= time()) {
+ $scheduled_at = '';
+ }
+
+ $fingerprint = md5($title . '|' . $text . '|' . $scheduled_at);
+ $existing_id = get_post_meta($post_id, 'cleverpush_draft_notification_id', true);
+ $existing_fingerprint = get_post_meta($post_id, 'cleverpush_draft_notification_hash', true);
+ if (!empty($existing_id) && $existing_fingerprint === $fingerprint) {
+ return;
+ }
+
+ if (!empty($existing_id)) {
+ $this->delete_draft_notification($post_id);
+ }
+
+ $options = array('status' => 'draft');
+ if (!empty($scheduled_at)) {
+ $options['scheduledAt'] = $scheduled_at;
+ }
+
+ try {
+ $response = CleverPush_Api::send_notification($title, $text, get_permalink($post_id), $options);
+ if (empty($response) || is_wp_error($response)) {
+ return;
+ }
+ $body = json_decode(wp_remote_retrieve_body($response));
+ if (empty($body->notificationId)) {
+ return;
+ }
+ update_post_meta($post_id, 'cleverpush_draft_notification_id', sanitize_text_field($body->notificationId));
+ update_post_meta($post_id, 'cleverpush_draft_notification_hash', $fingerprint);
+ } catch (Exception $ex) {
+ update_option('cleverpush_notification_error', $ex->getMessage());
+ }
+ }
+
+ public function delete_draft_notification($post_id)
+ {
+ $notification_id = get_post_meta($post_id, 'cleverpush_draft_notification_id', true);
+ if (!empty($notification_id)) {
+ CleverPush_Api::delete_notification($notification_id);
+ }
+ delete_post_meta($post_id, 'cleverpush_draft_notification_id');
+ delete_post_meta($post_id, 'cleverpush_draft_notification_hash');
+ }
+
public function show_public_preview( $query )
{
if ($query->is_main_query()
diff --git a/readme.txt b/readme.txt
index e6fc754..22b7fd8 100644
--- a/readme.txt
+++ b/readme.txt
@@ -5,7 +5,7 @@ Plugin URI: https://cleverpush.com
Tags: push notifications, web push, browser notifications, woocommerce
Requires at least: 2.7
Tested up to: 6.7.2
-Stable tag: 1.9.8
+Stable tag: 1.9.9
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -34,6 +34,11 @@ If you are using any cache plugin, also be sure, to empty your cache.
== ChangeLog ==
+= 1.9.9 =
+* Keep the optional notification schedule after saving a post
+* Send that scheduled push when WordPress publishes the post, including a scheduled post
+* Show an unpublished scheduled post as a draft in CleverPush
+
= 1.9.8 =
* Fixed issue with capabilities_version