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
2222use WP_REST_Request ;
2323use WP_REST_Response ;
2424
25+ if (!defined ('ABSPATH ' )) exit ;
26+
2527class 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 }
0 commit comments