Admin
3 months ago
Builder
3 months ago
Helpers
3 months ago
Integrations
3 months ago
CFF_Autolink.php
3 months ago
CFF_Blocks.php
3 months ago
CFF_Cache.php
3 months ago
CFF_Education.php
3 months ago
CFF_Elementor_Base.php
3 months ago
CFF_Elementor_Widget.php
3 months ago
CFF_Error_Reporter.php
3 months ago
CFF_FB_Settings.php
3 months ago
CFF_Feed_Elementor_Control.php
3 months ago
CFF_Feed_Locator.php
3 months ago
CFF_Feed_Pro.php
3 months ago
CFF_GDPR_Integrations.php
3 months ago
CFF_Group_Posts.php
3 months ago
CFF_HTTP_Request.php
3 months ago
CFF_Oembed.php
3 months ago
CFF_Parse.php
3 months ago
CFF_Resizer.php
3 months ago
CFF_Response.php
3 months ago
CFF_Shortcode.php
3 months ago
CFF_Shortcode_Display.php
3 months ago
CFF_SiteHealth.php
3 months ago
CFF_Utils.php
3 months ago
CFF_View.php
3 months ago
Custom_Facebook_Feed.php
3 months ago
Email_Notification.php
3 months ago
Platform_Data.php
3 months ago
SB_Facebook_Data_Encryption.php
3 months ago
SB_Facebook_Data_Manager.php
3 months ago
index.php
3 months ago
Platform_Data.php
364 lines
| 1 | <?php |
| 2 | |
| 3 | /** |
| 4 | * Platform Data |
| 5 | * |
| 6 | * @package Platform_Data |
| 7 | */ |
| 8 | |
| 9 | namespace CustomFacebookFeed; |
| 10 | |
| 11 | use CustomFacebookFeed\Builder\CFF_Db; |
| 12 | |
| 13 | if (!defined('ABSPATH')) { |
| 14 | exit; // Exit if accessed directly |
| 15 | } |
| 16 | |
| 17 | /** |
| 18 | * Class Platform_Data |
| 19 | * |
| 20 | * Handles all data related to the platform. |
| 21 | * |
| 22 | * @since 4.2 |
| 23 | * |
| 24 | * @package CustomFacebookFeed |
| 25 | */ |
| 26 | class Platform_Data |
| 27 | { |
| 28 | /** |
| 29 | * Option key for app statuses. |
| 30 | * |
| 31 | * @var string |
| 32 | */ |
| 33 | const CFF_STATUSES_OPTION_KEY = 'cff_statuses'; |
| 34 | |
| 35 | /** |
| 36 | * Option key for the revoke platform data. |
| 37 | * |
| 38 | * @var string |
| 39 | */ |
| 40 | const REVOKE_PLATFORM_DATA_OPTION_KEY = 'cff_revoke_platform_data'; |
| 41 | |
| 42 | /** |
| 43 | * Array key for the app permission status key on `cff_statuses`. |
| 44 | * |
| 45 | * @var string |
| 46 | */ |
| 47 | const APP_PERMISSION_REVOKED_STATUS_KEY = 'app_permission_revoked'; |
| 48 | |
| 49 | /** |
| 50 | * Array key for the warning email flag for unused feed status key on `cff_statuses`. |
| 51 | */ |
| 52 | const UNUSED_FEED_WARNING_EMAIL_SENT_STATUS_KEY = 'unused_feed_warning_email_sent'; |
| 53 | |
| 54 | /** |
| 55 | * Register the hooks. |
| 56 | * |
| 57 | * @return void |
| 58 | */ |
| 59 | public function register_hooks() |
| 60 | { |
| 61 | add_action('cff_api_connect_response', [$this, 'handle_platform_data_on_api_response'], 10, 2); |
| 62 | add_action('cff_before_display_facebook', [$this, 'handle_app_permission_error'], 10); |
| 63 | add_action('cff_app_permission_revoked', [$this, 'handle_app_permission_status'], 10, 1); |
| 64 | add_action('cff_before_delete_old_data', [$this, 'handle_event_before_delete_old_data'], 10); |
| 65 | |
| 66 | // Ajax Hooks |
| 67 | add_action('wp_ajax_cff_reset_unused_feed_usage', [$this, 'handle_unused_feed_usage'], 10); |
| 68 | } |
| 69 | |
| 70 | /** |
| 71 | * Handle the platform data on the API response. |
| 72 | * |
| 73 | * @param array $response The response from the API. |
| 74 | * @param string $url The URL of the request. |
| 75 | * |
| 76 | * @return void |
| 77 | */ |
| 78 | public function handle_platform_data_on_api_response($response, $url) |
| 79 | { |
| 80 | if (is_wp_error($response)) { |
| 81 | return; |
| 82 | } |
| 83 | |
| 84 | if (empty($response['response']) || empty($response['response']['code'])) { |
| 85 | return; |
| 86 | } |
| 87 | |
| 88 | if ($response['response']['code'] !== 200) { |
| 89 | return; |
| 90 | } |
| 91 | |
| 92 | \cff_main()->cff_error_reporter->remove_error('platform_data_deleted'); |
| 93 | |
| 94 | $cff_statuses_option = get_option(self::CFF_STATUSES_OPTION_KEY, []); |
| 95 | |
| 96 | if (empty($cff_statuses_option[self::APP_PERMISSION_REVOKED_STATUS_KEY])) { |
| 97 | return; |
| 98 | } |
| 99 | $cff_revoke_platform_data = get_option(self::REVOKE_PLATFORM_DATA_OPTION_KEY, []); |
| 100 | $revoked_account_username = isset($cff_revoke_platform_data['connected_account']['name']) ? $cff_revoke_platform_data['connected_account']['name'] : ''; |
| 101 | |
| 102 | if (empty($revoked_account_username)) { |
| 103 | return; |
| 104 | } |
| 105 | $api_response_username = json_decode($response['body'])->name; |
| 106 | if ($revoked_account_username !== $api_response_username) { |
| 107 | return; |
| 108 | } |
| 109 | |
| 110 | // Cleanup the revoked platform status and revoke account data. |
| 111 | $this->cleanup_revoked_account($cff_statuses_option); |
| 112 | \cff_main()->cff_error_reporter->reset_api_errors(); |
| 113 | } |
| 114 | |
| 115 | /** |
| 116 | * Handle the app permission error. |
| 117 | * |
| 118 | * @return void |
| 119 | */ |
| 120 | public function handle_app_permission_error() |
| 121 | { |
| 122 | $cff_statuses_option = get_option(self::CFF_STATUSES_OPTION_KEY, []); |
| 123 | |
| 124 | if (empty($cff_statuses_option[self::APP_PERMISSION_REVOKED_STATUS_KEY])) { |
| 125 | return; |
| 126 | } |
| 127 | |
| 128 | $cff_revoke_platform_data = get_option(self::REVOKE_PLATFORM_DATA_OPTION_KEY, []); |
| 129 | |
| 130 | $revoke_platform_data_timestamp = isset($cff_revoke_platform_data['revoke_platform_data_timestamp']) ? $cff_revoke_platform_data['revoke_platform_data_timestamp'] : 0; |
| 131 | $connected_account = isset($cff_revoke_platform_data['connected_account']) ? $cff_revoke_platform_data['connected_account'] : []; |
| 132 | |
| 133 | if (!$revoke_platform_data_timestamp) { |
| 134 | return; |
| 135 | } |
| 136 | |
| 137 | $current_timestamp = time(); |
| 138 | |
| 139 | // Check if current timestamp is less than revoke platform data timestamp, if so, return. |
| 140 | if ($current_timestamp < $revoke_platform_data_timestamp) { |
| 141 | return; |
| 142 | } |
| 143 | |
| 144 | // Revoke platform data. |
| 145 | $this->delete_platform_data($connected_account); |
| 146 | $this->send_platform_data_delete_notification_email(); |
| 147 | // Cleanup the revoked platform status and revoke account data. |
| 148 | $this->cleanup_revoked_account($cff_statuses_option); |
| 149 | \cff_main()->cff_error_reporter->reset_api_errors(); |
| 150 | \cff_main()->cff_error_reporter->add_error( |
| 151 | 'platform_data_deleted', |
| 152 | array( |
| 153 | __('An account admin has deauthorized the Smash Balloon app used to power the Facebook Feed plugin. The page was not reconnected within the 7 day limit and all Facebook data was automatically deleted on your website due to Facebook data privacy rules.', 'custom-facebook-feed') |
| 154 | ) |
| 155 | ); |
| 156 | } |
| 157 | |
| 158 | /** |
| 159 | * Handle the app permission status. |
| 160 | * |
| 161 | * @param array $connected_account The connected account data. |
| 162 | * |
| 163 | * @return void |
| 164 | */ |
| 165 | public function handle_app_permission_status($connected_account) |
| 166 | { |
| 167 | $cff_statuses_option = get_option(self::CFF_STATUSES_OPTION_KEY, []); |
| 168 | if (isset($cff_statuses_option['app_permission_revoked']) && true === $cff_statuses_option['app_permission_revoked']) { |
| 169 | return; |
| 170 | } |
| 171 | |
| 172 | $this->update_app_permission_revoked_status($cff_statuses_option, true); |
| 173 | |
| 174 | // Calculate the grace period for revoking platform data. |
| 175 | $current_timestamp = time(); |
| 176 | $revoke_platform_data_timestamp = strtotime('+7 days', $current_timestamp); |
| 177 | |
| 178 | update_option( |
| 179 | self::REVOKE_PLATFORM_DATA_OPTION_KEY, |
| 180 | [ |
| 181 | 'revoke_platform_data_timestamp' => $revoke_platform_data_timestamp, |
| 182 | 'connected_account' => $connected_account, |
| 183 | ] |
| 184 | ); |
| 185 | $this->send_revoke_notification_email(); |
| 186 | } |
| 187 | |
| 188 | /** |
| 189 | * Delete any data associated with the Facebook API and the |
| 190 | * connected account being deleted. |
| 191 | * |
| 192 | * @param $to_delete_connected_account |
| 193 | * |
| 194 | * @return void |
| 195 | */ |
| 196 | protected function delete_platform_data($to_delete_connected_account) |
| 197 | { |
| 198 | $all_connected_accounts = get_connected_accounts_list(); |
| 199 | $to_update = []; |
| 200 | foreach ($all_connected_accounts as $connected_account) { |
| 201 | if ((int) $connected_account['id'] !== (int) $to_delete_connected_account['id']) { |
| 202 | $to_update[$connected_account['id']] = $connected_account; |
| 203 | } |
| 204 | } |
| 205 | update_connected_accounts($to_update); |
| 206 | CFF_Db::delete_source_by_id($to_delete_connected_account['id']); |
| 207 | $manager = new SB_Facebook_Data_Manager(); |
| 208 | $manager->delete_caches(); |
| 209 | } |
| 210 | |
| 211 | /** |
| 212 | * Update the app permission revoked status. |
| 213 | * |
| 214 | * @param array $cff_statuses_option The option value. |
| 215 | * @param bool $is_revoked The revoke status. |
| 216 | * |
| 217 | * @return void |
| 218 | */ |
| 219 | protected function update_app_permission_revoked_status($cff_statuses_option, $is_revoked) |
| 220 | { |
| 221 | if ($is_revoked) { |
| 222 | $cff_statuses_option[self::APP_PERMISSION_REVOKED_STATUS_KEY] = true; |
| 223 | } else { |
| 224 | unset($cff_statuses_option[self::APP_PERMISSION_REVOKED_STATUS_KEY]); |
| 225 | } |
| 226 | update_option(self::CFF_STATUSES_OPTION_KEY, $cff_statuses_option); |
| 227 | } |
| 228 | |
| 229 | /** |
| 230 | * Handles events before the deletion of old data. |
| 231 | * |
| 232 | * @param array $statuses |
| 233 | * |
| 234 | * @return void |
| 235 | */ |
| 236 | public function handle_event_before_delete_old_data($statuses) |
| 237 | { |
| 238 | $cff_statuses_option = get_option(self::CFF_STATUSES_OPTION_KEY, []); |
| 239 | if (!empty($cff_statuses_option[self::UNUSED_FEED_WARNING_EMAIL_SENT_STATUS_KEY])) { |
| 240 | return; |
| 241 | } |
| 242 | |
| 243 | if ($statuses['last_used'] < cff_get_current_time() - (14 * DAY_IN_SECONDS)) { |
| 244 | \cff_main()->cff_error_reporter->add_error( |
| 245 | 'unused_feed', |
| 246 | array( |
| 247 | __('Your Facebook feed has been not viewed in the last 14 days. Due to Facebook data privacy rules, all data for this feed will be deleted in 7 days time. To avoid automated data deletion, simply view the Facebook feed on your website within the next 7 days.', 'custom-facebook-feed') |
| 248 | ) |
| 249 | ); |
| 250 | $this->send_unused_feed_usage_notification_email(); |
| 251 | // Setting the flag to true so that the warning email is not sent again. |
| 252 | $cff_statuses_option[self::UNUSED_FEED_WARNING_EMAIL_SENT_STATUS_KEY] = true; |
| 253 | update_option(self::CFF_STATUSES_OPTION_KEY, $cff_statuses_option); |
| 254 | } |
| 255 | } |
| 256 | |
| 257 | /** |
| 258 | * Handles the reset of unused feed data for deletion. |
| 259 | * |
| 260 | * @return void |
| 261 | */ |
| 262 | public function handle_unused_feed_usage() |
| 263 | { |
| 264 | // Security Checks |
| 265 | check_ajax_referer('cff_nonce', 'cff_nonce'); |
| 266 | $cap = current_user_can('manage_custom_facebook_feed_options') ? 'manage_custom_facebook_feed_options' : 'manage_options'; |
| 267 | if (!current_user_can($cap)) { |
| 268 | wp_send_json_error(); // This auto-dies. |
| 269 | } |
| 270 | |
| 271 | \cff_main()->cff_error_reporter->remove_error('unused_feed'); |
| 272 | |
| 273 | // ############## |
| 274 | $manager = new SB_Facebook_Data_Manager(); |
| 275 | $manager->update_last_used(); |
| 276 | $cff_statuses_option = get_option(self::CFF_STATUSES_OPTION_KEY, []); |
| 277 | // Unset the flag to allow the warning email to be sent again. |
| 278 | unset($cff_statuses_option[self::UNUSED_FEED_WARNING_EMAIL_SENT_STATUS_KEY]); |
| 279 | update_option(self::CFF_STATUSES_OPTION_KEY, $cff_statuses_option); |
| 280 | |
| 281 | wp_send_json_success( |
| 282 | [ |
| 283 | 'message' => '<div style="margin-top: 10px;">' . esc_html__('Success! Your Facebook Feeds will continue to work normally.', 'custom-facebook-feed') . '</div>' |
| 284 | ] |
| 285 | ); |
| 286 | } |
| 287 | |
| 288 | /** |
| 289 | * Cleanup revoked account data. |
| 290 | * |
| 291 | * @param array $cff_statuses_option |
| 292 | * |
| 293 | * @return void |
| 294 | */ |
| 295 | public function cleanup_revoked_account($cff_statuses_option) |
| 296 | { |
| 297 | $this->update_app_permission_revoked_status($cff_statuses_option, false); |
| 298 | delete_option(self::REVOKE_PLATFORM_DATA_OPTION_KEY); |
| 299 | } |
| 300 | |
| 301 | /** |
| 302 | * Sends a notification email to the admin when the app permission is revoked. |
| 303 | * |
| 304 | * @return void |
| 305 | */ |
| 306 | protected function send_revoke_notification_email() |
| 307 | { |
| 308 | $link = admin_url('admin.php?page=cff-settings'); |
| 309 | |
| 310 | $title = __('There has been a problem with your Facebook Feed.', 'custom-facebook-feed'); |
| 311 | $bold = __('Action Required Within 7 Days', 'custom-facebook-feed'); |
| 312 | $site_url = sprintf('<a href="%s">%s<a/>', esc_url(home_url()), __('your website', 'custom-facebook-feed')); |
| 313 | $details = '<p>' . sprintf(__('An account admin has deauthorized the Smash Balloon app used to power the Facebook Feed plugin on %s. If the Facebook source is not reconnected within 7 days then all Facebook data will be automatically deleted on your website due to Facebook data privacy rules.', 'custom-facebook-feed'), $site_url) . '</p>'; |
| 314 | $settings_page = sprintf('<a href="%s">%s</a>', esc_url($link), esc_html__('Settings Page', 'custom-facebook-feed')); |
| 315 | $details .= '<p>' . sprintf(__('To prevent the automated deletion of data for the source, please reconnect your source for the Facebook Feed plugin %s within 7 days.', 'custom-facebook-feed'), $settings_page) . '</p>'; |
| 316 | $details .= '<p><a href="https://smashballoon.com/doc/action-required-within-7-days/?facebook&utm_campaign=facebook-pro&utm_source=permissionerror&utm_medium=email&utm_content=More Information" target="_blank" rel="noopener">' . __('More Information', 'custom-facebook-feed') . '</a></p>'; |
| 317 | |
| 318 | Email_Notification::send($title, $bold, $details); |
| 319 | } |
| 320 | |
| 321 | /** |
| 322 | * Sends a notification email to the admin when the feed has not been used for a while. |
| 323 | * |
| 324 | * @return void |
| 325 | */ |
| 326 | protected function send_unused_feed_usage_notification_email() |
| 327 | { |
| 328 | $title = __('There has been a problem with your Facebook Feed.', 'custom-facebook-feed'); |
| 329 | $bold = __('Action Required Within 7 Days', 'custom-facebook-feed'); |
| 330 | $site_url = sprintf('<a href="%s">%s<a/>', esc_url(home_url()), __('your website', 'custom-facebook-feed')); |
| 331 | $details = '<p>' . sprintf(__('An Facebook feed on %s has been not viewed in the last 14 days. Due to Facebook data privacy rules, all data for this feed will be deleted in 7 days time.', 'custom-facebook-feed'), $site_url) . '</p>'; |
| 332 | $details .= '<p>' . __('To avoid automated data deletion, simply view the Facebook feed on your website within the next 7 days.', 'custom-facebook-feed') . '</p>'; |
| 333 | Email_Notification::send($title, $bold, $details); |
| 334 | } |
| 335 | |
| 336 | /** |
| 337 | * Sends a notification email to the admin when the platform data has been deleted. |
| 338 | * |
| 339 | * @return void |
| 340 | */ |
| 341 | protected function send_platform_data_delete_notification_email() |
| 342 | { |
| 343 | $link = admin_url('admin.php?page=cff-settings'); |
| 344 | |
| 345 | $title = __('All Facebook Data has Been Removed', 'custom-facebook-feed'); |
| 346 | $bold = __('An account admin has deauthorized the Smash Balloon app used to power the Facebook Feed plugin.', 'custom-facebook-feed'); |
| 347 | $site_url = sprintf('<a href="%s">%s<a/>', esc_url(home_url()), __('your website', 'custom-facebook-feed')); |
| 348 | $details = '<p>' . sprintf(__('The page was not reconnected within the 7 day limit and all Facebook data was automatically deleted on %s due to Facebook data privacy rules.', 'custom-facebook-feed'), $site_url) . '</p>'; |
| 349 | $settings_page = sprintf('<a href="%s">%s</a>', esc_url($link), esc_html__('Settings Page', 'custom-facebook-feed')); |
| 350 | $details .= '<p>' . sprintf(__('To fix your feeds, reconnect all accounts that were in use on the Settings page.', 'custom-facebook-feed'), $settings_page) . '</p>'; |
| 351 | |
| 352 | Email_Notification::send($title, $bold, $details); |
| 353 | } |
| 354 | |
| 355 | /** |
| 356 | * Sends a notification email to the admin when the platform data has been deleted. |
| 357 | * |
| 358 | * @return void |
| 359 | */ |
| 360 | protected function platform_data_deleted_notice() |
| 361 | { |
| 362 | } |
| 363 | } |
| 364 |