WP Security Audit Log - Version 3.1.5

Version Description

Download this release

Release Info

Developer WPWhiteSecurity
Plugin Icon 128x128 WP Security Audit Log
Version 3.1.5
Comparing to
See all releases

Code changes from version 3.1.4 to 3.1.5

classes/AlertManager.php CHANGED
@@ -398,6 +398,40 @@ final class WSAL_AlertManager {
398
  return $this->_alerts;
399
  }
400
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401
  /**
402
  * Returns all supported alerts.
403
  *
398
  return $this->_alerts;
399
  }
400
 
401
+ /**
402
+ * Method: Returns array of alerts by category.
403
+ *
404
+ * @param string $category - Alerts category.
405
+ * @return WSAL_Alert[]
406
+ */
407
+ public function get_alerts_by_category( $category ) {
408
+ // Categorized alerts array.
409
+ $alerts = array();
410
+ foreach ( $this->_alerts as $alert ) {
411
+ if ( $category === $alert->catg ) {
412
+ $alerts[ $alert->type ] = $alert;
413
+ }
414
+ }
415
+ return $alerts;
416
+ }
417
+
418
+ /**
419
+ * Method: Returns array of alerts by sub-category.
420
+ *
421
+ * @param string $sub_category - Alerts sub-category.
422
+ * @return WSAL_Alert[]
423
+ */
424
+ public function get_alerts_by_sub_category( $sub_category ) {
425
+ // Sub-categorized alerts array.
426
+ $alerts = array();
427
+ foreach ( $this->_alerts as $alert ) {
428
+ if ( $sub_category === $alert->subcatg ) {
429
+ $alerts[ $alert->type ] = $alert;
430
+ }
431
+ }
432
+ return $alerts;
433
+ }
434
+
435
  /**
436
  * Returns all supported alerts.
437
  *
classes/Loggers/Database.php CHANGED
@@ -66,6 +66,13 @@ class WSAL_Loggers_Database extends WSAL_AbstractLogger {
66
  if ( 9999 !== $type ) {
67
  $this->AlertInject( $occ );
68
  }
 
 
 
 
 
 
 
69
  }
70
 
71
  /**
66
  if ( 9999 !== $type ) {
67
  $this->AlertInject( $occ );
68
  }
69
+
70
+ /**
71
+ * Fires immediately after an alert is logged.
72
+ *
73
+ * @since 3.1.2
74
+ */
75
+ do_action( 'wsal_logged_alert', $occ, $type, $data, $date, $siteid, $migrated );
76
  }
77
 
78
  /**
classes/Sensors/Content.php CHANGED
@@ -1053,6 +1053,18 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor {
1053
  $event = 2002;
1054
  }
1055
  if ( $event ) {
 
 
 
 
 
 
 
 
 
 
 
 
1056
  $editor_link = $this->GetEditorLink( $oldpost );
1057
  $this->plugin->alerts->Trigger(
1058
  $event, array(
1053
  $event = 2002;
1054
  }
1055
  if ( $event ) {
1056
+ if ( 2002 === $event ) {
1057
+ // Get Yoast alerts.
1058
+ $yoast_alerts = $this->plugin->alerts->get_alerts_by_sub_category( 'Yoast SEO' );
1059
+
1060
+ // Check all alerts.
1061
+ foreach ( $yoast_alerts as $alert_code => $alert ) {
1062
+ if ( $this->plugin->alerts->WillOrHasTriggered( $alert_code ) ) {
1063
+ return 0; // Return if any Yoast alert has or will trigger.
1064
+ }
1065
+ }
1066
+ }
1067
+
1068
  $editor_link = $this->GetEditorLink( $oldpost );
1069
  $this->plugin->alerts->Trigger(
1070
  $event, array(
classes/Sensors/Menus.php CHANGED
@@ -129,7 +129,7 @@ class WSAL_Sensors_Menus extends WSAL_AbstractSensor {
129
  $item_parent_id = $args['menu-item-parent-id'];
130
  $item_name = $old_menu_items[ $menu_item_db_id ]['title'];
131
  if ( $old_menu_items[ $menu_item_db_id ]['parent'] != $item_parent_id ) {
132
- $parent_name = $old_menu_items[ $item_parent_id ]['title'];
133
  $this->EventChangeSubItem( $item_name, $parent_name, $post_array['menu-name'] );
134
  }
135
  }
129
  $item_parent_id = $args['menu-item-parent-id'];
130
  $item_name = $old_menu_items[ $menu_item_db_id ]['title'];
131
  if ( $old_menu_items[ $menu_item_db_id ]['parent'] != $item_parent_id ) {
132
+ $parent_name = isset( $old_menu_items[ $item_parent_id ]['title'] ) ? $old_menu_items[ $item_parent_id ]['title'] : false;
133
  $this->EventChangeSubItem( $item_name, $parent_name, $post_array['menu-name'] );
134
  }
135
  }
classes/Sensors/System.php CHANGED
@@ -818,7 +818,7 @@ class WSAL_Sensors_System extends WSAL_AbstractSensor {
818
 
819
  // Request URL.
820
  $request_uri = filter_input( INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_URL );
821
- $url = site_url() . $request_uri;
822
 
823
  // Get option to log referrer.
824
  $log_referrer = $this->plugin->GetGlobalOption( 'log-404-referrer' );
@@ -898,7 +898,7 @@ class WSAL_Sensors_System extends WSAL_AbstractSensor {
898
 
899
  // Request URL.
900
  $request_uri = filter_input( INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_URL );
901
- $url = site_url() . $request_uri;
902
 
903
  // Get option to log referrer.
904
  $log_referrer = $this->plugin->GetGlobalOption( 'log-visitor-404-referrer' );
818
 
819
  // Request URL.
820
  $request_uri = filter_input( INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_URL );
821
+ $url = home_url() . $request_uri;
822
 
823
  // Get option to log referrer.
824
  $log_referrer = $this->plugin->GetGlobalOption( 'log-404-referrer' );
898
 
899
  // Request URL.
900
  $request_uri = filter_input( INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_URL );
901
+ $url = home_url() . $request_uri;
902
 
903
  // Get option to log referrer.
904
  $log_referrer = $this->plugin->GetGlobalOption( 'log-visitor-404-referrer' );
classes/Sensors/WooCommerce.php CHANGED
@@ -83,6 +83,13 @@ class WSAL_Sensors_WooCommerce extends WSAL_AbstractSensor {
83
  */
84
  protected $_old_data = null;
85
 
 
 
 
 
 
 
 
86
  /**
87
  * Old Product Stock Status.
88
  *
@@ -118,6 +125,95 @@ class WSAL_Sensors_WooCommerce extends WSAL_AbstractSensor {
118
 
119
  add_action( 'create_product_cat', array( $this, 'EventCategoryCreation' ), 10, 1 );
120
  /* add_action('edit_product_cat', array($this, 'EventCategoryChanged'), 10, 1); */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  }
122
 
123
  /**
@@ -149,10 +245,11 @@ class WSAL_Sensors_WooCommerce extends WSAL_AbstractSensor {
149
  && ! (isset( $post_array['action'] ) && 'autosave' == $post_array['action'] )
150
  ) {
151
  $post_id = intval( $post_array['post_ID'] );
152
- $this->_old_post = get_post( $post_id );
153
- $this->_old_link = get_post_permalink( $post_id, false, true );
154
- $this->_old_cats = $this->GetProductCategories( $this->_old_post );
155
- $this->_old_data = $this->GetProductData( $this->_old_post );
 
156
  $this->_old_stock_status = get_post_meta( $post_id, '_stock_status', true );
157
 
158
  $old_downloadable_files = get_post_meta( $post_id, '_downloadable_files', true );
@@ -173,7 +270,7 @@ class WSAL_Sensors_WooCommerce extends WSAL_AbstractSensor {
173
  * @param stdClass $oldpost - The old post.
174
  */
175
  public function EventChanged( $post_id, $newpost, $oldpost ) {
176
- if ( $this->CheckWooCommerce( $oldpost ) ) {
177
  $changes = 0 + $this->EventCreation( $oldpost, $newpost );
178
  if ( ! $changes ) {
179
  // Change Categories.
@@ -1200,12 +1297,48 @@ class WSAL_Sensors_WooCommerce extends WSAL_AbstractSensor {
1200
  * @return array $editor_link - Name and value link.
1201
  */
1202
  private function GetEditorLink( $post ) {
 
1203
  $name = 'EditorLinkProduct';
 
 
1204
  $value = get_edit_post_link( $post->ID );
1205
- $editor_link = array(
1206
- 'name' => $name,
1207
- 'value' => $value,
1208
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1209
  return $editor_link;
1210
  }
1211
 
83
  */
84
  protected $_old_data = null;
85
 
86
+ /**
87
+ * Old Product Stock Quantity.
88
+ *
89
+ * @var int
90
+ */
91
+ protected $_old_stock = null;
92
+
93
  /**
94
  * Old Product Stock Status.
95
  *
125
 
126
  add_action( 'create_product_cat', array( $this, 'EventCategoryCreation' ), 10, 1 );
127
  /* add_action('edit_product_cat', array($this, 'EventCategoryChanged'), 10, 1); */
128
+
129
+ // Detect live change in stock.
130
+ add_filter( 'woocommerce_order_item_quantity', array( $this, 'set_old_stock' ), 10, 3 );
131
+ add_action( 'woocommerce_product_set_stock', array( $this, 'product_stock_changed' ), 10, 1 );
132
+ }
133
+
134
+ /**
135
+ * Triggered before updating stock quantity on customer order.
136
+ *
137
+ * @param int $order_quantity - Order quantity.
138
+ * @param WC_Order $order - Order object.
139
+ * @param WC_Order_Item $item - Order item object.
140
+ * @return int - Order quantity.
141
+ */
142
+ public function set_old_stock( $order_quantity, $order, $item ) {
143
+ // Get product from order item.
144
+ $product = $item->get_product();
145
+
146
+ // Get product id.
147
+ $product_id_with_stock = $product->get_stock_managed_by_id();
148
+
149
+ // Get product with stock.
150
+ $product_with_stock = wc_get_product( $product_id_with_stock );
151
+
152
+ // Set stock attributes of the product.
153
+ $this->_old_stock = $product_with_stock->get_stock_quantity();
154
+ $this->_old_stock_status = $product_with_stock->get_stock_status();
155
+
156
+ // Return original stock quantity.
157
+ return $order_quantity;
158
+ }
159
+
160
+ /**
161
+ * Triggered when stock of a product is changed.
162
+ *
163
+ * @param WC_Product $product - WooCommerce product object.
164
+ */
165
+ public function product_stock_changed( $product ) {
166
+ // Return if current screen is admin panel.
167
+ if ( is_admin() ) {
168
+ return;
169
+ }
170
+
171
+ $old_stock = $this->_old_stock; // Get old stock quantity.
172
+ $new_stock = $product->get_stock_quantity(); // Get new stock quantity.
173
+ $old_stock_status = $this->_old_stock_status; // Get old stock status.
174
+ $new_stock_status = $product->get_stock_status(); // Get new stock status.
175
+ $product_id = $product->get_id(); // Get product id.
176
+ $product_title = $product->get_title(); // Get product title.
177
+
178
+ // Set post object.
179
+ $post = new stdClass();
180
+ $post->ID = $product_id;
181
+
182
+ // Set username.
183
+ $username = '';
184
+ if ( ! is_user_logged_in() ) {
185
+ $username = 'Website Visitor';
186
+ } else {
187
+ $username = wp_get_current_user()->user_login;
188
+ }
189
+
190
+ // If stock status has changed then trigger the alert.
191
+ if ( ( $old_stock_status && $new_stock_status ) && ( $old_stock_status !== $new_stock_status ) ) {
192
+ $editor_link = $this->GetEditorLink( $post );
193
+ $this->plugin->alerts->Trigger(
194
+ 9018, array(
195
+ 'ProductTitle' => $product_title,
196
+ 'OldStatus' => $this->GetStockStatusName( $old_stock_status ),
197
+ 'NewStatus' => $this->GetStockStatusName( $new_stock_status ),
198
+ 'Username' => $username,
199
+ $editor_link['name'] => $editor_link['value'],
200
+ )
201
+ );
202
+ }
203
+
204
+ // If stock has changed then trigger the alert.
205
+ if ( $old_stock !== $new_stock ) {
206
+ $editor_link = $this->GetEditorLink( $post );
207
+ $this->plugin->alerts->Trigger(
208
+ 9019, array(
209
+ 'ProductTitle' => $product_title,
210
+ 'OldValue' => ( ! empty( $old_stock ) ? $old_stock : 0 ),
211
+ 'NewValue' => $new_stock,
212
+ 'Username' => $username,
213
+ $editor_link['name'] => $editor_link['value'],
214
+ )
215
+ );
216
+ }
217
  }
218
 
219
  /**
245
  && ! (isset( $post_array['action'] ) && 'autosave' == $post_array['action'] )
246
  ) {
247
  $post_id = intval( $post_array['post_ID'] );
248
+ $this->_old_post = get_post( $post_id );
249
+ $this->_old_link = get_post_permalink( $post_id, false, true );
250
+ $this->_old_cats = $this->GetProductCategories( $this->_old_post );
251
+ $this->_old_data = $this->GetProductData( $this->_old_post );
252
+ $this->_old_stock = get_post_meta( $post_id, '_stock', true );
253
  $this->_old_stock_status = get_post_meta( $post_id, '_stock_status', true );
254
 
255
  $old_downloadable_files = get_post_meta( $post_id, '_downloadable_files', true );
270
  * @param stdClass $oldpost - The old post.
271
  */
272
  public function EventChanged( $post_id, $newpost, $oldpost ) {
273
+ if ( $this->CheckWooCommerce( $oldpost ) && is_admin() ) {
274
  $changes = 0 + $this->EventCreation( $oldpost, $newpost );
275
  if ( ! $changes ) {
276
  // Change Categories.
1297
  * @return array $editor_link - Name and value link.
1298
  */
1299
  private function GetEditorLink( $post ) {
1300
+ // Meta value key.
1301
  $name = 'EditorLinkProduct';
1302
+
1303
+ // Get editor post link URL.
1304
  $value = get_edit_post_link( $post->ID );
1305
+
1306
+ // If the URL is not empty then set values.
1307
+ if ( ! empty( $value ) ) {
1308
+ $editor_link = array(
1309
+ 'name' => $name, // Meta key.
1310
+ 'value' => $value, // Meta value.
1311
+ );
1312
+ } else {
1313
+ // Get post object.
1314
+ $post = get_post( $post->ID );
1315
+
1316
+ // Set URL action.
1317
+ if ( 'revision' === $post->post_type ) {
1318
+ $action = '';
1319
+ } else {
1320
+ $action = '&action=edit';
1321
+ }
1322
+
1323
+ // Get and check post type object.
1324
+ $post_type_object = get_post_type_object( $post->post_type );
1325
+ if ( ! $post_type_object ) {
1326
+ return;
1327
+ }
1328
+
1329
+ // Set editor link manually.
1330
+ if ( $post_type_object->_edit_link ) {
1331
+ $link = admin_url( sprintf( $post_type_object->_edit_link . $action, $post->ID ) );
1332
+ } else {
1333
+ $link = '';
1334
+ }
1335
+
1336
+ $editor_link = array(
1337
+ 'name' => $name, // Meta key.
1338
+ 'value' => $link, // Meta value.
1339
+ );
1340
+ }
1341
+
1342
  return $editor_link;
1343
  }
1344
 
classes/Sensors/YoastSEO.php ADDED
@@ -0,0 +1,792 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Sensor: Yoast SEO
4
+ *
5
+ * Yoast SEO sensor file.
6
+ *
7
+ * @package Wsal
8
+ * @since 3.2.0
9
+ */
10
+
11
+ // Exit if accessed directly.
12
+ if ( ! defined( 'ABSPATH' ) ) {
13
+ exit;
14
+ }
15
+
16
+ /**
17
+ * Support for Yoast SEO Plugin.
18
+ *
19
+ * @package Wsal
20
+ * @subpackage Sensors
21
+ */
22
+ class WSAL_Sensors_YoastSEO extends WSAL_AbstractSensor {
23
+
24
+ /**
25
+ * Post ID.
26
+ *
27
+ * @var int
28
+ */
29
+ private $post_id = 0;
30
+
31
+ /**
32
+ * Post Object.
33
+ *
34
+ * @var WP_Post
35
+ */
36
+ private $post;
37
+
38
+ /**
39
+ * SEO Post Data.
40
+ *
41
+ * @var array
42
+ */
43
+ private $post_seo_data = array(
44
+ '_yoast_wpseo_title' => '',
45
+ '_yoast_wpseo_metadesc' => '',
46
+ '_yoast_wpseo_focuskw' => '',
47
+ '_yst_is_cornerstone' => '',
48
+ '_yoast_wpseo_meta-robots-noindex' => '',
49
+ '_yoast_wpseo_meta-robots-nofollow' => '',
50
+ '_yoast_wpseo_meta-robots-adv' => '',
51
+ '_yoast_wpseo_canonical' => '',
52
+ );
53
+
54
+ /**
55
+ * Listening to events using hooks.
56
+ */
57
+ public function HookEvents() {
58
+ // Check if Yoast SEO file exists.
59
+ if ( ! is_plugin_active( 'wordpress-seo/wp-seo.php' ) ) {
60
+ return false;
61
+ }
62
+
63
+ // If user can edit post then hook this function.
64
+ if ( current_user_can( 'edit_posts' ) ) {
65
+ add_action( 'admin_init', array( $this, 'event_admin_init' ) );
66
+ }
67
+
68
+ // Yoast SEO option alerts.
69
+ add_action( 'updated_option', array( $this, 'yoast_options_trigger' ), 10, 3 );
70
+ }
71
+
72
+ /**
73
+ * Method: Admin Init Event.
74
+ */
75
+ public function event_admin_init() {
76
+ // Load old data, if applicable.
77
+ $this->retrieve_post_data();
78
+
79
+ // Check for settings change.
80
+ $this->check_seo_data_change();
81
+ }
82
+
83
+ /**
84
+ * Method: Retrieve Post ID.
85
+ */
86
+ protected function retrieve_post_data() {
87
+ // Filter POST global array.
88
+ $post_array = filter_input_array( INPUT_POST );
89
+
90
+ if ( isset( $post_array['post_ID'] )
91
+ && isset( $post_array['_wpnonce'] )
92
+ && ! wp_verify_nonce( $post_array['_wpnonce'], 'update-post_' . $post_array['post_ID'] ) ) {
93
+ return false;
94
+ }
95
+
96
+ if ( isset( $post_array ) && isset( $post_array['post_ID'] )
97
+ && ! ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE)
98
+ && ! ( isset( $post_array['action'] ) && 'autosave' === $post_array['action'] )
99
+ ) {
100
+ $this->post_id = intval( $post_array['post_ID'] );
101
+ $this->post = get_post( $this->post_id );
102
+ $this->set_post_seo_data();
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Method: Set Post SEO Data.
108
+ */
109
+ private function set_post_seo_data() {
110
+ // Set post SEO meta data.
111
+ $this->post_seo_data = array(
112
+ '_yoast_wpseo_title' => get_post_meta( $this->post_id, '_yoast_wpseo_title', true ),
113
+ '_yoast_wpseo_metadesc' => get_post_meta( $this->post_id, '_yoast_wpseo_metadesc', true ),
114
+ '_yoast_wpseo_focuskw' => get_post_meta( $this->post_id, '_yoast_wpseo_focuskw', true ),
115
+ '_yst_is_cornerstone' => get_post_meta( $this->post_id, '_yst_is_cornerstone', true ),
116
+ '_yoast_wpseo_meta-robots-noindex' => get_post_meta( $this->post_id, '_yoast_wpseo_meta-robots-noindex', true ),
117
+ '_yoast_wpseo_meta-robots-nofollow' => get_post_meta( $this->post_id, '_yoast_wpseo_meta-robots-nofollow', true ),
118
+ '_yoast_wpseo_meta-robots-adv' => get_post_meta( $this->post_id, '_yoast_wpseo_meta-robots-adv', true ),
119
+ '_yoast_wpseo_canonical' => get_post_meta( $this->post_id, '_yoast_wpseo_canonical', true ),
120
+ );
121
+ }
122
+
123
+ /**
124
+ * Method: Get Post SEO Data.
125
+ *
126
+ * @param string $key – Meta Key.
127
+ * @return mix
128
+ */
129
+ protected function get_post_seo_data( $key = '' ) {
130
+ // If empty key then return false.
131
+ if ( empty( $key ) ) {
132
+ return false;
133
+ }
134
+
135
+ // Set prefix of meta data.
136
+ $prefix = '_yoast_wpseo_';
137
+
138
+ // Check prefix.
139
+ if ( 'is_cornerstone' === $key ) {
140
+ $prefix = '_yst_';
141
+ }
142
+
143
+ // Option to retrieve.
144
+ $option = $prefix . $key;
145
+
146
+ // If key exists and is not empty then return value.
147
+ if ( isset( $this->post_seo_data[ $option ] ) && ! empty( $this->post_seo_data[ $option ] ) ) {
148
+ return $this->post_seo_data[ $option ];
149
+ } else {
150
+ // Return false if key doesn't exists or its value is empty.
151
+ return false;
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Get editor link.
157
+ *
158
+ * @param stdClass $post_id - Post id.
159
+ * @return array $editor_link - Name and value link.
160
+ */
161
+ private function get_editor_link( $post_id ) {
162
+ $value = get_edit_post_link( $post_id );
163
+ $editor_link = array(
164
+ 'name' => 'EditorLinkPost',
165
+ 'value' => $value,
166
+ );
167
+ return $editor_link;
168
+ }
169
+
170
+ /**
171
+ * Method: Detect Post SEO Data Change.
172
+ */
173
+ protected function check_seo_data_change() {
174
+ // Set filter input args.
175
+ $filter_input_args = array(
176
+ 'post_ID' => FILTER_VALIDATE_INT,
177
+ '_wpnonce' => FILTER_SANITIZE_STRING,
178
+ 'action' => FILTER_SANITIZE_STRING,
179
+ 'yoast_wpseo_title' => FILTER_SANITIZE_STRING,
180
+ 'yoast_wpseo_metadesc' => FILTER_SANITIZE_STRING,
181
+ 'yoast_wpseo_focuskw' => FILTER_SANITIZE_STRING,
182
+ '_yst_is_cornerstone' => FILTER_VALIDATE_INT,
183
+ 'yoast_wpseo_meta-robots-noindex' => FILTER_VALIDATE_INT,
184
+ 'yoast_wpseo_meta-robots-nofollow' => FILTER_VALIDATE_INT,
185
+ 'yoast_wpseo_meta-robots-adv' => array(
186
+ 'flags' => FILTER_REQUIRE_ARRAY,
187
+ ),
188
+ 'yoast_wpseo_canonical' => FILTER_VALIDATE_URL,
189
+ );
190
+
191
+ // Filter POST global array.
192
+ $post_array = filter_input_array( INPUT_POST, $filter_input_args );
193
+
194
+ if ( isset( $post_array['post_ID'] )
195
+ && 'editpost' === $post_array['action']
196
+ && isset( $post_array['_wpnonce'] )
197
+ && wp_verify_nonce( $post_array['_wpnonce'], 'update-post_' . $post_array['post_ID'] ) ) {
198
+ // Check SEO data changes and alert if changed.
199
+ $this->check_title_change( $post_array['yoast_wpseo_title'] ); // Title.
200
+ $this->check_desc_change( $post_array['yoast_wpseo_metadesc'] ); // Meta description.
201
+ $this->check_robots_index_change( $post_array['yoast_wpseo_meta-robots-noindex'] ); // Meta Robots Index.
202
+ $this->check_robots_follow_change( $post_array['yoast_wpseo_meta-robots-nofollow'] ); // Meta Robots Follow.
203
+ $this->check_robots_advanced_change( $post_array['yoast_wpseo_meta-robots-adv'] ); // Meta Robots Advanced.
204
+ $this->check_canonical_url_change( $post_array['yoast_wpseo_canonical'] ); // Canonical URL.
205
+ $this->check_focus_keys_change( $post_array['yoast_wpseo_focuskw'] ); // Focus keywords.
206
+ $this->check_cornerstone_change( $post_array['_yst_is_cornerstone'] ); // Cornerstone.
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Method: Check SEO Title Change.
212
+ *
213
+ * @param string $title – Changed SEO Title.
214
+ */
215
+ protected function check_title_change( $title ) {
216
+ // Get old title value.
217
+ $old_title = $this->get_post_seo_data( 'title' );
218
+
219
+ // If old and new values are empty then don't log the alert.
220
+ if ( empty( $old_title ) && empty( $title ) ) {
221
+ return;
222
+ }
223
+
224
+ // If title is changed then log alert.
225
+ if ( $old_title !== $title ) {
226
+ $editor_link = $this->get_editor_link( $this->post_id );
227
+ $this->plugin->alerts->Trigger(
228
+ 8801, array(
229
+ 'PostID' => $this->post->ID,
230
+ 'PostType' => $this->post->post_type,
231
+ 'PostTitle' => $this->post->post_title,
232
+ 'PostStatus' => $this->post->post_status,
233
+ 'PostDate' => $this->post->post_date,
234
+ 'PostUrl' => get_permalink( $this->post->ID ),
235
+ 'OldSEOTitle' => $old_title,
236
+ 'NewSEOTitle' => $title,
237
+ $editor_link['name'] => $editor_link['value'],
238
+ )
239
+ );
240
+ }
241
+ }
242
+
243
+ /**
244
+ * Method: Check SEO Meta Description Change.
245
+ *
246
+ * @param string $desc – Changed SEO Meta Description.
247
+ */
248
+ protected function check_desc_change( $desc ) {
249
+ // Get old desc value.
250
+ $old_desc = $this->get_post_seo_data( 'metadesc' );
251
+
252
+ // If old and new values are empty then don't log the alert.
253
+ if ( empty( $old_desc ) && empty( $desc ) ) {
254
+ return;
255
+ }
256
+
257
+ // If desc is changed then log alert.
258
+ if ( $old_desc !== $desc ) {
259
+ $editor_link = $this->get_editor_link( $this->post_id );
260
+ $this->plugin->alerts->Trigger(
261
+ 8802, array(
262
+ 'PostID' => $this->post->ID,
263
+ 'PostType' => $this->post->post_type,
264
+ 'PostTitle' => $this->post->post_title,
265
+ 'PostStatus' => $this->post->post_status,
266
+ 'PostDate' => $this->post->post_date,
267
+ 'PostUrl' => get_permalink( $this->post->ID ),
268
+ 'old_desc' => $old_desc,
269
+ 'new_desc' => $desc,
270
+ $editor_link['name'] => $editor_link['value'],
271
+ )
272
+ );
273
+ }
274
+ }
275
+
276
+ /**
277
+ * Method: Check Meta Robots Index Change.
278
+ *
279
+ * @param string $index – Changed Meta Robots Index.
280
+ */
281
+ protected function check_robots_index_change( $index ) {
282
+ // Get old title value.
283
+ $old_index = (int) $this->get_post_seo_data( 'meta-robots-noindex' );
284
+
285
+ if ( 1 === $old_index ) {
286
+ $old_index = 'No';
287
+ } else {
288
+ $old_index = 'Yes';
289
+ }
290
+
291
+ if ( 1 === $index ) {
292
+ $index = 'No';
293
+ } else {
294
+ $index = 'Yes';
295
+ }
296
+
297
+ // If setting is changed then log alert.
298
+ if ( $old_index !== $index ) {
299
+ $editor_link = $this->get_editor_link( $this->post_id );
300
+ $this->plugin->alerts->Trigger(
301
+ 8803, array(
302
+ 'PostID' => $this->post->ID,
303
+ 'PostType' => $this->post->post_type,
304
+ 'PostTitle' => $this->post->post_title,
305
+ 'PostStatus' => $this->post->post_status,
306
+ 'PostDate' => $this->post->post_date,
307
+ 'PostUrl' => get_permalink( $this->post->ID ),
308
+ 'OldStatus' => $old_index,
309
+ 'NewStatus' => $index,
310
+ $editor_link['name'] => $editor_link['value'],
311
+ )
312
+ );
313
+ }
314
+ }
315
+
316
+ /**
317
+ * Method: Check Meta Robots Follow Change.
318
+ *
319
+ * @param string $follow – Changed Meta Robots Follow.
320
+ */
321
+ protected function check_robots_follow_change( $follow ) {
322
+ // Get old title value.
323
+ $old_follow = (int) $this->get_post_seo_data( 'meta-robots-nofollow' );
324
+
325
+ if ( 1 === $old_follow ) {
326
+ $old_follow = 'Disabled';
327
+ } else {
328
+ $old_follow = 'Enabled';
329
+ }
330
+
331
+ if ( 1 === $follow ) {
332
+ $follow = 'Disabled';
333
+ } else {
334
+ $follow = 'Enabled';
335
+ }
336
+
337
+ // If setting is changed then log alert.
338
+ if ( $old_follow !== $follow ) {
339
+ $editor_link = $this->get_editor_link( $this->post_id );
340
+ $this->plugin->alerts->Trigger(
341
+ 8804, array(
342
+ 'PostID' => $this->post->ID,
343
+ 'PostType' => $this->post->post_type,
344
+ 'PostTitle' => $this->post->post_title,
345
+ 'PostStatus' => $this->post->post_status,
346
+ 'PostDate' => $this->post->post_date,
347
+ 'PostUrl' => get_permalink( $this->post->ID ),
348
+ 'NewStatus' => $follow,
349
+ $editor_link['name'] => $editor_link['value'],
350
+ )
351
+ );
352
+ }
353
+ }
354
+
355
+ /**
356
+ * Method: Check Meta Robots Advanced Change.
357
+ *
358
+ * @param array $advanced – Advanced array.
359
+ */
360
+ protected function check_robots_advanced_change( $advanced ) {
361
+ // Convert to string.
362
+ if ( is_array( $advanced ) ) {
363
+ $advanced = implode( ',', $advanced );
364
+ }
365
+
366
+ // Get old title value.
367
+ $old_adv = $this->get_post_seo_data( 'meta-robots-adv' );
368
+
369
+ // If old and new values are empty then don't log the alert.
370
+ if ( empty( $old_title ) && '-' === $advanced ) {
371
+ return;
372
+ }
373
+
374
+ // If setting is changed then log alert.
375
+ if ( $old_adv !== $advanced ) {
376
+ $editor_link = $this->get_editor_link( $this->post_id );
377
+ $this->plugin->alerts->Trigger(
378
+ 8805, array(
379
+ 'PostID' => $this->post->ID,
380
+ 'PostType' => $this->post->post_type,
381
+ 'PostTitle' => $this->post->post_title,
382
+ 'PostStatus' => $this->post->post_status,
383
+ 'PostDate' => $this->post->post_date,
384
+ 'PostUrl' => get_permalink( $this->post->ID ),
385
+ 'NewStatus' => $advanced,
386
+ $editor_link['name'] => $editor_link['value'],
387
+ )
388
+ );
389
+ }
390
+ }
391
+
392
+ /**
393
+ * Method: Check Canonical URL Change.
394
+ *
395
+ * @param string $canonical_url – Changed Canonical URL.
396
+ */
397
+ protected function check_canonical_url_change( $canonical_url ) {
398
+ // Get old title value.
399
+ $old_url = $this->get_post_seo_data( 'canonical' );
400
+
401
+ // If title is changed then log alert.
402
+ if ( $old_url !== $canonical_url ) {
403
+ $editor_link = $this->get_editor_link( $this->post_id );
404
+ $this->plugin->alerts->Trigger(
405
+ 8806, array(
406
+ 'PostID' => $this->post->ID,
407
+ 'PostType' => $this->post->post_type,
408
+ 'PostTitle' => $this->post->post_title,
409
+ 'PostStatus' => $this->post->post_status,
410
+ 'PostDate' => $this->post->post_date,
411
+ 'PostUrl' => get_permalink( $this->post->ID ),
412
+ 'OldCanonicalUrl' => $old_url,
413
+ 'NewCanonicalUrl' => $canonical_url,
414
+ $editor_link['name'] => $editor_link['value'],
415
+ )
416
+ );
417
+ }
418
+ }
419
+
420
+ /**
421
+ * Method: Check Focus Keywords Change.
422
+ *
423
+ * @param string $focus_keys – Changed Focus Keywords.
424
+ */
425
+ protected function check_focus_keys_change( $focus_keys ) {
426
+ // Get old title value.
427
+ $old_focus_keys = $this->get_post_seo_data( 'focuskw' );
428
+
429
+ // If old and new values are empty then don't log the alert.
430
+ if ( empty( $old_focus_keys ) && empty( $focus_keys ) ) {
431
+ return;
432
+ }
433
+
434
+ // If title is changed then log alert.
435
+ if ( $old_focus_keys !== $focus_keys ) {
436
+ $editor_link = $this->get_editor_link( $this->post_id );
437
+ $this->plugin->alerts->Trigger(
438
+ 8807, array(
439
+ 'PostID' => $this->post->ID,
440
+ 'PostType' => $this->post->post_type,
441
+ 'PostTitle' => $this->post->post_title,
442
+ 'PostStatus' => $this->post->post_status,
443
+ 'PostDate' => $this->post->post_date,
444
+ 'PostUrl' => get_permalink( $this->post->ID ),
445
+ 'old_keywords' => $old_focus_keys,
446
+ 'new_keywords' => $focus_keys,
447
+ $editor_link['name'] => $editor_link['value'],
448
+ )
449
+ );
450
+ }
451
+ }
452
+
453
+ /**
454
+ * Method: Check Cornerstone Change.
455
+ *
456
+ * @param string $cornerstone – Changed Cornerstone.
457
+ */
458
+ protected function check_cornerstone_change( $cornerstone ) {
459
+ // Get old title value.
460
+ $old_cornerstone = (int) $this->get_post_seo_data( 'is_cornerstone' );
461
+ $cornerstone = (int) $cornerstone;
462
+
463
+ if ( 1 === $cornerstone ) {
464
+ $alert_status = 'Enabled';
465
+ } else {
466
+ $alert_status = 'Disabled';
467
+ }
468
+
469
+ // If setting is changed then log alert.
470
+ if ( $old_cornerstone !== $cornerstone ) {
471
+ $editor_link = $this->get_editor_link( $this->post_id );
472
+ $this->plugin->alerts->Trigger(
473
+ 8808, array(
474
+ 'PostID' => $this->post->ID,
475
+ 'PostType' => $this->post->post_type,
476
+ 'PostTitle' => $this->post->post_title,
477
+ 'PostStatus' => $this->post->post_status,
478
+ 'PostDate' => $this->post->post_date,
479
+ 'PostUrl' => get_permalink( $this->post->ID ),
480
+ 'Status' => $alert_status,
481
+ $editor_link['name'] => $editor_link['value'],
482
+ )
483
+ );
484
+ }
485
+ }
486
+
487
+ /**
488
+ * Method: Yoast SEO options trigger.
489
+ *
490
+ * @param string $option – Option name.
491
+ * @param mix $old_value – Option old value.
492
+ * @param mix $new_value – Option new value.
493
+ */
494
+ public function yoast_options_trigger( $option, $old_value, $new_value ) {
495
+ // Detect the SEO option.
496
+ if ( 'wpseo_titles' === $option || 'wpseo' === $option ) {
497
+ // WPSEO Title Alerts.
498
+ if ( 'wpseo_titles' === $option ) {
499
+ // Title Separator.
500
+ if ( $old_value['separator'] !== $new_value['separator'] ) {
501
+ $this->yoast_setting_change_alert( 'separator', $old_value['separator'], $new_value['separator'] );
502
+ }
503
+
504
+ // Homepage Title.
505
+ if ( $old_value['title-home-wpseo'] !== $new_value['title-home-wpseo'] ) {
506
+ $this->yoast_setting_change_alert( 'title-home-wpseo', $old_value['title-home-wpseo'], $new_value['title-home-wpseo'] );
507
+ }
508
+
509
+ // Homepage Meta Description.
510
+ if ( $old_value['metadesc-home-wpseo'] !== $new_value['metadesc-home-wpseo'] ) {
511
+ $this->yoast_setting_change_alert( 'metadesc-home-wpseo', $old_value['metadesc-home-wpseo'], $new_value['metadesc-home-wpseo'] );
512
+ }
513
+
514
+ // Company or Person.
515
+ if ( $old_value['company_or_person'] !== $new_value['company_or_person'] ) {
516
+ $this->yoast_setting_change_alert( 'company_or_person', $old_value['company_or_person'], $new_value['company_or_person'] );
517
+ }
518
+
519
+ // Get public post types.
520
+ $post_types = get_post_types( array( 'public' => true ) );
521
+
522
+ // For each post type check show, title, and description changes.
523
+ foreach ( $post_types as $type ) {
524
+ if ( isset( $old_value[ "noindex-$type" ] ) ) {
525
+ // Show Post Type in search results.
526
+ if ( $old_value[ "noindex-$type" ] !== $new_value[ "noindex-$type" ] ) {
527
+ $this->yoast_setting_switch_alert( "noindex-$type", $new_value[ "noindex-$type" ] );
528
+ }
529
+
530
+ // Post Type Title Template.
531
+ if ( $old_value[ "title-$type" ] !== $new_value[ "title-$type" ] ) {
532
+ $this->yoast_setting_change_alert( "title-$type", $old_value[ "title-$type" ], $new_value[ "title-$type" ] );
533
+ }
534
+
535
+ // Post Type Meta Description Template.
536
+ if ( $old_value[ "metadesc-$type" ] !== $new_value[ "metadesc-$type" ] ) {
537
+ $this->yoast_setting_change_alert( "metadesc-$type", $old_value[ "metadesc-$type" ], $new_value[ "metadesc-$type" ] );
538
+ }
539
+
540
+ // Show Date.
541
+ if ( $old_value[ "showdate-$type" ] !== $new_value[ "showdate-$type" ] ) {
542
+ $this->yoast_setting_switch_alert( "showdate-$type", $new_value[ "showdate-$type" ] );
543
+ }
544
+
545
+ // Show Meta box.
546
+ if ( $old_value[ "display-metabox-pt-$type" ] !== $new_value[ "display-metabox-pt-$type" ] ) {
547
+ $this->yoast_setting_switch_alert( "display-metabox-pt-$type", $new_value[ "display-metabox-pt-$type" ] );
548
+ }
549
+ }
550
+ }
551
+ }
552
+
553
+ // Webmaster URL alerts.
554
+ if ( 'wpseo' === $option ) {
555
+ // SEO analysis.
556
+ if ( $old_value['keyword_analysis_active'] !== $new_value['keyword_analysis_active'] ) {
557
+ $this->yoast_setting_switch_alert( 'keyword_analysis_active', $new_value['keyword_analysis_active'] );
558
+ }
559
+
560
+ // Readability analysis.
561
+ if ( $old_value['content_analysis_active'] !== $new_value['content_analysis_active'] ) {
562
+ $this->yoast_setting_switch_alert( 'content_analysis_active', $new_value['content_analysis_active'] );
563
+ }
564
+
565
+ // Cornerstone Content.
566
+ if ( $old_value['enable_cornerstone_content'] !== $new_value['enable_cornerstone_content'] ) {
567
+ $this->yoast_setting_switch_alert( 'enable_cornerstone_content', $new_value['enable_cornerstone_content'] );
568
+ }
569
+
570
+ // Text Link Counter.
571
+ if ( $old_value['enable_text_link_counter'] !== $new_value['enable_text_link_counter'] ) {
572
+ $this->yoast_setting_switch_alert( 'enable_text_link_counter', $new_value['enable_text_link_counter'] );
573
+ }
574
+
575
+ // XML Sitemaps.
576
+ if ( $old_value['enable_xml_sitemap'] !== $new_value['enable_xml_sitemap'] ) {
577
+ $this->yoast_setting_switch_alert( 'enable_xml_sitemap', $new_value['enable_xml_sitemap'] );
578
+ }
579
+
580
+ // Ryte integration.
581
+ if ( $old_value['onpage_indexability'] !== $new_value['onpage_indexability'] ) {
582
+ $this->yoast_setting_switch_alert( 'onpage_indexability', $new_value['onpage_indexability'] );
583
+ }
584
+
585
+ // Admin bar menu.
586
+ if ( $old_value['enable_admin_bar_menu'] !== $new_value['enable_admin_bar_menu'] ) {
587
+ $this->yoast_setting_switch_alert( 'enable_admin_bar_menu', $new_value['enable_admin_bar_menu'] );
588
+ }
589
+
590
+ // Advanced settings for authors.
591
+ if ( $old_value['disableadvanced_meta'] !== $new_value['disableadvanced_meta'] ) {
592
+ $this->yoast_setting_switch_alert( 'disableadvanced_meta', $new_value['disableadvanced_meta'] );
593
+ }
594
+ }
595
+ }
596
+ }
597
+
598
+ /**
599
+ * Method: Trigger Yoast Setting Change Alerts.
600
+ *
601
+ * @param string $key – Setting key.
602
+ * @param string $old_value – Old setting value.
603
+ * @param string $new_value – New setting value.
604
+ */
605
+ private function yoast_setting_change_alert( $key, $old_value, $new_value ) {
606
+ // Return if key is empty.
607
+ if ( empty( $key ) ) {
608
+ return;
609
+ }
610
+
611
+ // Return if both old and new values are empty.
612
+ if ( empty( $old_value ) && empty( $new_value ) ) {
613
+ return;
614
+ }
615
+
616
+ // Alert arguments.
617
+ $alert_args = array(
618
+ 'old' => $old_value, // Old value.
619
+ 'new' => $new_value, // New value.
620
+ );
621
+
622
+ // Find title-* in the key.
623
+ if ( false !== strpos( $key, 'title-' ) ) {
624
+ $seo_post_type = str_replace( 'title-', '', $key );
625
+ $seo_post_type = ucfirst( $seo_post_type );
626
+ $seo_post_type .= 's';
627
+
628
+ // Set alert meta data.
629
+ $alert_args['SEOPostType'] = $seo_post_type;
630
+ }
631
+
632
+ // Find metadesc-* in the key.
633
+ if ( false !== strpos( $key, 'metadesc-' ) ) {
634
+ $seo_post_type = str_replace( 'metadesc-', '', $key );
635
+ $seo_post_type = ucfirst( $seo_post_type );
636
+ $seo_post_type .= 's';
637
+
638
+ // Set alert meta data.
639
+ $alert_args['SEOPostType'] = $seo_post_type;
640
+ }
641
+
642
+ // Set alert code to null initially.
643
+ $alert_code = null;
644
+
645
+ // Detect alert code for setting.
646
+ switch ( $key ) {
647
+ case 'separator':
648
+ $alert_code = 8809;
649
+ break;
650
+
651
+ case 'title-home-wpseo':
652
+ $alert_code = 8810;
653
+ break;
654
+
655
+ case 'metadesc-home-wpseo':
656
+ $alert_code = 8811;
657
+ break;
658
+
659
+ case 'company_or_person':
660
+ $alert_code = 8812;
661
+ break;
662
+
663
+ case strpos( $key, 'title-' ):
664
+ $alert_code = 8814;
665
+ break;
666
+
667
+ case strpos( $key, 'metadesc-' ):
668
+ $alert_code = 8822;
669
+ break;
670
+
671
+ default:
672
+ break;
673
+ }
674
+
675
+ // Trigger the alert.
676
+ if ( ! empty( $alert_code ) ) {
677
+ $this->plugin->alerts->Trigger( $alert_code, $alert_args );
678
+ }
679
+ }
680
+
681
+ /**
682
+ * Method: Trigger Yoast Enable/Disable Setting Alerts.
683
+ *
684
+ * @param string $key – Setting index to alert.
685
+ * @param mix $new_value – Setting new value.
686
+ */
687
+ private function yoast_setting_switch_alert( $key, $new_value ) {
688
+ // If key is empty, then return.
689
+ if ( empty( $key ) ) {
690
+ return;
691
+ }
692
+
693
+ // Check and set status.
694
+ $status = (int) $new_value;
695
+
696
+ // Alert arguments.
697
+ $alert_args = array();
698
+
699
+ // Find noindex-* in the key.
700
+ if ( false !== strpos( $key, 'noindex-' ) ) {
701
+ $seo_post_type = str_replace( 'noindex-', '', $key );
702
+ $seo_post_type = ucfirst( $seo_post_type );
703
+ $seo_post_type .= 's';
704
+
705
+ // Set alert meta data.
706
+ $alert_args['SEOPostType'] = $seo_post_type;
707
+ $status = ( 1 === $status ) ? 0 : 1;
708
+ }
709
+
710
+ // Find showdate-* in the key.
711
+ if ( false !== strpos( $key, 'showdate-' ) ) {
712
+ $seo_post_type = str_replace( 'showdate-', '', $key );
713
+ $seo_post_type = ucfirst( $seo_post_type );
714
+ $seo_post_type .= 's';
715
+
716
+ // Set alert meta data.
717
+ $alert_args['SEOPostType'] = $seo_post_type;
718
+ }
719
+
720
+ // Find display-metabox-pt-* in the key.
721
+ if ( false !== strpos( $key, 'display-metabox-pt-' ) ) {
722
+ $seo_post_type = str_replace( 'display-metabox-pt-', '', $key );
723
+ $seo_post_type = ucfirst( $seo_post_type );
724
+ $seo_post_type .= 's';
725
+
726
+ // Set alert meta data.
727
+ $alert_args['SEOPostType'] = $seo_post_type;
728
+ }
729
+
730
+ $status = ( 1 === $status ) ? 'Enabled' : 'Disabled';
731
+ $alert_args['Status'] = $status;
732
+
733
+ // Set alert code to NULL initially.
734
+ $alert_code = null;
735
+
736
+ // Add switch case to set the alert code.
737
+ switch ( $key ) {
738
+ case strpos( $key, 'noindex-' ):
739
+ $alert_code = 8813;
740
+ break;
741
+
742
+ case 'keyword_analysis_active':
743
+ $alert_code = 8815;
744
+ break;
745
+
746
+ case 'content_analysis_active':
747
+ $alert_code = 8816;
748
+ break;
749
+
750
+ case 'enable_cornerstone_content':
751
+ $alert_code = 8817;
752
+ break;
753
+
754
+ case 'enable_text_link_counter':
755
+ $alert_code = 8818;
756
+ break;
757
+
758
+ case 'enable_xml_sitemap':
759
+ $alert_code = 8819;
760
+ break;
761
+
762
+ case 'onpage_indexability':
763
+ $alert_code = 8820;
764
+ break;
765
+
766
+ case 'enable_admin_bar_menu':
767
+ $alert_code = 8821;
768
+ break;
769
+
770
+ case strpos( $key, 'showdate-' ):
771
+ $alert_code = 8823;
772
+ break;
773
+
774
+ case strpos( $key, 'display-metabox-pt-' ):
775
+ $alert_code = 8824;
776
+ break;
777
+
778
+ case strpos( $key, 'disableadvanced_meta' ):
779
+ $alert_code = 8825;
780
+ break;
781
+
782
+ default:
783
+ break;
784
+ }
785
+
786
+ // Trigger the alert.
787
+ if ( ! empty( $alert_code ) ) {
788
+ $this->plugin->alerts->Trigger( $alert_code, $alert_args );
789
+ }
790
+ }
791
+ }
792
+
classes/Views/AuditLog.php CHANGED
@@ -480,7 +480,16 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView {
480
  */
481
  public function Header() {
482
  add_thickbox();
483
- wp_enqueue_style( 'darktooltip', $this->_plugin->GetBaseUrl() . '/css/darktooltip.css', array(), '' );
 
 
 
 
 
 
 
 
 
484
  wp_enqueue_style(
485
  'auditlog',
486
  $this->_plugin->GetBaseUrl() . '/css/auditlog.css',
@@ -494,8 +503,18 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView {
494
  */
495
  public function Footer() {
496
  wp_enqueue_script( 'jquery' );
497
- wp_enqueue_script( 'darktooltip', $this->_plugin->GetBaseUrl() . '/js/jquery.darktooltip.js', array( 'jquery' ), '' );
 
 
 
 
 
 
 
 
498
  wp_enqueue_script( 'suggest' );
 
 
499
  wp_enqueue_script(
500
  'auditlog',
501
  $this->_plugin->GetBaseUrl() . '/js/auditlog.js',
480
  */
481
  public function Header() {
482
  add_thickbox();
483
+
484
+ // Darktooltip styles.
485
+ wp_enqueue_style(
486
+ 'darktooltip',
487
+ $this->_plugin->GetBaseUrl() . '/css/darktooltip.css',
488
+ array(),
489
+ '0.4.0'
490
+ );
491
+
492
+ // Audit log styles.
493
  wp_enqueue_style(
494
  'auditlog',
495
  $this->_plugin->GetBaseUrl() . '/css/auditlog.css',
503
  */
504
  public function Footer() {
505
  wp_enqueue_script( 'jquery' );
506
+
507
+ // Darktooltip js.
508
+ wp_enqueue_script(
509
+ 'darktooltip', // Identifier.
510
+ $this->_plugin->GetBaseUrl() . '/js/jquery.darktooltip.js', // Script location.
511
+ array( 'jquery' ), // Depends on jQuery.
512
+ '0.4.0' // Script version.
513
+ );
514
+
515
  wp_enqueue_script( 'suggest' );
516
+
517
+ // Audit log script.
518
  wp_enqueue_script(
519
  'auditlog',
520
  $this->_plugin->GetBaseUrl() . '/js/auditlog.js',
defaults.php CHANGED
@@ -505,7 +505,7 @@ function wsaldefaults_wsal_init( WpSecurityAuditLog $wsal ) {
505
  array( 9016, E_WARNING, __( 'User changed type of a price', 'wp-security-audit-log' ), __( 'Changed the %PriceType% of the product %ProductTitle% from %OldPrice% to %NewPrice%. View the product: %EditorLinkProduct%.', 'wp-security-audit-log' ) ),
506
  array( 9017, E_WARNING, __( 'User changed the SKU of a product', 'wp-security-audit-log' ), __( 'Changed the SKU of the product %ProductTitle% from %OldSku% to %NewSku%. View the product: %EditorLinkProduct%.', 'wp-security-audit-log' ) ),
507
  array( 9018, E_CRITICAL, __( 'User changed the stock status of a product', 'wp-security-audit-log' ), __( 'Changed the stock status of the product %ProductTitle% from %OldStatus% to %NewStatus%. View the product: %EditorLinkProduct%.', 'wp-security-audit-log' ) ),
508
- array( 9019, E_WARNING, __( 'User changed the stock quantity', 'wp-security-audit-log' ), __( 'Changed the stock quantity from %OldValue% to %NewValue% of the product %ProductTitle%. View the product: %EditorLinkProduct%', 'wp-security-audit-log' ) ),
509
  array( 9020, E_WARNING, __( 'User set a product type', 'wp-security-audit-log' ), __( 'Set the product %ProductTitle% as %Type%. View the product: %EditorLinkProduct%.', 'wp-security-audit-log' ) ),
510
  array( 9021, E_WARNING, __( 'User changed the weight of a product', 'wp-security-audit-log' ), __( 'Changed the weight of the product %ProductTitle% from %OldWeight% to %NewWeight%. View the product: %EditorLinkProduct%.', 'wp-security-audit-log' ) ),
511
  array( 9022, E_WARNING, __( 'User changed the dimensions of a product', 'wp-security-audit-log' ), __( 'Changed the %DimensionType% dimensions of the product %ProductTitle% from %OldDimension% to %NewDimension%. View the product: %EditorLinkProduct%.', 'wp-security-audit-log' ) ),
@@ -522,6 +522,33 @@ function wsaldefaults_wsal_init( WpSecurityAuditLog $wsal ) {
522
  array( 9033, E_CRITICAL, __( 'User Enabled/Disabled guest checkout', 'wp-security-audit-log' ), __( '%Status% guest checkout in WooCommerce.', 'wp-security-audit-log' ) ),
523
  array( 9034, E_CRITICAL, __( 'User Enabled/Disabled cash on delivery', 'wp-security-audit-log' ), __( '%Status% the option Enable cash on delivery in WooCommerce.', 'wp-security-audit-log' ) ),
524
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
525
  ),
526
  )
527
  );
505
  array( 9016, E_WARNING, __( 'User changed type of a price', 'wp-security-audit-log' ), __( 'Changed the %PriceType% of the product %ProductTitle% from %OldPrice% to %NewPrice%. View the product: %EditorLinkProduct%.', 'wp-security-audit-log' ) ),
506
  array( 9017, E_WARNING, __( 'User changed the SKU of a product', 'wp-security-audit-log' ), __( 'Changed the SKU of the product %ProductTitle% from %OldSku% to %NewSku%. View the product: %EditorLinkProduct%.', 'wp-security-audit-log' ) ),
507
  array( 9018, E_CRITICAL, __( 'User changed the stock status of a product', 'wp-security-audit-log' ), __( 'Changed the stock status of the product %ProductTitle% from %OldStatus% to %NewStatus%. View the product: %EditorLinkProduct%.', 'wp-security-audit-log' ) ),
508
+ array( 9019, E_WARNING, __( 'User changed the stock quantity', 'wp-security-audit-log' ), __( 'Changed the stock quantity of the product %ProductTitle% from %OldValue% to %NewValue%. View the product: %EditorLinkProduct%', 'wp-security-audit-log' ) ),
509
  array( 9020, E_WARNING, __( 'User set a product type', 'wp-security-audit-log' ), __( 'Set the product %ProductTitle% as %Type%. View the product: %EditorLinkProduct%.', 'wp-security-audit-log' ) ),
510
  array( 9021, E_WARNING, __( 'User changed the weight of a product', 'wp-security-audit-log' ), __( 'Changed the weight of the product %ProductTitle% from %OldWeight% to %NewWeight%. View the product: %EditorLinkProduct%.', 'wp-security-audit-log' ) ),
511
  array( 9022, E_WARNING, __( 'User changed the dimensions of a product', 'wp-security-audit-log' ), __( 'Changed the %DimensionType% dimensions of the product %ProductTitle% from %OldDimension% to %NewDimension%. View the product: %EditorLinkProduct%.', 'wp-security-audit-log' ) ),
522
  array( 9033, E_CRITICAL, __( 'User Enabled/Disabled guest checkout', 'wp-security-audit-log' ), __( '%Status% guest checkout in WooCommerce.', 'wp-security-audit-log' ) ),
523
  array( 9034, E_CRITICAL, __( 'User Enabled/Disabled cash on delivery', 'wp-security-audit-log' ), __( '%Status% the option Enable cash on delivery in WooCommerce.', 'wp-security-audit-log' ) ),
524
  ),
525
+ __( 'Yoast SEO', 'wp-security-audit-log' ) => array(
526
+ array( 8801, E_NOTICE, __( 'User changed title of a SEO post', 'wp-security-audit-log' ), __( 'Changed the SEO title of the %PostStatus% %PostType% from %OldSEOTitle% to %NewSEOTitle%. %EditorLinkPost%.', 'wp-security-audit-log' ) ),
527
+ array( 8802, E_NOTICE, __( 'User changed the meta description of a SEO post', 'wp-security-audit-log' ), __( 'Changed the Meta description of the %PostStatus% %PostType% titled %PostTitle% from %old_desc% to %new_desc%. %EditorLinkPost%.', 'wp-security-audit-log' ) ),
528
+ array( 8803, E_NOTICE, __( 'User changed setting to allow search engines to show post in search results of a SEO post', 'wp-security-audit-log' ), __( 'Changed the setting to allow search engines to show post in search results from %OldStatus% to %NewStatus% in the %PostStatus% %PostType% titled %PostTitle%. %EditorLinkPost%.', 'wp-security-audit-log' ) ),
529
+ array( 8804, E_NOTICE, __( 'User Enabled/Disabled the option for search engine to follow links of a SEO post', 'wp-security-audit-log' ), __( '%NewStatus% the option for search engine to follow links in the %PostType% titled %PostTitle%. %EditorLinkPost%.', 'wp-security-audit-log' ) ),
530
+ array( 8805, E_NOTICE, __( 'User set the meta robots advanced setting of a SEO post', 'wp-security-audit-log' ), __( 'Set the Meta Robots Advanced setting to %NewStatus% in the %PostStatus% %PostType% titled %PostTitle%. %EditorLinkPost%.', 'wp-security-audit-log' ) ),
531
+ array( 8806, E_NOTICE, __( 'User changed the canonical URL of a SEO post', 'wp-security-audit-log' ), __( 'Changed the Canonical URL of the %PostStatus% %PostType% titled %PostTitle% from %OldCanonicalUrl% to %NewCanonicalUrl%. %EditorLinkPost%.', 'wp-security-audit-log' ) ),
532
+ array( 8807, E_NOTICE, __( 'User changed the focus keyword of a SEO post', 'wp-security-audit-log' ), __( 'Changed the focus keyword of the %PostStatus% %PostType% titled %PostTitle% from %old_keywords% to %new_keywords%. %EditorLinkPost%.', 'wp-security-audit-log' ) ),
533
+ array( 8808, E_NOTICE, __( 'User Enabled/Disabled the option Cornerston Content of a SEO post', 'wp-security-audit-log' ), __( '%Status% the option Cornerston Content on the %PostStatus% %PostType% titled %PostTitle%. %EditorLinkPost%.', 'wp-security-audit-log' ) ),
534
+ array( 8809, E_WARNING, __( 'User changed the Title Separator setting', 'wp-security-audit-log' ), __( 'Changed the Title Separator from %old% to %new% in the Yoast SEO plugin settings.', 'wp-security-audit-log' ) ),
535
+ array( 8810, E_WARNING, __( 'User changed the Homepage Title setting', 'wp-security-audit-log' ), __( 'Changed the Homepage Title from %old% to %new% in the Yoast SEO plugin settings.', 'wp-security-audit-log' ) ),
536
+ array( 8811, E_WARNING, __( 'User changed the Homepage Meta description setting', 'wp-security-audit-log' ), __( 'Changed the Homepage Meta description from %old% to %new% in the Yoast SEO plugin settings.', 'wp-security-audit-log' ) ),
537
+ array( 8812, E_WARNING, __( 'User changed the Company or Person setting', 'wp-security-audit-log' ), __( 'Changed the Company or Person setting from %old% to %new% in the YOAST SEO plugin settings.', 'wp-security-audit-log' ) ),
538
+ array( 8813, E_WARNING, __( 'User Enabled/Disabled the option Show Posts/Pages in Search Results in the Yoast SEO plugin settings', 'wp-security-audit-log' ), __( '%Status% the option Show %SEOPostType% in Search Results in the Yoast SEO plugin settings.', 'wp-security-audit-log' ) ),
539
+ array( 8814, E_WARNING, __( 'User changed the Posts/Pages title template in the Yoast SEO plugin settings', 'wp-security-audit-log' ), __( 'Changed the %SEOPostType% title template from %old% to %new% in the Yoast SEO plugin settings.', 'wp-security-audit-log' ) ),
540
+ array( 8815, E_WARNING, __( 'User Enabled/Disabled SEO analysis in the Yoast SEO plugin settings', 'wp-security-audit-log' ), __( '%Status% SEO analysis in the Yoast SEO plugin settings.', 'wp-security-audit-log' ) ),
541
+ array( 8816, E_WARNING, __( 'User Enabled/Disabled readability analysis in the Yoast SEO plugin settings', 'wp-security-audit-log' ), __( '%Status% Readability analysis in the Yoast SEO plugin settings.', 'wp-security-audit-log' ) ),
542
+ array( 8817, E_WARNING, __( 'User Enabled/Disabled cornerstone content in the Yoast SEO plugin settings', 'wp-security-audit-log' ), __( '%Status% Cornerstone content in the Yoast SEO plugin settings.', 'wp-security-audit-log' ) ),
543
+ array( 8818, E_WARNING, __( 'User Enabled/Disabled the text link counter in the Yoast SEO plugin settings', 'wp-security-audit-log' ), __( '%Status% the Text link counter in the Yoast SEO plugin settings.', 'wp-security-audit-log' ) ),
544
+ array( 8819, E_WARNING, __( 'User Enabled/Disabled XML sitemaps in the Yoast SEO plugin settings', 'wp-security-audit-log' ), __( '%Status% XML Sitemaps in the Yoast SEO plugin settings.', 'wp-security-audit-log' ) ),
545
+ array( 8820, E_WARNING, __( 'User Enabled/Disabled ryte integration in the Yoast SEO plugin settings', 'wp-security-audit-log' ), __( '%Status% Ryte Integration in the Yoast SEO plugin settings.', 'wp-security-audit-log' ) ),
546
+ array( 8821, E_WARNING, __( 'User Enabled/Disabled the admin bar menu in the Yoast SEO plugin settings', 'wp-security-audit-log' ), __( '%Status% the Admin bar menu in the Yoast SEO plugin settings.', 'wp-security-audit-log' ) ),
547
+ array( 8822, E_WARNING, __( 'User changed the Posts/Pages meta description template in the Yoast SEO plugin settings', 'wp-security-audit-log' ), __( 'Changed the %SEOPostType% meta description template from %old% to %new% in the Yoast SEO plugin settings.', 'wp-security-audit-log' ) ),
548
+ array( 8823, E_WARNING, __( 'User set the option Date in Snippet Preview for Posts/Pages in the Yoast SEO plugin settings', 'wp-security-audit-log' ), __( '%Status% the option Date in Snippet Preview for %SEOPostType% in the Yoast SEO plugin settings.', 'wp-security-audit-log' ) ),
549
+ array( 8824, E_WARNING, __( 'User set the option Yoast SEO Meta Box for Posts/Pages in the Yoast SEO plugin settings', 'wp-security-audit-log' ), __( '%Status% the option Yoast SEO Meta Box for %SEOPostType% in the Yoast SEO plugin settings.', 'wp-security-audit-log' ) ),
550
+ array( 8825, E_WARNING, __( 'User Enabled/Disabled the advanced settings for authors in the Yoast SEO plugin settings', 'wp-security-audit-log' ), __( '%Status% the advanced settings for authors in the Yoast SEO settings.', 'wp-security-audit-log' ) ),
551
+ ),
552
  ),
553
  )
554
  );
readme.txt CHANGED
@@ -6,7 +6,7 @@ License URI: http://www.gnu.org/licenses/gpl.html
6
  Tags: wordpress security plugin, wordpress security audit log, audit log, event log wordpress, wordpress user tracking, wordpress activity log, wordpress audit, security event log, audit trail, wordpress security monitor, wordpress admin, wordpress admin monitoring, user activity, admin, multisite, dashboard, notification, wordpress monitoring, email notification, wordpress email alerts, tracking, user tracking, user activity report, wordpress audit trail
7
  Requires at least: 3.6
8
  Tested up to: 4.9.4
9
- Stable tag: 3.1.4
10
  Requires PHP: 5.3
11
 
12
  An easy to use and comprehensive monitoring & activity log solution that keeps a log of all changes & user activity on your WordPress site.
@@ -179,12 +179,45 @@ Please refer to our [Support & Documentation pages](https://www.wpsecurityauditl
179
 
180
  == Changelog ==
181
 
182
- = 3.1.4(2018-03-23) =
183
-
184
- * **Improvements**
185
- * Reintroduced the functionality to download 404 error log files from activity log.
186
-
187
- * **Bug Fix**
188
- * Freemius addressed mutliple issues in SDK for WordPress multisite (updated SDK)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
 
190
  Refer to the [WP Security Audit Log change log](https://www.wpsecurityauditlog.com/plugin-change-log/) page for the complete change log.
6
  Tags: wordpress security plugin, wordpress security audit log, audit log, event log wordpress, wordpress user tracking, wordpress activity log, wordpress audit, security event log, audit trail, wordpress security monitor, wordpress admin, wordpress admin monitoring, user activity, admin, multisite, dashboard, notification, wordpress monitoring, email notification, wordpress email alerts, tracking, user tracking, user activity report, wordpress audit trail
7
  Requires at least: 3.6
8
  Tested up to: 4.9.4
9
+ Stable tag: 3.1.5
10
  Requires PHP: 5.3
11
 
12
  An easy to use and comprehensive monitoring & activity log solution that keeps a log of all changes & user activity on your WordPress site.
179
 
180
  == Changelog ==
181
 
182
+ = 3.1.5(2018-04-04) =
183
+
184
+ * **New Features**
185
+ * Terminate all logged in sessions button.
186
+ * Setting to [configure automatic termination of idle logged in sessions](https://www.wpsecurityauditlog.com/support-documentation/automatically-terminate-idle-wordpress-users-sessions/).
187
+ * Text search with filters for logged in sessions (first & last, username, role, email).
188
+ * New settings to [limit the number of simultaneous logged in sessions per user in WordPress](https://www.wpsecurityauditlog.com/support-documentation/managing-multiple-same-wordpress-user-sessions/#limiting-simultaneous).
189
+ * New settings to [configure logged in sessions override in WordPress](https://www.wpsecurityauditlog.com/support-documentation/managing-multiple-same-wordpress-user-sessions/#allow-override).
190
+
191
+ * **New activity log for Yoast SEO**
192
+ * 8801: Changed the SEO title
193
+ * 8802: Modified SEO description
194
+ * 8803: Changed the option Allow Search engine to show post in search results
195
+ * 8804: Changed the option Search Engine follow links
196
+ * 8805: Set the Meta Robots Advanced setting
197
+ * 8806: Changed the canonical URL
198
+ * 8807: Changed the focus keyword
199
+ * 8808: Changed the cornerstone article option
200
+ * 8809: Changed title separator in Yoast SEO plugin settings
201
+ * 8810: Changed the Homepage Title
202
+ * 8811: Changed the Homepage Meta description
203
+ * 8812: Changed the Knowledge Graph setting
204
+ * 8813: Changed the option Show Posts / Pages / Attachments in Search Results
205
+ * 8814: Changed the Posts / pages / Attachments title template
206
+ * 8815: Changed the SEO Analysis setting
207
+ * 8816: changed the Readability analysis setting
208
+ * 8817: Change the cornerstone content plugin setting
209
+ * 8818: Changed the Text link counter setting
210
+ * 8819: Changed XML Sitemaps setting
211
+ * 8820: Changed Ryte Integration setting
212
+ * 8821: Changed the Admin bar menu setting
213
+ * 8822: Changed the Posts / Pages / Attachments meta description template
214
+ * 8823: Changed the option Date in Snippet Preview for Posts / Pages / Attachments
215
+ * 8824: Changed the option Yoast SEO Metabox for Posts / Pages / Attachments
216
+ * 8825: Changed the setting Security: no advanced settings for authors
217
+
218
+ * **Plugin improvements**
219
+ * List of logged in users uses displays either first & last name or username.
220
+ * Automated changes in WooCommerce product stock quantity and statuses done by plugins or order placements are now recorded.
221
+ * Added checks for when the plugin cannot retrieve the latest change of a session to report in the logged in users section.
222
 
223
  Refer to the [WP Security Audit Log change log](https://www.wpsecurityauditlog.com/plugin-change-log/) page for the complete change log.
wp-security-audit-log.php CHANGED
@@ -4,7 +4,7 @@
4
  * Plugin URI: http://www.wpsecurityauditlog.com/
5
  * Description: Identify WordPress security issues before they become a problem. Keep track of everything happening on your WordPress including WordPress users activity. Similar to Windows Event Log and Linux Syslog, WP Security Audit Log generates a security alert for everything that happens on your WordPress blogs and websites. Use the Audit Log Viewer included in the plugin to see all the security alerts.
6
  * Author: WP White Security
7
- * Version: 3.1.4
8
  * Text Domain: wp-security-audit-log
9
  * Author URI: http://www.wpsecurityauditlog.com/
10
  * License: GPL2
@@ -54,7 +54,7 @@ if ( ! function_exists( 'wsal_freemius' ) ) {
54
  *
55
  * @var string
56
  */
57
- public $version = '3.1.4';
58
 
59
  // Plugin constants.
60
  const PLG_CLS_PRFX = 'WSAL_';
4
  * Plugin URI: http://www.wpsecurityauditlog.com/
5
  * Description: Identify WordPress security issues before they become a problem. Keep track of everything happening on your WordPress including WordPress users activity. Similar to Windows Event Log and Linux Syslog, WP Security Audit Log generates a security alert for everything that happens on your WordPress blogs and websites. Use the Audit Log Viewer included in the plugin to see all the security alerts.
6
  * Author: WP White Security
7
+ * Version: 3.1.5
8
  * Text Domain: wp-security-audit-log
9
  * Author URI: http://www.wpsecurityauditlog.com/
10
  * License: GPL2
54
  *
55
  * @var string
56
  */
57
+ public $version = '3.1.5';
58
 
59
  // Plugin constants.
60
  const PLG_CLS_PRFX = 'WSAL_';