Skip to content

Commit 81e0a61

Browse files
authored
Merge pull request #14 from PolyPlugins/version/1.2.0
1.2.0
2 parents a573ed3 + 6968d75 commit 81e0a61

3 files changed

Lines changed: 239 additions & 8 deletions

File tree

README.MD

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,10 @@ Yes, the plugin supports uploading images to the WordPress media library via the
6565

6666
## Changelog
6767

68-
### 1.1.1
69-
* Bugfix: When updating a products SKU it says it already exists when it doesn't
68+
### 1.2.0
69+
* Added: Previous beta feature to send email or Discord message if time elapsed is past last access time
70+
* Updated: Date function to gmdate and replaced unlink calls with wp_delete_file
71+
* Updated: Tested up to
7072

7173
### 1.1.0
7274
* Added: Ability to schedule posts using publish_on for [Create Post](https://www.polyplugins.com/docs/content-api/api/create-post/)

content-api.php

Lines changed: 228 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Plugin Name: Content API
55
* Plugin URI: https://www.polyplugins.com/contact/
66
* Description: Adds various endpoints to create content
7-
* Version: 1.1.1
7+
* Version: 1.2.0
88
* Requires at least: 6.5
99
* Requires PHP: 7.4
1010
* Author: Poly Plugins
@@ -22,6 +22,8 @@
2222
use WP_REST_Request;
2323
use WP_REST_Response;
2424

25+
if (!defined('ABSPATH')) exit;
26+
2527
class Content_API
2628
{
2729
const REQUIRED_FIELDS = array('title', 'post_type', 'content', 'categories', 'tags', 'yoast');
@@ -39,6 +41,8 @@ public function init() {
3941
add_action('admin_menu', array($this, 'register_settings_page'));
4042
add_action('admin_init', array($this, 'settings_page_init'));
4143
add_action('admin_notices', array($this, 'maybe_display_last_accessed_notice'));
44+
add_action('wp_loaded', array($this, 'maybe_send_last_accessed_email_notification'));
45+
add_action('wp_loaded', array($this, 'maybe_send_last_accessed_discord_notification'));
4246
}
4347

4448
/**
@@ -222,7 +226,7 @@ public function create_post(WP_REST_Request $request) {
222226
$timestamp = strtotime($publish_on);
223227

224228
if ($timestamp !== false) {
225-
$post_date = date('Y-m-d H:i:s', $timestamp);
229+
$post_date = gmdate('Y-m-d H:i:s', $timestamp);
226230
$post_date_gmt = get_gmt_from_date($post_date);
227231

228232
if ($timestamp > current_time('timestamp')) {
@@ -2441,6 +2445,22 @@ public function settings_page_init() {
24412445
'content-api-settings',
24422446
'setting_section'
24432447
);
2448+
2449+
add_settings_field(
2450+
'last_accessed_notification',
2451+
'Last Accessed Notification',
2452+
array($this, 'last_accessed_notification_callback'),
2453+
'content-api-settings',
2454+
'setting_section'
2455+
);
2456+
2457+
add_settings_field(
2458+
'last_accessed_discord',
2459+
'Last Accessed Discord',
2460+
array($this, 'last_accessed_discord_callback'),
2461+
'content-api-settings',
2462+
'setting_section'
2463+
);
24442464
}
24452465

24462466
/**
@@ -2481,6 +2501,32 @@ public function last_accessed_error_time_callback() {
24812501
<?php
24822502
}
24832503

2504+
/**
2505+
* Last Accessed Notification callback
2506+
*
2507+
* @return void
2508+
*/
2509+
public function last_accessed_notification_callback() {
2510+
$option = isset($this->options['last_accessed_notification']) ? sanitize_text_field($this->options['last_accessed_notification']) : '';
2511+
?>
2512+
<input type="checkbox" name="content_api_options_polyplugins[last_accessed_notification]" id="last_accessed_notification" <?php esc_attr(checked(1, $option, true)); ?> /> <?php echo esc_html__('Yes', 'content-api'); ?>
2513+
<p>This will send an email to the email under Settings -> General when time has exceeded "Last Accessed Error Time".</p>
2514+
<?php
2515+
}
2516+
2517+
/**
2518+
* Last Accessed Discord callback
2519+
*
2520+
* @return void
2521+
*/
2522+
public function last_accessed_discord_callback() {
2523+
$option = isset($this->options['last_accessed_discord']) ? sanitize_text_field($this->options['last_accessed_discord']) : '';
2524+
?>
2525+
<input class="regular-text" type="password" name="content_api_options_polyplugins[last_accessed_discord]" id="last_accessed_discord" value="<?php echo esc_html($option); ?>">
2526+
<p>Enter your Discord Webhook URL to get a Discord alert when time has exceeded "Last Accessed Error Time".</p>
2527+
<?php
2528+
}
2529+
24842530
/**
24852531
* Sanitize Options
24862532
*
@@ -2504,6 +2550,16 @@ public function sanitize($input) {
25042550
$sanitary_values['last_accessed_error_time'] = intval($input['last_accessed_error_time']);
25052551
}
25062552

2553+
if (isset($input['last_accessed_notification']) && $input['last_accessed_notification']) {
2554+
$sanitary_values['last_accessed_notification'] = $input['last_accessed_notification'] === 'on' ? true : false;
2555+
} else {
2556+
$sanitary_values['last_accessed_notification'] = false;
2557+
}
2558+
2559+
if (isset($input['last_accessed_discord']) && $input['last_accessed_discord']) {
2560+
$sanitary_values['last_accessed_discord'] = sanitize_text_field($input['last_accessed_discord']);
2561+
}
2562+
25072563
return $sanitary_values;
25082564
}
25092565

@@ -2546,6 +2602,174 @@ public function maybe_display_last_accessed_notice() {
25462602
<?php
25472603
}
25482604

2605+
/**
2606+
* Maybe send last accessed Discord notification
2607+
*
2608+
* @return void
2609+
*/
2610+
public function maybe_send_last_accessed_discord_notification() {
2611+
$this->options = get_option('content_api_options_polyplugins');
2612+
2613+
if (empty($this->options['last_accessed_enabled'])) {
2614+
return;
2615+
}
2616+
2617+
// Prevent multiple runs in a short period
2618+
if (get_transient('content_api_last_accessed_discord_lock')) {
2619+
return; // Already running, exit early
2620+
}
2621+
2622+
set_transient('content_api_last_accessed_discord_lock', 1, 300);
2623+
2624+
$last_accessed = get_option('content_api_last_accessed_polyplugins');
2625+
2626+
if (!$last_accessed) {
2627+
delete_transient('content_api_last_accessed_discord_lock');
2628+
return;
2629+
}
2630+
2631+
$threshold = isset($this->options['last_accessed_error_time']) ? intval($this->options['last_accessed_error_time']) : 0;
2632+
$minutes_since_last_access = (time() - intval($last_accessed)) / 60;
2633+
$webhook_url = isset($this->options['last_accessed_discord']) ? $this->options['last_accessed_discord'] : '';
2634+
2635+
if (!$webhook_url) {
2636+
delete_transient('content_api_last_accessed_discord_lock');
2637+
return;
2638+
}
2639+
2640+
// Track last notification state
2641+
$notified_error = get_option('content_api_last_accessed_error_notified');
2642+
$notified_recovered = get_option('content_api_last_accessed_recovered_notified');
2643+
$notified_initial = get_option('content_api_last_accessed_initial_notified');
2644+
2645+
if ($last_accessed && !$notified_initial) {
2646+
$message = array(
2647+
'content' => "⚡ Connection Successful"
2648+
);
2649+
2650+
wp_remote_post($webhook_url, array(
2651+
'body' => wp_json_encode($message),
2652+
'headers' => array('Content-Type' => 'application/json'),
2653+
'timeout' => 5,
2654+
));
2655+
2656+
update_option('content_api_last_accessed_initial_notified', 1);
2657+
delete_transient('content_api_last_accessed_discord_lock');
2658+
return; // exit early; no need to check threshold yet
2659+
}
2660+
2661+
// Threshold exceeded -> send error notification once
2662+
if ($threshold && $minutes_since_last_access > $threshold) {
2663+
if (!$notified_error) {
2664+
$message = array(
2665+
'content' => sprintf(
2666+
"⚠️ Connection lost. Last accessed %d minutes ago.",
2667+
$minutes_since_last_access,
2668+
$threshold
2669+
)
2670+
);
2671+
2672+
wp_remote_post($webhook_url, array(
2673+
'body' => wp_json_encode($message),
2674+
'headers' => array('Content-Type' => 'application/json'),
2675+
'timeout' => 5,
2676+
));
2677+
2678+
update_option('content_api_last_accessed_error_notified', 1);
2679+
delete_option('content_api_last_accessed_recovered_notified');
2680+
}
2681+
} else {
2682+
if ($notified_error && !$notified_recovered) {
2683+
$message = array(
2684+
'content' => "✅ Connection restored."
2685+
);
2686+
2687+
wp_remote_post($webhook_url, array(
2688+
'body' => wp_json_encode($message),
2689+
'headers' => array('Content-Type' => 'application/json'),
2690+
'timeout' => 5,
2691+
));
2692+
2693+
update_option('content_api_last_accessed_recovered_notified', 1);
2694+
delete_option('content_api_last_accessed_error_notified');
2695+
}
2696+
}
2697+
2698+
delete_transient('content_api_last_accessed_discord_lock');
2699+
}
2700+
2701+
/**
2702+
* Maybe send last accessed email notification
2703+
*
2704+
* @return void
2705+
*/
2706+
public function maybe_send_last_accessed_email_notification() {
2707+
$this->options = get_option('content_api_options_polyplugins');
2708+
2709+
// Check if notifications are enabled
2710+
if (empty($this->options['last_accessed_enabled']) || empty($this->options['last_accessed_notification'])) {
2711+
return;
2712+
}
2713+
2714+
// Prevent multiple runs in a short period
2715+
if (get_transient('content_api_last_accessed_email_lock')) {
2716+
return; // Already running, exit early
2717+
}
2718+
2719+
set_transient('content_api_last_accessed_email_lock', 1, 300);
2720+
2721+
$last_accessed = get_option('content_api_last_accessed_polyplugins');
2722+
2723+
if (!$last_accessed) {
2724+
delete_transient('content_api_last_accessed_email_lock');
2725+
return;
2726+
}
2727+
2728+
$threshold = isset($this->options['last_accessed_error_time']) ? intval($this->options['last_accessed_error_time']) : 0;
2729+
$minutes_since_last_access = (time() - intval($last_accessed)) / 60;
2730+
2731+
$admin_email = get_option('admin_email'); // default WP email
2732+
2733+
if (!$admin_email) {
2734+
delete_transient('content_api_last_accessed_email_lock');
2735+
return;
2736+
}
2737+
2738+
// Track last notification state
2739+
$notified_error = get_option('content_api_last_accessed_email_error_notified');
2740+
$notified_recovered = get_option('content_api_last_accessed_email_recovered_notified');
2741+
2742+
$headers = array('Content-Type: text/html; charset=UTF-8');
2743+
2744+
// Threshold exceeded -> send error email once
2745+
if ($threshold && $minutes_since_last_access > $threshold) {
2746+
if (!$notified_error) {
2747+
$subject = "⚠️ Content API Connection Lost";
2748+
$message = sprintf(
2749+
"The Content API has not been accessed for %.1f minutes.",
2750+
$minutes_since_last_access,
2751+
);
2752+
2753+
wp_mail($admin_email, $subject, $message, $headers);
2754+
2755+
update_option('content_api_last_accessed_email_error_notified', 1);
2756+
delete_option('content_api_last_accessed_email_recovered_notified');
2757+
}
2758+
} else {
2759+
if ($notified_error && !$notified_recovered) {
2760+
$subject = "✅ Content API Connection Restored";
2761+
$message = "Normal operation has resumed, and the system is accessible.";
2762+
2763+
wp_mail($admin_email, $subject, $message, $headers);
2764+
2765+
update_option('content_api_last_accessed_email_recovered_notified', 1);
2766+
delete_option('content_api_last_accessed_email_error_notified');
2767+
}
2768+
}
2769+
2770+
delete_transient('content_api_last_accessed_email_lock');
2771+
}
2772+
25492773
/**
25502774
* Checks if request is granted
25512775
*
@@ -2835,12 +3059,12 @@ private function upload_image_to_media_library($image_url, $post_id) {
28353059
$file_id = media_handle_sideload($file_array, $post_id);
28363060

28373061
if (is_wp_error($file_id)) {
2838-
@unlink($tmp);
3062+
wp_delete_file($tmp);
28393063
return;
28403064
}
28413065

28423066
// Clean up temporary file
2843-
@unlink($tmp);
3067+
wp_delete_file($tmp);
28443068

28453069
return $file_id;
28463070
}

readme.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
=== Content API ===
22
Contributors: polyplugins
33
Tags: content api, rest api, content, creative, api
4-
Tested up to: 6.8
5-
Stable tag: 1.1.1
4+
Tested up to: 6.9
5+
Stable tag: 1.2.0
66
Requires PHP: 7.4
77
License: GPLv3
88
License URI: https://www.gnu.org/licenses/gpl-3.0.html
@@ -84,6 +84,11 @@ Yes, the plugin supports uploading images to the WordPress media library via the
8484

8585
== Changelog ==
8686

87+
= 1.2.0 =
88+
* Added: Previous beta feature to send email or Discord message if time elapsed is past last access time
89+
* Updated: Date function to gmdate and replaced unlink calls with wp_delete_file
90+
* Updated: Tested up to
91+
8792
= 1.1.1 =
8893
* Bugfix: When updating a products SKU it says it already exists when it doesn't
8994

0 commit comments

Comments
 (0)